feat: serve built frontend from backend with SPA fallback
This commit is contained in:
@@ -1,11 +1,16 @@
|
|||||||
from contextlib import asynccontextmanager
|
from contextlib import asynccontextmanager
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
from fastapi import FastAPI
|
from fastapi import FastAPI
|
||||||
|
from fastapi.responses import FileResponse
|
||||||
|
from fastapi.staticfiles import StaticFiles
|
||||||
|
|
||||||
import app.models # noqa: F401 — registers models on Base.metadata before create_all
|
import app.models # noqa: F401 — registers models on Base.metadata before create_all
|
||||||
from app.db import Base, engine
|
from app.db import Base, engine
|
||||||
from app.routes.auth import router as auth_router
|
from app.routes.auth import router as auth_router
|
||||||
|
|
||||||
|
FRONTEND_DIST = Path(__file__).resolve().parent.parent.parent / "frontend" / "dist"
|
||||||
|
|
||||||
|
|
||||||
@asynccontextmanager
|
@asynccontextmanager
|
||||||
async def lifespan(app: FastAPI):
|
async def lifespan(app: FastAPI):
|
||||||
@@ -21,3 +26,11 @@ app.include_router(auth_router)
|
|||||||
@app.get("/healthz")
|
@app.get("/healthz")
|
||||||
async def healthz():
|
async def healthz():
|
||||||
return {"status": "ok"}
|
return {"status": "ok"}
|
||||||
|
|
||||||
|
|
||||||
|
app.mount("/assets", StaticFiles(directory=FRONTEND_DIST / "assets"), name="frontend-assets")
|
||||||
|
|
||||||
|
|
||||||
|
@app.get("/{full_path:path}")
|
||||||
|
async def serve_spa(full_path: str):
|
||||||
|
return FileResponse(FRONTEND_DIST / "index.html")
|
||||||
|
|||||||
16
backend/tests/test_frontend_serving.py
Normal file
16
backend/tests/test_frontend_serving.py
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_unknown_path_serves_spa_index(client):
|
||||||
|
response = await client.get("/some/client/side/route")
|
||||||
|
assert response.status_code == 200
|
||||||
|
assert '<div id="root">' in response.text
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_auth_routes_still_work_alongside_spa_fallback(client):
|
||||||
|
response = await client.post(
|
||||||
|
"/auth/register", json={"username": "frontendcheck", "password": "spookyspooky"}
|
||||||
|
)
|
||||||
|
assert response.status_code == 201
|
||||||
Reference in New Issue
Block a user