Commit Graph
8 Commits
Author SHA1 Message Date
sneak 2670d9002f Take the signature, the expiry and the URL scheme off the image request (closes #314)
check / check (push) Waiting to run
The image request now holds only its source and its transform, exactly what
the variant key covers. The /v1/image/ handler checks the allowlist and
verifies the signature itself with Signer.Verify(req, sig, expires). Both
image handlers keep the URL's expiry as a local value for Cache-Control. The
image service holds no signer, allowlist or AllowHTTP, and ValidateRequest is
gone. The fetcher takes the source and builds its URL with Source.URL from its
own AllowHTTP, so no URL string is built and parsed again. chooseAutoFormat
returns the format it chooses instead of writing into the request. The signed
URL format and every route's answers are unchanged.

Model: opus-5-5
2026-10-26 12:34:19 +00:00
clawbot 63690a9ec9 Build the image pipeline in pixad's fx graph (closes #313)
check / check (push) Canceled after 0s
The new package internal/providers builds the cache, the fetcher, the
processor, the image service, the session manager and the encrypted URL
generator from the config. pixad's fx graph provides them with
providers.Constructors(), and handlers.New receives them built. The
server tests build the same graph, with only the fetcher's dial function
replaced. database.New opens the database, so these parts can read it
while fx builds them; the cache's stop hook still runs before the
database's.

Each setting's default is declared in internal/config, and
internal/providers works out the default cache_max_bytes. The cache's
MaxBytes is the one value for the disk cache limit, and 0 turns the disk
cache off. The fetcher and the processor take explicit values.

Model: opus-5-5
2026-10-26 12:28:23 +01:00
clawbot ac2bae0489 Remove the code nothing in production calls (closes #312)
check / check (push) Canceled after 0s
Service.Warm, the ImageCache interface, both GenerateSignedURL methods,
signature.ParseParams, imagerequest.ParseImagePath, four symbols of
internal/magic, the image processor's lists of supported formats,
IsEmpty and Count of the allowlist, ssrfSafeDialer, CacheStale,
ErrCacheMiss, ErrNegativeCache, ImageResponse.LastModified and the Load
methods of ContentStorage and VariantStorage had no caller outside
tests. They are gone, with the tests that tested only them.

The handlers tests sign their image URLs with generateSignedURL, a test
helper that builds the URL as the removed generator did. The SSRF dialer
tests call dialSSRFSafe with no operator blocklist, which is all
ssrfSafeDialer did. The tests of ParseImagePath and ContentStorage.Load
call ParseImageURL and LoadWithSize instead. MIMEToImageFormat,
ContentStorage.Store and CleanExpired stay, as pixa calls them.

Model: opus-5-5
2026-10-26 10:54:14 +01:00
clawbot b49d0068df Count hits, misses, fetches and transforms as Prometheus counters (closes #311)
check / check (push) Canceled after 0s
The five counts the cache_stats table held are now Prometheus counters in
memory, as fields of the cache. NewCache makes them and registers them on
the registry it is given. pixad gives it Prometheus' default registry,
which /metrics serves; each test gives it a new one. The Increment methods
add to their cache's counters, so counting makes no database call.

cache_stats, Cache.Stats, Service.Stats, CacheStats and the pending counts
are gone, with their tests. The background goroutine now writes only access
times, and its names say so: StartPendingAccessTimeWrites,
StopPendingAccessTimeWrites and pendingaccesstimes.go. The two stop tests
whose write under way was a count now use access times.

Model: opus-5-5
2026-10-26 10:20:42 +01:00
clawbot 00d8ba26c5 One image request type instead of five (closes #307)
check / check (push) Canceled after 0s
The new package internal/imagerequest holds the request type, its two
parts Source and Transform, the Format and Fit types, the dimension and
fit checks, the /v1/image/ path parsing and the variant key; it imports
no other package of pixa. imgcache.ParsedURL, imgcache.ImageRequest,
signature.Request, imageprocessor.Request, the second Size, format and
fit types and the conversions between them are gone. The image
processor takes a Transform only. encurl keeps a private struct with the
token's short CBOR field names. VariantKey moves with the function that
makes it. Tests follow the moved and renamed code; the tests of the
removed conversions go with them.

Model: opus-5-5
2026-10-21 14:41:07 +02:00
clawbot ca512fdb4f Remove the unused cache lifetime setting (closes #69)
check / check (push) Canceled after 0s
CacheConfig.CacheTTL was set to DefaultCacheTTL (24 hours) and never
read, so cached images never expired. Remove the field, the constant
and the line that set it. Cached source and transformed images stay
until eviction removes them to keep the cache within cache_max_bytes.

A new test caches a source and a transformed image, sets every time
pixa stores for them two days back (database rows, metadata files and
file times), and checks that both are still served from the cache
without a new upstream fetch.

Existing tests lose only the CacheTTL line of their cache config.

Model: opus-5-5
2026-10-13 07:58:55 +02:00
clawbot c7173c47d8 Return and pass on request IDs, and give /v1/e/ ETag, 304 and HEAD (closes #84)
check / check (push) Failing after 2s
Every response carries X-Request-Id, the upstream fetch sends it, and
the "upstream fetched", "image converted" and "image served" lines log
it as request_id. pixa's own RequestID middleware keeps a request's own
ID only when it is at most 64 letters, digits, '-', '_' or '.', and
otherwise makes a random one with crypto/rand, so nothing a client
chooses freely and nothing about the host reaches upstream. /v1/e/ now
sets ETag, answers a matching If-None-Match with 304 and is routed for
HEAD, through notModified, which both image handlers call. No Vary is
added: go-chi/cors already sends Vary: Origin.

Model: opus-5-5
2026-10-04 12:41:54 +02:00
clawbot 2afe61e301 Keep max-age within an expiring image URL's lifetime (closes #63)
check / check (push) Successful in 12s
Both image routes sent Cache-Control: public, max-age=31536000,
immutable unconditionally, so a browser or proxy could keep serving an
image for a year after its signed or encrypted URL had expired. max-age
is now the whole seconds left until the URL expires, never negative and
at most one year; a URL with no expiry keeps one year. The 304 answer
uses the same value. An encrypted URL's expiry now reaches
ImageRequest.Expires through ToImageRequest. immutable stays: freshness
now ends no later than the URL's expiry. README.md documents the header.

Model: opus-5-5
2026-09-29 03:51:58 +02:00