diff --git a/internal/handlers/unsupported_source_internal_test.go b/internal/handlers/unsupported_source_internal_test.go new file mode 100644 index 0000000..a10e37e --- /dev/null +++ b/internal/handlers/unsupported_source_internal_test.go @@ -0,0 +1,54 @@ +package handlers + +import ( + "fmt" + "log/slog" + "net/http" + "net/http/httptest" + "strings" + "testing" + + "sneak.berlin/go/pixa/internal/httpfetcher" + "sneak.berlin/go/pixa/internal/imageprocessor" + "sneak.berlin/go/pixa/internal/imgcache" +) + +// TestUnsupportedSourceFormatAnswers415 checks that both image routes answer +// 415 with a clear error when the upstream answers with a content type pixa +// does not accept, such as SVG, and when orig is asked of a source in a +// format the processor cannot name, wrapped as the service wraps them. +func TestUnsupportedSourceFormatAnswers415(t *testing.T) { + t.Parallel() + + h := &Handlers{log: slog.New(slog.DiscardHandler)} + req := &imgcache.ImageRequest{SourceHost: "img.example.com", SourcePath: "/a.svg"} + + for _, err := range []error{ + fmt.Errorf("upstream fetch failed: %w: image/svg+xml", + httpfetcher.ErrInvalidContentType), + fmt.Errorf("image processing failed: %w: unknown", + imageprocessor.ErrUnsupportedInputFormat), + } { + plain := httptest.NewRecorder() + h.respondImageError(plain, req, err) + + encrypted := httptest.NewRecorder() + h.handleImageError(encrypted, err) + + for route, rec := range map[string]*httptest.ResponseRecorder{ + "HandleImage": plain, "HandleImageEnc": encrypted, + } { + t.Logf("%s for %v: %d %s", route, err, rec.Code, rec.Body.String()) + + if rec.Code != http.StatusUnsupportedMediaType { + t.Errorf("%s for %v: status = %d, want %d", + route, err, rec.Code, http.StatusUnsupportedMediaType) + } + + if !strings.Contains(rec.Body.String(), "unsupported source format") { + t.Errorf("%s for %v: body = %q, want the unsupported source format error", + route, err, rec.Body.String()) + } + } + } +} diff --git a/internal/imageprocessor/orig_format_internal_test.go b/internal/imageprocessor/orig_format_internal_test.go new file mode 100644 index 0000000..f788b7c --- /dev/null +++ b/internal/imageprocessor/orig_format_internal_test.go @@ -0,0 +1,39 @@ +package imageprocessor + +import ( + "bytes" + "errors" + "testing" + + "github.com/davidbyttow/govips/v2/vips" +) + +// TestImageProcessor_OrigOfUnnamedFormatRefused verifies that orig of an +// input in a format the processor decodes but cannot name, here TIFF, is +// an error, and not the image saved as JPEG. +func TestImageProcessor_OrigOfUnnamedFormatRefused(t *testing.T) { + t.Parallel() + + img, err := vips.NewImageFromBuffer(createTestPNG(t, 20, 20)) + if err != nil { + t.Fatalf("failed to decode test PNG: %v", err) + } + + t.Cleanup(img.Close) + + tiff, _, err := img.ExportTiff(vips.NewTiffExportParams()) + if err != nil { + t.Fatalf("failed to save test TIFF: %v", err) + } + + result, err := New(Params{}).Process( + t.Context(), bytes.NewReader(tiff), &Request{Format: FormatOriginal}, + ) + if result != nil { + t.Logf("Process() returned %s", result.ContentType) + } + + if !errors.Is(err, ErrUnsupportedInputFormat) { + t.Errorf("Process() error = %v, want %v", err, ErrUnsupportedInputFormat) + } +} diff --git a/internal/server/svg_internal_test.go b/internal/server/svg_internal_test.go new file mode 100644 index 0000000..95b46fa --- /dev/null +++ b/internal/server/svg_internal_test.go @@ -0,0 +1,41 @@ +package server + +import ( + "io" + "net/http" + "net/http/httptest" + "testing" +) + +// TestImageProxyRefusesSVG requests an image the upstream answers as SVG, +// in its own format (orig) and resized as PNG, through pixa's router, +// upstream fetcher and image processor. pixa does not accept SVG as a +// source, so each request is answered 415, never with an image. +func TestImageProxyRefusesSVG(t *testing.T) { + t.Parallel() + + upstream := httptest.NewServer(http.HandlerFunc( + func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Content-Type", "image/svg+xml") + _, _ = io.WriteString(w, ``) + })) + t.Cleanup(upstream.Close) + + s, _, _ := startImageProxy(t, upstream) + + for _, sizeFormat := range []string{"64x48.orig", "32x24.png"} { + target := "/v1/image/" + upstreamHost + "/drawing.svg/" + sizeFormat + + rec := httptest.NewRecorder() + s.ServeHTTP(rec, httptest.NewRequestWithContext( + t.Context(), http.MethodGet, target, nil)) + t.Logf("GET %s: %d, Content-Type %s, body %s", + target, rec.Code, rec.Header().Get("Content-Type"), rec.Body.String()) + + if rec.Code != http.StatusUnsupportedMediaType { + t.Errorf("GET %s status = %d, want %d", + target, rec.Code, http.StatusUnsupportedMediaType) + } + } +}