fix(spa): serve index.html for SvelteKit client-side routes
Release / release (push) Successful in 1m7s
Release / release (push) Successful in 1m7s
Deep-linking to non-root URLs like /settings or /notification-trackers
returned {"detail":"Not Found"} because StaticFiles(html=True) only
serves index.html for directory roots, not for arbitrary SPA routes.
Subclass StaticFiles with an SPA fallback: any 404 on a non-/api path
serves the root index.html, letting the SvelteKit router hydrate the
correct view on the client. Real /api/* 404s still bubble up as JSON
from FastAPI.
This commit is contained in:
@@ -158,7 +158,27 @@ async def health():
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
if _cfg.static_dir and Path(_cfg.static_dir).is_dir():
|
if _cfg.static_dir and Path(_cfg.static_dir).is_dir():
|
||||||
from fastapi.staticfiles import StaticFiles
|
from fastapi.staticfiles import StaticFiles
|
||||||
app.mount("/", StaticFiles(directory=_cfg.static_dir, html=True), name="frontend")
|
from starlette.responses import FileResponse
|
||||||
|
from starlette.exceptions import HTTPException as StarletteHTTPException
|
||||||
|
|
||||||
|
_static_dir = Path(_cfg.static_dir)
|
||||||
|
|
||||||
|
class SPAStaticFiles(StaticFiles):
|
||||||
|
"""StaticFiles that falls back to index.html for SvelteKit client-side routes.
|
||||||
|
|
||||||
|
Unknown paths return index.html so that deep links like /settings
|
||||||
|
hydrate the SPA, while /api/* and real asset 404s behave normally.
|
||||||
|
"""
|
||||||
|
|
||||||
|
async def get_response(self, path: str, scope):
|
||||||
|
try:
|
||||||
|
return await super().get_response(path, scope)
|
||||||
|
except StarletteHTTPException as exc:
|
||||||
|
if exc.status_code == 404 and not path.startswith("api/"):
|
||||||
|
return FileResponse(_static_dir / "index.html")
|
||||||
|
raise
|
||||||
|
|
||||||
|
app.mount("/", SPAStaticFiles(directory=_cfg.static_dir, html=True), name="frontend")
|
||||||
|
|
||||||
|
|
||||||
def run():
|
def run():
|
||||||
|
|||||||
Reference in New Issue
Block a user