Skip to content

docs(deployment): drop immutable from nginx /uploads/ cache header#62

Merged
bigin merged 1 commit into
mainfrom
fix/uploads-cache-immutable
May 25, 2026
Merged

docs(deployment): drop immutable from nginx /uploads/ cache header#62
bigin merged 1 commit into
mainfrom
fix/uploads-cache-immutable

Conversation

@bigin

@bigin bigin commented May 25, 2026

Copy link
Copy Markdown
Owner

The nginx snippet in docs/deployment.md recommended Cache-Control: public, immutable for /uploads/, which is wrong for iManager's FileStorage layout.

FileStorage writes to var/uploads/<itemId>/<fieldId>/<filename> keeping the user's original filename. Re-uploading a file under the same name leaves the URL stable while the bytes change. With immutable set, browsers serve the stale bytes for up to 30 days (the expires window) and skip revalidation entirely.

Switch to Cache-Control: public, must-revalidate and add an inline comment explaining the choice. The 30-day expires window is kept; browsers now send If-None-Match on every hit and nginx's built-in ETag answers 304 cheaply when the file is unchanged, 200 with the new bytes when it changed.

The Caddy snippet in the same section was already correct (no explicit Cache-Control, default revalidation), so it stays untouched.

CHANGELOG entry under Unreleased / Documentation. No code or behavior change.

This mirrors the same fix applied to Scriptor's docker/nginx.conf in scriptor#fix/uploads-cache-immutable (the bug surfaced there when re-uploading the same-named image kept showing the old one).

@bigin
bigin force-pushed the fix/uploads-cache-immutable branch from be4ff12 to 17f0729 Compare May 25, 2026 16:09
The nginx snippet in docs/deployment.md recommended
`Cache-Control: public, immutable` for `/uploads/`, which is wrong
for iManager's FileStorage layout.

FileStorage writes to `var/uploads/<itemId>/<fieldId>/<filename>`
keeping the user's original filename. Re-uploading a file under
the same name leaves the URL stable while the bytes change. With
`immutable` set, browsers serve the stale bytes for up to 30 days
(the `expires` window) and skip revalidation entirely.

Switch to `Cache-Control: public, must-revalidate` and add an
inline comment explaining the choice. The 30-day expires window
is kept; browsers now send `If-None-Match` on every hit and
nginx's built-in ETag answers 304 cheaply when the file is
unchanged, 200 with the new bytes when it changed.

The Caddy snippet in the same section was already correct (no
explicit Cache-Control, default revalidation), so it stays
untouched.

CHANGELOG entry under Unreleased / Documentation. No code or
behavior change.

This mirrors the same fix applied to Scriptor's docker/nginx.conf
in scriptor#fix/uploads-cache-immutable (the bug surfaced there
when re-uploading the same-named image kept showing the old one).
@bigin
bigin force-pushed the fix/uploads-cache-immutable branch from 17f0729 to bab4c85 Compare May 25, 2026 16:12
@bigin
bigin merged commit ca6d1d8 into main May 25, 2026
4 checks passed
@bigin
bigin deleted the fix/uploads-cache-immutable branch May 25, 2026 16:13
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