Files
planer/backend/server.py
2026-07-22 16:12:23 +02:00

49 lines
1.6 KiB
Python

"""FastAPI-Server des Planers (Phase 2).
Start: `uvicorn server:app --port 8100` aus backend/ — OHNE --reload: der Reload killt
laufende Scans im eigenen Prozess (Creator-Lehre; siehe README, Selbst-Änderungs-Regel).
"""
import sys
from contextlib import asynccontextmanager
from pathlib import Path
sys.path.insert(0, str(Path(__file__).resolve().parent))
from fastapi import FastAPI # noqa: E402
from fastapi.staticfiles import StaticFiles # noqa: E402
from starlette.responses import Response # noqa: E402
import agents # noqa: E402
import config # noqa: E402
import database as db # noqa: E402
from routes import router # noqa: E402
FRONTEND_DIST = config.PROJECT_ROOT / "frontend" / "dist"
@asynccontextmanager
async def lifespan(app: FastAPI):
await db.init_db()
agents.on_event = db.add_event
yield
await db.close_db()
class CachedStatic(StaticFiles):
"""assets/ = unveränderlich (gehashte Namen), index.html = nie cachen."""
def file_response(self, full_path, stat_result, scope, status_code=200) -> Response:
resp = super().file_response(full_path, stat_result, scope, status_code)
pfad = str(full_path)
if "/assets/" in pfad:
resp.headers["Cache-Control"] = "public, max-age=31536000, immutable"
elif pfad.endswith("index.html"):
resp.headers["Cache-Control"] = "no-cache"
return resp
app = FastAPI(title="Planer", lifespan=lifespan)
app.include_router(router)
if FRONTEND_DIST.exists():
app.mount("/", CachedStatic(directory=FRONTEND_DIST, html=True), name="frontend")