fix(white-page): Service Worker Kill-Switch + Cache-Control no-cache für index.html

- /sw.js und /service-worker.js liefern jetzt einen Self-Unregister Service Worker
- index.html bekommt Cache-Control: no-cache, no-store, must-revalidate
- Fixt das wiederkehrende weiße-Seite-Problem nach Deploys
This commit is contained in:
Agent Zero
2026-08-21 19:05:02 +02:00
parent 37f6868328
commit f7d2abf967
+27 -2
View File
@@ -14,7 +14,7 @@ from contextlib import asynccontextmanager
import structlog import structlog
from fastapi import Depends, FastAPI, HTTPException, Request from fastapi import Depends, FastAPI, HTTPException, Request
from fastapi.middleware.cors import CORSMiddleware 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 fastapi.staticfiles import StaticFiles
from starlette.middleware.base import BaseHTTPMiddleware 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/") blocked_prefixes = ("var/log/", "error/", "error_log", "var/", "etc/", "proc/", "sys/")
if full_path.startswith(blocked_prefixes) or ".." in full_path: if full_path.startswith(blocked_prefixes) or ".." in full_path:
raise HTTPException(status_code=404, detail="Not Found") 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") index_path = os.path.join(frontend_dist, "index.html")
if os.path.isfile(index_path): # noqa: ASYNC240 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") raise HTTPException(status_code=404, detail="Frontend not built")
return app return app