fix: force browser revalidation for JS/CSS/HTML static files

FastAPI StaticFiles sets Last-Modified/ETag but no Cache-Control, so
browsers use heuristic caching and can serve stale code after git pull.

Subclass StaticFiles to add 'Cache-Control: no-cache, must-revalidate'
on .html/.js/.css/.json files. ETag/Last-Modified still work, so
revalidation returns efficient 304 Not Modified when unchanged.

Other assets (images, fonts, tile textures) are unaffected and cache
normally.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Erik 2026-04-10 09:57:00 +02:00
parent 604d4376b4
commit 994bc618db

16
main.py
View file

@ -3316,4 +3316,18 @@ async def proxy_inventory_service(path: str, request: Request):
# Icons are now served from static/icons directory
# Serve SPA files (catch-all for frontend routes)
# Mount the single-page application frontend (static assets) at root path
app.mount("/", StaticFiles(directory="static", html=True), name="static")
#
# Force browsers to always revalidate static assets so bind-mounted file
# changes are picked up without a hard refresh. The ETag/Last-Modified
# headers already make revalidation efficient (304 responses).
class NoCacheStaticFiles(StaticFiles):
async def get_response(self, path, scope):
response = await super().get_response(path, scope)
# Force revalidation for HTML/JS/CSS/JSON so code changes show up
# immediately after git pull. Other assets (images, fonts) can cache.
if any(path.endswith(ext) for ext in (".html", ".js", ".css", ".json")):
response.headers["Cache-Control"] = "no-cache, must-revalidate"
return response
app.mount("/", NoCacheStaticFiles(directory="static", html=True), name="static")