1 Commits
Author SHA1 Message Date
sneak fe2deec5bb Page is sent with Cache-Control: no-cache (closes #141)
check / check (push) Canceled after 0s
nginx sent index.html with no Cache-Control, so a browser could keep
it after a deploy and ask for hashed assets the new build no longer
has, and show an empty page. location / now adds Cache-Control:
no-cache, which covers its try_files fallback to /index.html, and
includes security-headers.conf again, since its own add_header drops
the server's. /assets/ and the locations passed to the backend are
unchanged.

script/frontend-viewport-test fails unless / and a path that falls
back to the page carry Cache-Control: no-cache and
Content-Security-Policy, which comes from the same file as the other
security headers.

Model: opus-5-5
2026-10-19 00:41:51 +00:00
2 changed files with 15 additions and 16 deletions
+7 -7
View File
@@ -26,13 +26,13 @@ Run `make frontend-viewport-test` in CI as its own step; it is not part of
keeps a copy checks with the server that it is current before using it again. keeps a copy checks with the server that it is current before using it again.
The page went out with no `Cache-Control`, so a browser could keep it after a The page went out with no `Cache-Control`, so a browser could keep it after a
deploy and ask for files under `/assets/` that the new build no longer has, deploy and ask for files under `/assets/` that the new build no longer has,
and show an empty page. A path that `location /` answers with the page through and show an empty page. A path with no file of its own falls back to the page
its `try_files` fallback gets the same header. `location /` now includes the and gets the same header. `location /` now includes the security headers
security headers again, as `/assets/` does, since its own `add_header` drops again, as `/assets/` does, since its own `add_header` drops the server's.
the server's. `/assets/` keeps its immutable caching. `/assets/` keeps its immutable caching. `make frontend-viewport-test` fails
`make frontend-viewport-test` fails unless `/` and a path that falls back to unless `/` and a path that falls back to the page carry
the page carry `Cache-Control: no-cache` and `Content-Security-Policy`, which `Cache-Control: no-cache` and `Content-Security-Policy`, which comes from the
comes from the same file as the other security headers same file as the other security headers
- 2026-10-18: a browser that cannot format the header's clocks still probes - 2026-10-18: a browser that cannot format the header's clocks still probes
([#149](https://git.eeqj.de/sneak/netwatch/issues/149)). The clocks name the ([#149](https://git.eeqj.de/sneak/netwatch/issues/149)). The clocks name the
local time zone through `Intl.DateTimeFormat`'s `shortGeneric` option, which local time zone through `Intl.DateTimeFormat`'s `shortGeneric` option, which
+8 -9
View File
@@ -77,15 +77,14 @@ main() {
-v "$ROOT/configs/security-headers.conf:/etc/nginx/security-headers.conf:ro" \ -v "$ROOT/configs/security-headers.conf:/etc/nginx/security-headers.conf:ro" \
"$SERVER_IMAGE" > /dev/null "$SERVER_IMAGE" > /dev/null
# The page, and /no-such-page, which location / answers with the # The page, and a path with no file of its own, which falls back to
# page through its try_files fallback, must go out with # it, must go out with Cache-Control: no-cache. That add_header in
# Cache-Control: no-cache. That add_header in its location drops the # its location drops the server's own unless the location includes
# server's own unless the location includes the security headers # the security headers again; only Content-Security-Policy is
# again; only Content-Security-Policy is checked, as it comes from # checked, as it comes from the same file as the rest. curl tries up
# the same file as the rest. curl tries up to ten more times, a # to ten more times, a second apart, while nginx starts. It runs
# second apart, while nginx starts. It runs without -S, which would # without -S, which would print an error for every failed attempt,
# print an error for every failed attempt, even when a later one # even when a later one succeeds.
# succeeds.
for path in / /no-such-page; do for path in / /no-such-page; do
if ! headers="$(docker exec "$SERVER" curl -s -o /dev/null -D - \ if ! headers="$(docker exec "$SERVER" curl -s -o /dev/null -D - \
--retry 10 --retry-connrefused --retry-delay 1 \ --retry 10 --retry-connrefused --retry-delay 1 \