diff --git a/app/main.py b/app/main.py index 41bf3da..7aa0c6b 100644 --- a/app/main.py +++ b/app/main.py @@ -14,7 +14,7 @@ from contextlib import asynccontextmanager import structlog from fastapi import Depends, FastAPI, HTTPException, Request from fastapi.middleware.cors import CORSMiddleware -from fastapi.responses import FileResponse, JSONResponse +from fastapi.responses import FileResponse, JSONResponse, PlainTextResponse from fastapi.staticfiles import StaticFiles from starlette.middleware.base import BaseHTTPMiddleware @@ -639,9 +639,34 @@ def create_app() -> FastAPI: blocked_prefixes = ("var/log/", "error/", "error_log", "var/", "etc/", "proc/", "sys/") if full_path.startswith(blocked_prefixes) or ".." in full_path: raise HTTPException(status_code=404, detail="Not Found") + + # Kill switch for old PWA service workers — return self-unregistering SW + if full_path in ("sw.js", "service-worker.js"): + return PlainTextResponse( + content="""// Kill switch — unregister all service workers +self.addEventListener('install', (e) => { self.skipWaiting(); }); +self.addEventListener('activate', (e) => { + e.waitUntil( + self.registration.unregister().then(() => { + console.log('Service Worker unregistered'); + return self.clients.claim(); + }) + ); +}); +self.addEventListener('fetch', (e) => { + e.respondWith(fetch(e.request).catch(() => new Response('', {status: 504}))); +}); +""", + media_type="application/javascript", + headers={"Cache-Control": "no-cache, no-store, must-revalidate"}, + ) + index_path = os.path.join(frontend_dist, "index.html") if os.path.isfile(index_path): # noqa: ASYNC240 - return FileResponse(index_path) + return FileResponse( + index_path, + headers={"Cache-Control": "no-cache, no-store, must-revalidate"}, + ) raise HTTPException(status_code=404, detail="Frontend not built") return app