1 Commits
Author SHA1 Message Date
clawbot 0b203a6dd4 Serve JPEG XL when a request names no format (closes #222)
check / check (push) Waiting to run
A /v1/image/ URL whose last segment is a size with no format, such as
800x600 or orig, is served as JPEG XL and signed as jxl, so it shares
the signature of the same URL ending in .jxl. An encrypted URL whose
token holds no format is served as JPEG XL, as encurl.DefaultFormat is
now jxl. The generator page selects JPEG XL by default, and a form
with an empty format, or none, makes a URL whose name ends in .jxl.

The image processor no longer takes an empty format as orig: both
routes give every request a format, so it refuses a request with none
instead of keeping a second default. auto still ends with JPEG.

Model: opus-5-5
2026-10-08 09:43:52 +00:00
4 changed files with 21 additions and 18 deletions
+15 -14
View File
@@ -175,20 +175,21 @@ path under `/v1/` answers 200, in maintenance mode too.
with the page naming a field that is not valid; 500 when the URL cannot be
made.
- `GET /logout` — end the login session. Needs: nothing. Answers: 303 to `/`.
- `GET` or `HEAD` `/v1/image/<host>/<path>/<size>.<format>` — an image, fetched,
resized and converted (below). Needs: a signature, unless the host is
allowlisted (see Source Hosts). Answers: 200; 304 when `If-None-Match` matches
the image's `ETag`; 400 for a URL or parameter that is not valid, or for the
format `auto` an `Accept` header that is not valid; 406 for the format `auto`
when `Accept` allows none of the formats it chooses from; 401 for a missing or
wrong signature, a missing `exp` or an `exp` in the past; 403 when the
request's `Referer` names a host in `referer_blocklist`, checked before the
signature, the cache and the upstream fetch; 403 when the upstream host, or a
host it redirects to, is `localhost`, ends in `.localhost` or `.local`, or has
an address in a blocked network (see `blocked_networks`); 502 when the
upstream answered with an error status, and for 5 minutes after that for the
same source URL; 503 when pixa is busy or in maintenance mode; 500 for any
other failure.
- `GET` or `HEAD` `/v1/image/<host>/<path>/<size>.<format>`, or
`/v1/image/<host>/<path>/<size>` with no format — an image, fetched, resized
and converted (below). Needs: a signature, unless the host is allowlisted (see
Source Hosts). Answers: 200; 304 when `If-None-Match` matches the image's
`ETag`; 400 for a URL or parameter that is not valid, or for the format `auto`
an `Accept` header that is not valid; 406 for the format `auto` when `Accept`
allows none of the formats it chooses from; 401 for a missing or wrong
signature, a missing `exp` or an `exp` in the past; 403 when the request's
`Referer` names a host in `referer_blocklist`, checked before the signature,
the cache and the upstream fetch; 403 when the upstream host, or a host it
redirects to, is `localhost`, ends in `.localhost` or `.local`, or has an
address in a blocked network (see `blocked_networks`); 502 when the upstream
answered with an error status, and for 5 minutes after that for the same
source URL; 503 when pixa is busy or in maintenance mode; 500 for any other
failure.
- `GET` or `HEAD` `/v1/e/<token>/<name>` — an image through an encrypted URL
(see Encrypted URLs). Needs: nothing but the URL. Answers: 200; 304 when
`If-None-Match` matches the image's `ETag`; 400 for a token that does not
+2 -1
View File
@@ -18,7 +18,8 @@ import (
)
// HandleImage handles the main image proxy route:
// /v1/image/<host>/<path>/<width>x<height>.<format>
// /v1/image/<host>/<path>/<width>x<height>.<format>, or with no format
// /v1/image/<host>/<path>/<width>x<height>
func (s *Handlers) HandleImage() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
if s.refuseBlockedReferer(w, r) {
+2 -2
View File
@@ -100,8 +100,8 @@ func NewService(cfg *ServiceConfig) (*Service, error) {
allowHTTP = cfg.FetcherConfig.AllowHTTP
}
// JPEG XL is to become the default output format, so pixad does not
// start without it.
// JPEG XL is the default output format, so pixad does not start
// without it.
err := imageprocessor.CheckJPEGXLSupport()
if err != nil {
return nil, err
+2 -1
View File
@@ -89,7 +89,8 @@ func (s *Server) SetupRoutes() {
r.Use(s.refuseDuringMaintenance)
// Main image proxy route
// /v1/image/<host>/<path>/<width>x<height>.<format>
// /v1/image/<host>/<path>/<width>x<height>.<format>, or with no
// format /v1/image/<host>/<path>/<width>x<height>
r.Get("/image/*", s.h.HandleImage())
r.Head("/image/*", s.h.HandleImage())