Capture upstream Last-Modified/ETag and support conditional revalidation #83

Open
opened 2026-08-09 03:49:30 +02:00 by clawbot · 0 comments
Collaborator

Verified against main at 61f42e6. Covers the "Last-Modified headers" item in TODO.md.

The scaffolding exists and is entirely unpopulated:

  • ImageResponse.LastModified (internal/imgcache/imgcache.go:111-112) — declared, never set, never read
  • SourceMetadata.LastModified and SourceMetadata.ETag (internal/imgcache/storage.go:211-212) — declared, never populated

So pixa neither records what the upstream told it about freshness nor uses it. Two consequences:

  1. Downstream: responses carry no Last-Modified, so clients and CDNs can only revalidate via the ETag pixa generates itself. That works, but it discards information the origin already gave us.
  2. Upstream: pixa cannot issue conditional requests. Any re-fetch is an unconditional full download, even when the origin would have answered 304 Not Modified for free. This becomes directly relevant if the CacheTTL issue is resolved by enforcing the TTL — without conditional revalidation, every expiry means a full re-download of unchanged bytes.

Definition of done

  1. Last-Modified and ETag from the upstream response are captured into SourceMetadata and persisted with the source entry.
  2. Re-fetches send If-Modified-Since/If-None-Match when the stored values exist, and a 304 is handled by refreshing the freshness timestamp without re-downloading or re-processing.
  3. Responses set Last-Modified where a meaningful value exists. Do not synthesize one from cache write time and present it as origin truth — an absent header is better than a wrong one.
  4. The existing self-generated ETag behavior is preserved; the two mechanisms must not conflict. internal/handlers already has ETag/304 tests — they must still pass unmodified.
  5. Failing tests first: an upstream serving Last-Modified results in a stored value and a response header; a re-fetch sends the conditional header; a 304 response does not re-download and does not corrupt the cached entry.
  6. make check green.

Coordination

Pairs naturally with the CacheTTL issue — that issue decides when to revalidate, this one supplies the mechanism to do it cheaply. If both are done, do this one first.

Verified against `main` at `61f42e6`. Covers the "Last-Modified headers" item in `TODO.md`. The scaffolding exists and is entirely unpopulated: - `ImageResponse.LastModified` (`internal/imgcache/imgcache.go:111-112`) — declared, never set, never read - `SourceMetadata.LastModified` and `SourceMetadata.ETag` (`internal/imgcache/storage.go:211-212`) — declared, never populated So pixa neither records what the upstream told it about freshness nor uses it. Two consequences: 1. **Downstream:** responses carry no `Last-Modified`, so clients and CDNs can only revalidate via the ETag pixa generates itself. That works, but it discards information the origin already gave us. 2. **Upstream:** pixa cannot issue conditional requests. Any re-fetch is an unconditional full download, even when the origin would have answered `304 Not Modified` for free. This becomes directly relevant if the `CacheTTL` issue is resolved by enforcing the TTL — without conditional revalidation, every expiry means a full re-download of unchanged bytes. ## Definition of done 1. `Last-Modified` and `ETag` from the upstream response are captured into `SourceMetadata` and persisted with the source entry. 2. Re-fetches send `If-Modified-Since`/`If-None-Match` when the stored values exist, and a `304` is handled by refreshing the freshness timestamp without re-downloading or re-processing. 3. Responses set `Last-Modified` where a meaningful value exists. Do not synthesize one from cache write time and present it as origin truth — an absent header is better than a wrong one. 4. The existing self-generated ETag behavior is preserved; the two mechanisms must not conflict. `internal/handlers` already has ETag/304 tests — they must still pass unmodified. 5. Failing tests first: an upstream serving `Last-Modified` results in a stored value and a response header; a re-fetch sends the conditional header; a `304` response does not re-download and does not corrupt the cached entry. 6. `make check` green. ## Coordination Pairs naturally with the `CacheTTL` issue — that issue decides *when* to revalidate, this one supplies the mechanism to do it cheaply. If both are done, do this one first.
clawbot added this to the 1.0.0 milestone 2026-08-09 03:49:30 +02:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: sneak/pixa#83