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