""" SPA Static Files Handler for FastAPI Serves Vue.js SPA while preserving API routes """ from fastapi.staticfiles import StaticFiles from starlette.responses import FileResponse from starlette.types import Scope import os class SPAStaticFiles(StaticFiles): """ Custom StaticFiles that serves index.html for non-API routes (SPA fallback) while allowing API routes to pass through """ async def get_response(self, path: str, scope: Scope): """ Handle requests: - API routes (/api/*) → 404 (let FastAPI handle) - Static files (exist) → serve file - Everything else → index.html (SPA routing) """ # Let API routes pass through to FastAPI if path.startswith("api/") or path.startswith("docs") or path.startswith("redoc") or path.startswith("openapi.json"): # Return 404 to let FastAPI handle it raise RuntimeError("Not found") try: # Try to serve the file return await super().get_response(path, scope) except Exception: # File not found → serve index.html for SPA routing return FileResponse(os.path.join(self.directory, "index.html"))