from contextlib import asynccontextmanager from pathlib import Path from fastapi import FastAPI from fastapi.staticfiles import StaticFiles from . import db, version from .api import fs, imports, libraries, requests, search @asynccontextmanager async def lifespan(app: FastAPI): db.init_db() yield app = FastAPI(title="wordarr", lifespan=lifespan) app.include_router(libraries.router) app.include_router(search.router) app.include_router(requests.router) app.include_router(imports.router) app.include_router(fs.router) @app.get("/api/version") def read_version(): return {"version": version.VERSION, "build": version.BUILD, "built_at": version.BUILT_AT} class RevalidatingStatics(StaticFiles): """Without a Cache-Control header the browser caches heuristically and does not ask again, so a redeployed app.js kept rendering the old UI. no-cache still allows the cached copy, it just has to be revalidated first - one 304 per file per load.""" def file_response(self, *args, **kwargs): # starlette passes these positionally resp = super().file_response(*args, **kwargs) resp.headers["Cache-Control"] = "no-cache" return resp static_dir = Path(__file__).parent.parent / "static" app.mount("/", RevalidatingStatics(directory=static_dir, html=True), name="static")