check / check (push) Canceled after 0s
The fetcher accepts image/svg+xml again and internal/magic detects SVG. A raster format renders the SVG at the least size that covers the output, held to 8192 on a side, through libvips' thumbnail, which renders at any scale, so an enlarged SVG stays sharp. An SVG's own size is not limited; one with a side more than 8192 times the other is ErrSVGTooThin, answered 415. orig of an SVG at the orig size is the SVG unchanged, cached as a variant; at any other size it is ErrSVGNotOriginalSize, answered 400. The cache reads up to 1024 first bytes of a file to find its format. Render time and memory grow with what the SVG draws: P1 in TODO.md. Tests that pinned SVG as refused now expect it to be read. Model: opus-5-5
77 lines
2.4 KiB
Go
77 lines
2.4 KiB
Go
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/imagerequest"
|
|
)
|
|
|
|
// TestUnsupportedSourceFormatAnswers415 checks that respondImageError, which
|
|
// answers the errors of both image routes, answers 415 with a clear error when
|
|
// the upstream answers with a content type pixa does not accept, such as TIFF,
|
|
// and when libvips does not read a source as the format its first bytes
|
|
// show, wrapped as the service wraps them.
|
|
func TestUnsupportedSourceFormatAnswers415(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
h := &Handlers{log: slog.New(slog.DiscardHandler)}
|
|
req := &imagerequest.Request{
|
|
Source: imagerequest.Source{Host: "img.example.com", Path: "/a.tiff"},
|
|
}
|
|
|
|
for _, err := range []error{
|
|
fmt.Errorf("upstream fetch failed: %w: image/tiff",
|
|
httpfetcher.ErrInvalidContentType),
|
|
fmt.Errorf("image processing failed: %w: libvips does not read the input as avif",
|
|
imageprocessor.ErrUnsupportedInputFormat),
|
|
} {
|
|
rec := httptest.NewRecorder()
|
|
h.respondImageError(rec, req, err)
|
|
t.Logf("for %v: %d %s", err, rec.Code, rec.Body.String())
|
|
|
|
if rec.Code != http.StatusUnsupportedMediaType {
|
|
t.Errorf("for %v: status = %d, want %d",
|
|
err, rec.Code, http.StatusUnsupportedMediaType)
|
|
}
|
|
|
|
if !strings.Contains(rec.Body.String(), "unsupported source format") {
|
|
t.Errorf("for %v: body = %q, want the unsupported source format error",
|
|
err, rec.Body.String())
|
|
}
|
|
}
|
|
}
|
|
|
|
// TestSVGTooThinAnswers415 checks that respondImageError answers 415 with a
|
|
// clear error for an SVG source too thin to render, wrapped as the service
|
|
// wraps it.
|
|
func TestSVGTooThinAnswers415(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
h := &Handlers{log: slog.New(slog.DiscardHandler)}
|
|
req := &imagerequest.Request{
|
|
Source: imagerequest.Source{Host: "svg.example.com", Path: "/a.svg"},
|
|
}
|
|
err := fmt.Errorf("image processing failed: %w: 81930x10",
|
|
imageprocessor.ErrSVGTooThin)
|
|
|
|
rec := httptest.NewRecorder()
|
|
h.respondImageError(rec, req, err)
|
|
t.Logf("for %v: %d %s", err, rec.Code, rec.Body.String())
|
|
|
|
if rec.Code != http.StatusUnsupportedMediaType {
|
|
t.Errorf("status = %d, want %d", rec.Code,
|
|
http.StatusUnsupportedMediaType)
|
|
}
|
|
|
|
if !strings.Contains(rec.Body.String(), "SVG source too thin to render") {
|
|
t.Errorf("body = %q, want the SVG too thin error", rec.Body.String())
|
|
}
|
|
}
|