Keep max-age within an expiring image URL's lifetime (closes #63)

Both image routes sent Cache-Control: public, max-age=31536000,
immutable, so a browser or proxy could keep serving an image for a year
after its signed or encrypted URL had expired. The header is now built
from the request's Expires: max-age is the whole seconds left until the
URL expires, never negative, or one year for a URL with no expiry.
ToImageRequest now carries an encrypted URL's expiry onto the request,
as the image route already does with exp. immutable stays: it only stops
revalidation while a copy is fresh, and freshness now ends at the
expiry. README.md documents the header.

Model: opus-5-5
This commit is contained in:
2026-09-29 01:25:25 +00:00
parent ac95c33cdb
commit 0a0142d1af
6 changed files with 44 additions and 5 deletions
+6
View File
@@ -100,6 +100,12 @@ than once, is refused with 400.
- `<format>`: one of `orig`, `png`, `jpeg`, `webp`
- `<size>`: `orig` or `<width>x<height>` (e.g. `800x600`)
An image is served with `Cache-Control: public, max-age=<seconds>, immutable`.
When the URL has an expiry (an `exp`, or the TTL of an encrypted URL),
`max-age` is the whole seconds left until then, so no browser or proxy cache
keeps the image after pixa would refuse the URL. A URL with no expiry gets one
year. `immutable` only stops a client revalidating while its copy is fresh.
The login form (`POST /`) is limited to 5 attempts per minute per client
address, counting an IPv6 client by its /64; an attempt over the limit is
refused with 429 and a `Retry-After` header. Behind a reverse proxy the client