commit 2925a3853d109ab3fec04c5cd559a23d0ce7c0b8 equwal <truex@equwal.com> 2026-09-21 16:48:03 -0700 Make the browser revalidate the engine scripts engine/job.js imports ./asr.js by bare path, so a browser could keep an old asr.js and run it with a new app.js. The old asr.js fetched the model from huggingface.co. The page, app.js and the engine modules now answer with Cache-Control: no-cache, and the ETag makes the check one round trip. The pinned files under /vendor/ may stay for a day.
backend/main.py | 8 ++++++++ tests/test_static_headers.py | 25 +++++++++++++++++++++++++ 2 files changed, 33 insertions(+)
diff --git a/backend/main.py b/backend/main.py index 80063b7..a6ee76e 100644 --- a/backend/main.py +++ b/backend/main.py @@ -137,6 +137,14 @@ async def cross_origin_isolation(request, call_next): response = await call_next(request) response.headers["Cross-Origin-Opener-Policy"] = "same-origin" response.headers["Cross-Origin-Embedder-Policy"] = "credentialless" + # The engine's modules import each other by bare path, so a browser that + # kept an old engine/asr.js would run it with a new app.js. Make each of + # them ask the server first (an ETag answers in one round trip); the + # pinned libraries and weights under /vendor/ may stay a day. + if request.url.path.startswith("/vendor/"): + response.headers["Cache-Control"] = "public, max-age=86400" + elif response.headers.get("content-type", "").startswith(("text/javascript", "text/html")): + response.headers["Cache-Control"] = "no-cache" return response diff --git a/tests/test_static_headers.py b/tests/test_static_headers.py new file mode 100644 index 0000000..4810d5d --- /dev/null +++ b/tests/test_static_headers.py @@ -0,0 +1,25 @@ +"""The headers on the static files: cross-origin isolation, and how long a +browser may keep each file.""" + +from __future__ import annotations + + +def test_page_is_cross_origin_isolated(client): + r = client.get("/") + assert r.headers["cross-origin-opener-policy"] == "same-origin" + assert r.headers["cross-origin-embedder-policy"] == "credentialless" + + +def test_engine_modules_are_revalidated_every_time(client): + # engine/job.js imports ./asr.js by bare path. A kept copy of one with a + # new copy of the other is a broken engine, so each must ask the server. + for path in ("/", "/app.js", "/engine/asr.js", "/engine/job.js"): + r = client.get(path) + assert r.status_code == 200, path + assert r.headers["cache-control"] == "no-cache", path + + +def test_vendor_files_may_be_kept(client): + r = client.get("/vendor/versions.json") + assert r.status_code == 200 + assert r.headers["cache-control"] == "public, max-age=86400"