Skip to content

fix(images): browser-cacheable cover art and SPA assets#743

Draft
kevinheneveld wants to merge 1 commit into
Listenarrs:canaryfrom
kevinheneveld:fix/cover-cache-headers-upstream
Draft

fix(images): browser-cacheable cover art and SPA assets#743
kevinheneveld wants to merge 1 commit into
Listenarrs:canaryfrom
kevinheneveld:fix/cover-cache-headers-upstream

Conversation

@kevinheneveld

Copy link
Copy Markdown
Contributor

What

Cover images served via /api/v1/images/{id} carry Cache-Control: private, max-age=3600 — on a large library the browser refetches every cover after an hour, hammering the server on each browse (measured: ~3.2k covers, ~100MB per full grid render). This PR:

  • Raises the image hot path to private, max-age=604800 (7 days; ETag/Last-Modified already answer revalidation with 0-byte 304s)
  • Adds public, max-age=604800 to the /config/cache/images static middleware
  • Bonus found while there: SPA static files had no Cache-Control at all — hashed /assets/* now public, max-age=31536000, immutable; index.html (both static and SPA-fallback routes) now no-cache, which also fixes a stale-app-shell-after-deploy hazard

Tests

2 header-pinning tests; full suite passing.

🤖 Generated with Claude Code

The /images/{id} endpoint (the grid's hot path — the frontend rewrites
/config/cache/images/* URLs to it) served covers with Cache-Control:
private, max-age=3600. On a ~3.2k-book library that meant a full
~100MB cover refetch on any browse more than an hour after the last.
Raise to 7 days; PhysicalFileResult already answers If-Modified-Since
with 304 (verified live), so post-expiry revalidation costs zero bytes.

Also:
- /config/cache/images static middleware (direct-path consumers) gains
  public, max-age=604800 — it already emits ETags for revalidation.
- SPA static assets had NO Cache-Control at all: content-hashed
  /assets/* now cache forever (max-age=31536000, immutable) and
  index.html — including the SPA-route fallback — is no-cache, so a
  deploy can no longer strand browsers on a stale shell referencing
  purged asset hashes.

Image URLs carry no per-session tokens (verified: getImageUrl builds
plain /images/{id} paths; auth rides headers/cookies), so browser
caching is safe across sessions.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant