The fetcher accepts image/svg+xml again and internal/magic detects SVG. A raster format renders the SVG with librsvg at the density that makes it cover the output size, so an enlarged SVG stays sharp; the rendered size is held to MaxInputDimension. 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, as an SVG's root element can come after a prolog. Tests that pinned SVG as refused now expect it to be read. Model: opus-5-5
This commit is contained in:
1 parent
9f1e9f5253
commit
632fe0bd36
20 files changed
+669
-76
No files matched your search
@@ -449,16 +449,18 @@ func (c *Cache) cleanExpiredBatch(ctx context.Context) (int64, error) {
|
||||
return deleted, nil
|
||||
}
|
||||
|
||||
// readFormat reads the first bytes of a source or variant file, without
|
||||
// moving its offset, and returns the format they show. Sources and variants
|
||||
// are in the same six formats.
|
||||
// readFormat reads up to magic.MaxMagicBytes first bytes of a source or
|
||||
// variant file, without moving its offset, and returns the format they show.
|
||||
// Sources and variants are in the same seven formats; a variant is SVG only
|
||||
// as orig of an SVG source. A file shorter than magic.MinMagicBytes is
|
||||
// io.EOF.
|
||||
func readFormat(content io.ReaderAt) (imagerequest.Format, error) {
|
||||
firstBytes := make([]byte, magic.MinMagicBytes)
|
||||
firstBytes := make([]byte, magic.MaxMagicBytes)
|
||||
|
||||
_, err := content.ReadAt(firstBytes, 0)
|
||||
if err != nil {
|
||||
n, err := content.ReadAt(firstBytes, 0)
|
||||
if err != nil && (!errors.Is(err, io.EOF) || n < magic.MinMagicBytes) {
|
||||
return "", fmt.Errorf("failed to read the first bytes: %w", err)
|
||||
}
|
||||
|
||||
return magic.DetectFormat(firstBytes)
|
||||
return magic.DetectFormat(firstBytes[:n])
|
||||
}
|
||||
@@ -95,8 +95,6 @@ func TestVariant_RefusesFileOfNoOutputFormat(t *testing.T) {
|
||||
wantErr error
|
||||
}{
|
||||
{"text", []byte("this is text, not an image"), magic.ErrUnknownFormat},
|
||||
{"SVG", []byte(`<svg xmlns="http://www.w3.org/2000/svg"></svg>`),
|
||||
magic.ErrUnknownFormat},
|
||||
{"JPEG cut to 10 bytes", jpegImage[:10], io.EOF},
|
||||
{"empty", nil, io.EOF},
|
||||
}
|
||||
|
||||
@@ -216,8 +216,6 @@ func TestSource_RefusesFileOfNoSourceFormat(t *testing.T) {
|
||||
wantErr error
|
||||
}{
|
||||
{"text", []byte("this is text, not an image"), magic.ErrUnknownFormat},
|
||||
{"SVG", []byte(`<svg xmlns="http://www.w3.org/2000/svg"></svg>`),
|
||||
magic.ErrUnknownFormat},
|
||||
{"JPEG cut to 10 bytes", jpegImage[:10], io.EOF},
|
||||
{"empty file", nil, io.EOF},
|
||||
}
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
package imgcache
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"sneak.berlin/go/pixa/internal/imagerequest"
|
||||
)
|
||||
|
||||
// testSVG is an SVG with a comment before its root element, so that its
|
||||
// first magic.MinMagicBytes bytes do not show its format.
|
||||
const testSVG = `<!-- a drawing --><svg xmlns="http://www.w3.org/2000/svg" ` +
|
||||
`width="4" height="4"/>`
|
||||
|
||||
// TestSourceAndVariant_ReadSVG checks that a cached SVG source is read as
|
||||
// SVG, and a cached SVG variant (orig of an SVG source) as image/svg+xml.
|
||||
func TestSourceAndVariant_ReadSVG(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
cache, _ := newEvictionTestCache(t, 1<<30)
|
||||
|
||||
storeEvictionTestSource(t, cache, testHostCDN, "/drawing.svg", []byte(testSVG))
|
||||
|
||||
reader, _, format, err := cache.Source(t.Context(),
|
||||
imagerequest.Source{Host: testHostCDN, Path: "/drawing.svg"})
|
||||
t.Logf("Source() format = %q, error = %v", format, err)
|
||||
|
||||
if err != nil || format != imagerequest.FormatSVG {
|
||||
t.Errorf("Source() = format %q, error %v; want %q", format, err,
|
||||
imagerequest.FormatSVG)
|
||||
}
|
||||
|
||||
if reader != nil {
|
||||
_ = reader.Close()
|
||||
}
|
||||
|
||||
key := imagerequest.VariantKey("aabbccdd3001")
|
||||
|
||||
err = cache.variants.Write(string(key), []byte(testSVG))
|
||||
if err != nil {
|
||||
t.Fatalf("storing the variant file: %v", err)
|
||||
}
|
||||
|
||||
reader, _, contentType, err := cache.Variant(key)
|
||||
t.Logf("Variant() content type = %q, error = %v", contentType, err)
|
||||
|
||||
if err != nil || contentType != "image/svg+xml" {
|
||||
t.Errorf("Variant() = content type %q, error %v; want image/svg+xml",
|
||||
contentType, err)
|
||||
}
|
||||
|
||||
if reader != nil {
|
||||
_ = reader.Close()
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user