From c2d666b43477ea7042b574ad940c508216cb0e83 Mon Sep 17 00:00:00 2001 From: Gabriel Arakaki Giovanini Date: Mon, 3 Jul 2023 23:13:04 +0200 Subject: fix: Fix content type Content type was always being set to `text/html`. Also swap lib for processing thumbnail for something that accepts HEIC. --- cmd/server/main.go | 2 +- go.mod | 3 +-- go.sum | 37 ++----------------------------- pkg/ext/middleware.go | 4 +++- pkg/fileop/file.go | 5 ++++- pkg/fileop/thumbnail.go | 49 ++++++++++++++++++----------------------- pkg/worker/list_processor.go | 13 +++++++++++ pkg/worker/thumbnail_scanner.go | 7 +++--- 8 files changed, 50 insertions(+), 70 deletions(-) diff --git a/cmd/server/main.go b/cmd/server/main.go index 1bd445c..224b37a 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -120,7 +120,7 @@ func main() { // worker var ( - serverWorker = worker.NewServerWorker(&fasthttp.Server{Handler: r.Handler}) + serverWorker = worker.NewServerWorker(&fasthttp.Server{Handler: r.Handler, NoDefaultContentType: true}) fileWorker = worker.NewWorkerFromChanProcessor[string]( fileScanner, scheduler, diff --git a/go.mod b/go.mod index a473a48..d94e64b 100644 --- a/go.mod +++ b/go.mod @@ -4,9 +4,9 @@ go 1.19 require ( github.com/barasher/go-exiftool v1.10.0 - github.com/disintegration/imaging v1.6.2 github.com/fasthttp/router v1.4.19 github.com/google/go-cmp v0.5.9 + github.com/h2non/bimg v1.1.9 github.com/sirupsen/logrus v1.9.2 github.com/spf13/pflag v1.0.5 github.com/valyala/fasthttp v1.47.0 @@ -30,7 +30,6 @@ require ( github.com/mattn/go-sqlite3 v1.14.16 // indirect github.com/savsgio/gotils v0.0.0-20230208104028-c358bd845dee // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect - golang.org/x/image v0.8.0 // indirect golang.org/x/mod v0.10.0 // indirect golang.org/x/sys v0.8.0 // indirect golang.org/x/text v0.10.0 // indirect diff --git a/go.sum b/go.sum index 8694f64..f50562c 100644 --- a/go.sum +++ b/go.sum @@ -5,8 +5,6 @@ github.com/barasher/go-exiftool v1.10.0/go.mod h1:F9s/a3uHSM8YniVfwF+sbQUtP8Gmh9 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c= -github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4= github.com/fasthttp/router v1.4.19 h1:RLE539IU/S4kfb4MP56zgP0TIBU9kEg0ID9GpWO0vqk= github.com/fasthttp/router v1.4.19/go.mod h1:+Fh3YOd8x1+he6ZS+d2iUDBH9MGGZ1xQFUor0DE9rKE= github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= @@ -17,6 +15,8 @@ github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0kt github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/h2non/bimg v1.1.9 h1:WH20Nxko9l/HFm4kZCA3Phbgu2cbHvYzxwxn9YROEGg= +github.com/h2non/bimg v1.1.9/go.mod h1:R3+UiYwkK4rQl6KVFTOFJHitgLbZXBZNFh2cv3AEbp8= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk= @@ -50,51 +50,18 @@ github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6Kllzaw github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasthttp v1.47.0 h1:y7moDoxYzMooFpT5aHgNgVOQDrS3qlkfiP9mDtGGK9c= github.com/valyala/fasthttp v1.47.0/go.mod h1:k2zXd82h/7UZc3VOdJ2WaUqt1uZ/XpXAfE9i+HBC3lA= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.8.0 h1:pd9TJtTueMTVQXzk8E2XESSMQDj/U7OUu0PqJqPXQjQ= golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE= -golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.8.0 h1:agUcRXV/+w6L9ryntYYsF2x9fQTMd4T8fiiYXAVW6Jg= -golang.org/x/image v0.8.0/go.mod h1:PwLxp3opCYg4WR2WO9P0L6ESnsD6bLTWcw8zanLMVFM= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk= golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.10.0 h1:UpjohKhiEgNc0CSauXmwYftY1+LlaC75SJwh0SgCX58= golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.9.3 h1:Gn1I8+64MsuTb/HpH+LmQtNas23LhUVr3rYZ0eKuaMM= golang.org/x/tools v0.9.3/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/pkg/ext/middleware.go b/pkg/ext/middleware.go index d255c6d..c83b998 100644 --- a/pkg/ext/middleware.go +++ b/pkg/ext/middleware.go @@ -12,7 +12,9 @@ import ( func HTML(next fasthttp.RequestHandler) fasthttp.RequestHandler { return func(ctx *fasthttp.RequestCtx) { - ctx.Response.Header.SetContentType("text/html") + if len(ctx.Request.Header.ContentType()) > 0 { + ctx.Response.Header.SetContentType("text/html") + } next(ctx) } } diff --git a/pkg/fileop/file.go b/pkg/fileop/file.go index 07c08e5..10e2202 100644 --- a/pkg/fileop/file.go +++ b/pkg/fileop/file.go @@ -12,6 +12,9 @@ func GetHashFromPath(path string) string { } func IsMimeTypeSupported(mimetype string) bool { - return strings.HasPrefix(mimetype, "video") && + if mimetype == "image/svg+xml" { + return false + } + return strings.HasPrefix(mimetype, "video") || strings.HasPrefix(mimetype, "image") } diff --git a/pkg/fileop/thumbnail.go b/pkg/fileop/thumbnail.go index 32f6064..fcdfa12 100644 --- a/pkg/fileop/thumbnail.go +++ b/pkg/fileop/thumbnail.go @@ -1,60 +1,55 @@ package fileop import ( - "image" - "image/jpeg" - "os" + "bytes" + "fmt" "os/exec" + "strconv" - "github.com/disintegration/imaging" + "github.com/h2non/bimg" ) func EncodeImageThumbnail(inputPath string, outputPath string, width, height int) error { - inputImage, err := imaging.Open(inputPath, imaging.AutoOrientation(true)) + buffer, err := bimg.Read(inputPath) if err != nil { return err } - thumbImage := imaging.Fit(inputImage, width, height, imaging.Lanczos) - if err = encodeImageJPEG(thumbImage, outputPath, 60); err != nil { - return err - } - - return nil -} - -func encodeImageJPEG(image image.Image, outputPath string, jpegQuality int) error { - photo_file, err := os.Create(outputPath) - if err != nil { - return err + options := bimg.Options{ + Width: width, + Height: height, + Embed: true, + Type: bimg.JPEG, + StripMetadata: true, } - defer photo_file.Close() - err = jpeg.Encode(photo_file, image, &jpeg.Options{Quality: jpegQuality}) + newImage, err := bimg.NewImage(buffer).Process(options) if err != nil { return err } - return nil + return bimg.Write(outputPath, newImage) } -func EncodeVideoThumbnail(inputPath string, outputPath string, width, height int) error { +func EncodeVideoThumbnail(inputPath string, outputPath string, width, _ int) error { args := []string{ "-i", inputPath, - "-vframes", "1", // output one frame - "-an", // disable audio - "-vf", "scale='min(1024,iw)':'min(1024,ih)':force_original_aspect_ratio=decrease:force_divisible_by=2", - "-vf", "select=gte(n\\,100)", + "-y", + "-vframes", "1", + "-q:v", "1", + "-vf", "thumbnail,scale=" + strconv.Itoa(width) + ":-1", outputPath, } cmd := exec.Command("ffmpeg", args...) + var b bytes.Buffer + cmd.Stderr = &b + if err := cmd.Run(); err != nil { - return err + return fmt.Errorf("%s; %w", b.String(), err) } return nil - } diff --git a/pkg/worker/list_processor.go b/pkg/worker/list_processor.go index 0a07085..c060583 100644 --- a/pkg/worker/list_processor.go +++ b/pkg/worker/list_processor.go @@ -16,6 +16,10 @@ type ( Process(context.Context, T) error } + OnFail[T any] interface { + OnFail(context.Context, T, error) + } + BatchProcessor[T any] interface { Query(context.Context) ([]T, error) Process(context.Context, T) error @@ -77,6 +81,12 @@ func (l *batchProcessorWorker[T]) Start(ctx context.Context) error { var wg sync.WaitGroup for _, v := range values { + select { + case <-ctx.Done(): + return ctx.Err() + default: + } + wg.Add(1) l.scheduler.Take() go func(v T) { @@ -84,6 +94,9 @@ func (l *batchProcessorWorker[T]) Start(ctx context.Context) error { defer wg.Done() if err := l.batchProcessor.Process(ctx, v); err != nil && !errors.Is(err, context.Canceled) { l.logrus.WithError(err).Error("Error processing batch") + if failure, ok := l.batchProcessor.(OnFail[T]); ok { + failure.OnFail(ctx, v, err) + } } }(v) } diff --git a/pkg/worker/thumbnail_scanner.go b/pkg/worker/thumbnail_scanner.go index cc201b8..168abef 100644 --- a/pkg/worker/thumbnail_scanner.go +++ b/pkg/worker/thumbnail_scanner.go @@ -2,6 +2,7 @@ package worker import ( "context" + "fmt" "math" "os" "path" @@ -47,12 +48,12 @@ func (t *ThumbnailScanner) Process(ctx context.Context, media *repository.Media) if media.IsVideo() { err := fileop.EncodeVideoThumbnail(media.Path, output, 1080, 1080) if err != nil { - return err + return fmt.Errorf("Error thumbnail video %d; %w", media.ID, err) } } else { - err := fileop.EncodeImageThumbnail(media.Path, output, 1080, math.MaxInt) + err := fileop.EncodeImageThumbnail(media.Path, output, 1080, math.MinInt32) if err != nil { - return err + return fmt.Errorf("Error thumbnail image %d; %w", media.ID, err) } } -- cgit v1.2.3