49 lines
1.6 KiB
Python
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")
|