mirror of
https://github.com/matrix-org/dendrite.git
synced 2025-01-31 08:04:28 -06:00
fix complexity
This commit is contained in:
parent
016500b3f4
commit
dd3fd3d3d3
|
@ -172,7 +172,12 @@ func makeUrlPreviewHandler(
|
||||||
if err != nil {
|
if err != nil {
|
||||||
activeUrlPreviewRequest.Error = err
|
activeUrlPreviewRequest.Error = err
|
||||||
} else {
|
} else {
|
||||||
defer resp.Body.Close()
|
defer func() {
|
||||||
|
err := resp.Body.Close()
|
||||||
|
if err != nil {
|
||||||
|
logger.WithError(err).Error("unable to close response body")
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
var result *types.UrlPreview
|
var result *types.UrlPreview
|
||||||
var err, err2 error
|
var err, err2 error
|
||||||
|
@ -349,66 +354,23 @@ func downloadAndStoreImage(
|
||||||
}
|
}
|
||||||
|
|
||||||
tmpFileName := filepath.Join(string(tmpDir), "content")
|
tmpFileName := filepath.Join(string(tmpDir), "content")
|
||||||
// Check if the file is an image.
|
fileType, err := detectFileType(tmpFileName, logger)
|
||||||
// Otherwise return an error
|
|
||||||
file, err := os.Open(string(tmpFileName))
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.WithError(err).Error("unable to open file")
|
logger.WithError(err).Error("unable to detect file type")
|
||||||
return nil, 0, 0, err
|
return nil, width, height, err
|
||||||
}
|
|
||||||
defer file.Close()
|
|
||||||
|
|
||||||
buf := make([]byte, 512)
|
|
||||||
|
|
||||||
_, err = file.Read(buf)
|
|
||||||
if err != nil {
|
|
||||||
logger.WithError(err).Error("unable to read file")
|
|
||||||
return nil, 0, 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
fileType := http.DetectContentType(buf)
|
|
||||||
if !strings.HasPrefix(fileType, "image") {
|
|
||||||
logger.WithField("contentType", fileType).Debugf("uploaded file is not an image or can not be thumbnailed, not generating thumbnails")
|
|
||||||
return nil, 0, 0, ErrorUnsupportedContentType
|
|
||||||
}
|
}
|
||||||
logger.WithField("contentType", fileType).Debug("uploaded file is an image")
|
logger.WithField("contentType", fileType).Debug("uploaded file is an image")
|
||||||
|
|
||||||
// Create a thumbnail from the image
|
// Create a thumbnail from the image
|
||||||
thumbnailPath := tmpFileName + ".thumbnail"
|
thumbnailPath := tmpFileName + ".thumbnail"
|
||||||
|
|
||||||
// Check if we have too many thumbnail generators running
|
width, height, err = createThumbnail(types.Path(tmpFileName), types.Path(thumbnailPath), types.ThumbnailSize(cfg.UrlPreviewThumbnailSize),
|
||||||
// If so, wait up to 30 seconds for one to finish
|
hash, activeThumbnailGeneration, cfg.MaxThumbnailGenerators, logger)
|
||||||
timeout := time.After(30 * time.Second)
|
if err != nil {
|
||||||
for {
|
if errors.Is(err, thumbnailer.ErrThumbnailTooLarge) {
|
||||||
if len(activeThumbnailGeneration.PathToResult) < cfg.MaxThumbnailGenerators {
|
thumbnailPath = tmpFileName
|
||||||
activeThumbnailGeneration.Lock()
|
} else {
|
||||||
activeThumbnailGeneration.PathToResult[string(hash)] = nil
|
return nil, width, height, err
|
||||||
activeThumbnailGeneration.Unlock()
|
|
||||||
|
|
||||||
defer func() {
|
|
||||||
activeThumbnailGeneration.Lock()
|
|
||||||
delete(activeThumbnailGeneration.PathToResult, string(hash))
|
|
||||||
activeThumbnailGeneration.Unlock()
|
|
||||||
}()
|
|
||||||
|
|
||||||
width, height, err = thumbnailer.CreateThumbnailFromFile(types.Path(tmpFileName), types.Path(thumbnailPath), types.ThumbnailSize(cfg.UrlPreviewThumbnailSize), logger)
|
|
||||||
if err != nil {
|
|
||||||
if errors.Is(err, thumbnailer.ErrThumbnailTooLarge) {
|
|
||||||
thumbnailPath = tmpFileName
|
|
||||||
} else {
|
|
||||||
logger.WithError(err).Error("unable to create thumbnail")
|
|
||||||
return nil, 0, 0, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
select {
|
|
||||||
case <-timeout:
|
|
||||||
logger.Error("timed out waiting for thumbnail generator")
|
|
||||||
return nil, 0, 0, ErrorTimeoutThumbnailGenerator
|
|
||||||
default:
|
|
||||||
time.Sleep(time.Second)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -462,6 +424,41 @@ func downloadAndStoreImage(
|
||||||
return mediaMetaData, width, height, nil
|
return mediaMetaData, width, height, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func createThumbnail(src types.Path, dst types.Path, size types.ThumbnailSize, hash types.Base64Hash, activeThumbnailGeneration *types.ActiveThumbnailGeneration, maxThumbnailGenerators int, logger *log.Entry) (int, int, error) {
|
||||||
|
// Check if we have too many thumbnail generators running
|
||||||
|
// If so, wait up to 30 seconds for one to finish
|
||||||
|
timeout := time.After(30 * time.Second)
|
||||||
|
for {
|
||||||
|
if len(activeThumbnailGeneration.PathToResult) < maxThumbnailGenerators {
|
||||||
|
|
||||||
|
activeThumbnailGeneration.Lock()
|
||||||
|
activeThumbnailGeneration.PathToResult[string(hash)] = nil
|
||||||
|
activeThumbnailGeneration.Unlock()
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
activeThumbnailGeneration.Lock()
|
||||||
|
delete(activeThumbnailGeneration.PathToResult, string(hash))
|
||||||
|
activeThumbnailGeneration.Unlock()
|
||||||
|
}()
|
||||||
|
|
||||||
|
width, height, err := thumbnailer.CreateThumbnailFromFile(src, dst, size, logger)
|
||||||
|
if err != nil {
|
||||||
|
logger.WithError(err).Error("unable to create thumbnail")
|
||||||
|
return 0, 0, err
|
||||||
|
}
|
||||||
|
return width, height, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
select {
|
||||||
|
case <-timeout:
|
||||||
|
logger.Error("timed out waiting for thumbnail generator")
|
||||||
|
return 0, 0, ErrorTimeoutThumbnailGenerator
|
||||||
|
default:
|
||||||
|
time.Sleep(time.Second)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func storeUrlPreviewResponse(ctx context.Context, cfg *config.MediaAPI, db storage.Database, user userapi.Device, hash types.Base64Hash, preview *types.UrlPreview, logger *log.Entry) error {
|
func storeUrlPreviewResponse(ctx context.Context, cfg *config.MediaAPI, db storage.Database, user userapi.Device, hash types.Base64Hash, preview *types.UrlPreview, logger *log.Entry) error {
|
||||||
|
|
||||||
jsonPreview, err := json.Marshal(preview)
|
jsonPreview, err := json.Marshal(preview)
|
||||||
|
@ -532,6 +529,37 @@ func loadUrlPreviewResponse(ctx context.Context, cfg *config.MediaAPI, db storag
|
||||||
return nil, ErrNoMetadataFound
|
return nil, ErrNoMetadataFound
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func detectFileType(filePath string, logger *log.Entry) (string, error) {
|
||||||
|
// Check if the file is an image.
|
||||||
|
// Otherwise return an error
|
||||||
|
file, err := os.Open(string(filePath))
|
||||||
|
if err != nil {
|
||||||
|
logger.WithError(err).Error("unable to open image file")
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
err := file.Close()
|
||||||
|
if err != nil {
|
||||||
|
logger.WithError(err).Error("unable to close image file")
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
buf := make([]byte, 512)
|
||||||
|
|
||||||
|
_, err = file.Read(buf)
|
||||||
|
if err != nil {
|
||||||
|
logger.WithError(err).Error("unable to read file")
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
fileType := http.DetectContentType(buf)
|
||||||
|
if !strings.HasPrefix(fileType, "image") {
|
||||||
|
logger.WithField("contentType", fileType).Debugf("uploaded file is not an image")
|
||||||
|
return "", ErrorUnsupportedContentType
|
||||||
|
}
|
||||||
|
return fileType, nil
|
||||||
|
}
|
||||||
|
|
||||||
func getHashFromString(s string) types.Base64Hash {
|
func getHashFromString(s string) types.Base64Hash {
|
||||||
hasher := sha256.New()
|
hasher := sha256.New()
|
||||||
hasher.Write([]byte(s))
|
hasher.Write([]byte(s))
|
||||||
|
|
Loading…
Reference in a new issue