Support SVG sources (closes #68)
check / check (push) Canceled after 0s

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:
sneak committed 2026-11-11 00:38:16 +00:00
1 parent 9f1e9f5253
commit 632fe0bd36
20 files changed
+669 -76

No files matched your search

+19 -4
View File
@@ -307,6 +307,7 @@ path under `/v1/` answers 200, in maintenance mode too.
- 304 when `If-None-Match` matches the image's `ETag`.
- 400 for a URL or parameter that is not valid.
- 400 when the format is `auto` and the `Accept` header is not valid.
- 400 for `orig` of an SVG source at a size other than `orig`.
- 406 when the format is `auto` and `Accept` allows none of the formats it
chooses from.
- 401 for a missing or wrong signature.
@@ -344,6 +345,8 @@ path under `/v1/` answers 200, in maintenance mode too.
- 304 when `If-None-Match` matches the image's `ETag`.
- 400 for a token that does not decrypt.
- 400 for a token that asks for a size or fit that is not valid.
- 400 for a token that asks for `orig` of an SVG source at a size other than
`orig`.
- 410 once the token has expired.
- 400 when the token's format is `auto` and the `Accept` header is not
valid.
@@ -457,9 +460,9 @@ more than 40 seconds (see below). That includes `orig` of an AVIF source, and
`auto` when it chooses AVIF, so a client whose `Accept` names `image/avif` but
not `image/jxl` is refused such a size.
The source image may be JPEG, PNG, GIF, WebP, AVIF or JPEG XL. The upstream's
`Content-Type` must name its format, and the image's first bytes must match it.
An upstream answering with any other `Content-Type`, SVG included, is refused
The source image may be JPEG, PNG, GIF, WebP, AVIF, JPEG XL or SVG. The
upstream's `Content-Type` must name its format, and the image's first bytes must
match it. An upstream answering with any other `Content-Type` is refused
with 415. So is a body whose first bytes are not those of the format its
`Content-Type` names, such as a JPEG sent as `image/png`, text sent as an image,
or an empty body. pixa then does not fetch that source URL again for 5 minutes,
@@ -468,6 +471,17 @@ would need that fetch. An image whose first bytes libvips reads as another
format, such as an SVG whose first bytes pass the check for AVIF, is refused
with 415 too.
For any format but `orig`, pixa renders an SVG source at the requested size, so
an enlarged SVG stays sharp. At the `orig` size it is rendered at its own size,
from the `width` and `height` of its root element. Rendering loads no file or
URL that the SVG refers to.
`orig` of an SVG source is the SVG itself, unchanged, and is cached like any
other image. It is given only at the `orig` size, since pixa does not resize an
SVG as SVG: `orig` of an SVG at any other size is refused with 400. A browser
that opens an SVG from pixa runs none of its scripts, as pixa's
`Content-Security-Policy` allows no inline script.
With the format `auto`, pixa chooses the format for each request from its
`Accept` header, in this order:
@@ -607,7 +621,8 @@ session.
pixa decodes and re-encodes every image it serves, and removes all metadata from
the output: EXIF (GPS position, camera make, model and serial number, capture
time, embedded thumbnail), XMP, IPTC and the ICC colour profile. This cannot be
turned off.
turned off. The one exception is `orig` of an SVG source, which is the SVG
unchanged, its metadata included.
- The `orig` format means the source's own format, not the source's bytes: an
`orig` image is re-encoded and stripped like any other.