diff --git a/ffmpeg/ffmpeg.go b/ffmpeg/ffmpeg.go index 4be5509..42b7336 100644 --- a/ffmpeg/ffmpeg.go +++ b/ffmpeg/ffmpeg.go @@ -278,7 +278,7 @@ func convertFrameToRGB(av *AVContext) error { func exportBuffer(av *AVContext) ([]byte, error) { if !av.hasFrame { - return nil, ErrDecoderNotFound + return nil, ErrInvalidData } size := av.height * av.width if av.hasAlpha { diff --git a/ffmpeg/ffmpeg_test.go b/ffmpeg/ffmpeg_test.go index e3a52af..72587cf 100644 --- a/ffmpeg/ffmpeg_test.go +++ b/ffmpeg/ffmpeg_test.go @@ -31,6 +31,7 @@ func TestAVContext(t *testing.T) { SetFFmpegLogLevel(AVLogDebug) logger := zap.NewExample() SetLogging(nil) + log(AVLogDebug, "nop logging") SetLogging(func(level AVLogLevel, message string) { message = strings.TrimSuffix(message, "\n") switch level { diff --git a/go.mod b/go.mod index 7d7a4fd..ef8a13d 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/cshum/imagorvideo go 1.18 require ( - github.com/cshum/imagor v1.1.1-0.20220914044842-2b4d0ec4fd38 + github.com/cshum/imagor v1.1.1-0.20220915071030-cb478d3bcae2 github.com/gabriel-vasile/mimetype v1.4.1 github.com/stretchr/testify v1.8.0 go.uber.org/zap v1.23.0 diff --git a/go.sum b/go.sum index 48c742c..c536c25 100644 --- a/go.sum +++ b/go.sum @@ -85,8 +85,8 @@ github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWH github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cshum/imagor v1.1.1-0.20220914044842-2b4d0ec4fd38 h1:H/I3T2YJM79ZOnOuPmObsFa3qUVK+IrGADsIYvWF9aU= -github.com/cshum/imagor v1.1.1-0.20220914044842-2b4d0ec4fd38/go.mod h1:nhOPIyQwjrbcopfe7ODwLQ7hbb+Ww5Kt6Jo29iJ+7HY= +github.com/cshum/imagor v1.1.1-0.20220915071030-cb478d3bcae2 h1:Aho41Rj0wAHrqwBEmJgMHY4FTdTJj1b6BdvI3JW66AU= +github.com/cshum/imagor v1.1.1-0.20220915071030-cb478d3bcae2/go.mod h1:nhOPIyQwjrbcopfe7ODwLQ7hbb+Ww5Kt6Jo29iJ+7HY= 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= diff --git a/processor.go b/processor.go index 465de19..a10cf8a 100644 --- a/processor.go +++ b/processor.go @@ -57,6 +57,10 @@ func (p *Processor) Process(ctx context.Context, in *imagor.Blob, params imagorp if err == nil || out != nil { return } + if _, ok := err.(imagor.ErrForward); ok { + return + } + err = imagor.NewError(err.Error(), 406) // fallback image on error out = imagor.NewBlobFromBytes(transPixel) if p.FallbackImage != "" { diff --git a/processor_test.go b/processor_test.go index f8a4316..b71541b 100644 --- a/processor_test.go +++ b/processor_test.go @@ -17,6 +17,7 @@ import ( "path/filepath" "reflect" "runtime" + "strings" "testing" ) @@ -28,8 +29,9 @@ func init() { } type test struct { - name string - path string + name string + path string + expectCode int } func TestProcessor(t *testing.T) { @@ -38,8 +40,7 @@ func TestProcessor(t *testing.T) { t.Cleanup(func() { require.NoError(t, v.Shutdown(context.Background())) }) - var resultDir = filepath.Join(testDataDir, "golden/result") - doGoldenTests(t, resultDir, []test{ + doGoldenTests(t, filepath.Join(testDataDir, "golden/result"), []test{ {name: "mkv", path: "fit-in/100x100/everybody-betray-me.mkv"}, {name: "mkv meta", path: "meta/everybody-betray-me.mkv"}, {name: "mp4", path: "fit-in/100x100/schizo_0.mp4"}, @@ -47,17 +48,21 @@ func TestProcessor(t *testing.T) { {name: "mp4 180", path: "fit-in/100x100/schizo_180.mp4"}, {name: "mp4 270", path: "fit-in/100x100/schizo_270.mp4"}, {name: "image", path: "fit-in/100x100/demo.png"}, - }, WithDebug(true)) + {name: "corrupted", path: "fit-in/100x100/corrupt/everybody-betray-me.mkv", expectCode: 406}, + }, WithDebug(true), WithLogger(zap.NewExample())) + doGoldenTests(t, filepath.Join(testDataDir, "golden/result-fallback-image"), []test{ + {name: "corrupted with fallback image", path: "fit-in/100x100/corrupt/everybody-betray-me.mkv", expectCode: 406}, + }, WithDebug(false), WithLogger(zap.NewExample()), WithFallbackImage("demo.png")) } func doGoldenTests(t *testing.T, resultDir string, tests []test, opts ...Option) { resStorage := filestorage.New(resultDir, filestorage.WithSaveErrIfExists(true)) - loader := filestorage.New(testDataDir) + fileLoader := filestorage.New(testDataDir) loaders := []imagor.Loader{ - loader, + fileLoader, loaderFunc(func(r *http.Request, image string) (blob *imagor.Blob, err error) { - image, _ = loader.Path(image) + image, _ = fileLoader.Path(image) return imagor.NewBlob(func() (reader io.ReadCloser, size int64, err error) { // force read full file by 0 size reader, err = os.Open(image) @@ -67,7 +72,21 @@ func doGoldenTests(t *testing.T, resultDir string, tests []test, opts ...Option) } for i, loader := range loaders { app := imagor.New( - imagor.WithLoaders(loader), + imagor.WithLoaders(loaderFunc(func(r *http.Request, image string) (blob *imagor.Blob, err error) { + if strings.HasPrefix(image, "corrupt/") { + image, _ = fileLoader.Path(strings.TrimPrefix(image, "corrupt/")) + return imagor.NewBlob(func() (reader io.ReadCloser, size int64, err error) { + file, err := os.Open(image) + // truncate so it corrupt + reader = &readCloser{ + Reader: io.LimitReader(file, 1024), + Closer: file, + } + return + }), nil + } + return nil, imagor.ErrNotFound + }), loader), imagor.WithUnsafe(true), imagor.WithDebug(true), imagor.WithLogger(zap.NewExample()), @@ -85,7 +104,11 @@ func doGoldenTests(t *testing.T, resultDir string, tests []test, opts ...Option) http.MethodGet, fmt.Sprintf("/unsafe/%s", tt.path), nil).WithContext(ctx) app.ServeHTTP(w, req) cancel() - assert.Equal(t, 200, w.Code) + if tt.expectCode == 0 { + assert.Equal(t, 200, w.Code) + } else { + assert.Equal(t, tt.expectCode, w.Code) + } b := imagor.NewBlobFromBytes(w.Body.Bytes()) _ = resStorage.Put(context.Background(), tt.path, b) path := filepath.Join(resultDir, imagorpath.Normalize(tt.path, nil)) @@ -119,3 +142,8 @@ type loaderFunc func(r *http.Request, image string) (blob *imagor.Blob, err erro func (f loaderFunc) Get(r *http.Request, image string) (*imagor.Blob, error) { return f(r, image) } + +type readCloser struct { + io.Reader + io.Closer +} diff --git a/testdata/golden/result-fallback-image/fit-in/100x100/corrupt/everybody-betray-me.mkv b/testdata/golden/result-fallback-image/fit-in/100x100/corrupt/everybody-betray-me.mkv new file mode 100644 index 0000000..24b35b4 Binary files /dev/null and b/testdata/golden/result-fallback-image/fit-in/100x100/corrupt/everybody-betray-me.mkv differ diff --git a/testdata/golden/result/fit-in/100x100/corrupt/everybody-betray-me.mkv b/testdata/golden/result/fit-in/100x100/corrupt/everybody-betray-me.mkv new file mode 100644 index 0000000..5bfd67a Binary files /dev/null and b/testdata/golden/result/fit-in/100x100/corrupt/everybody-betray-me.mkv differ