Fix: move SPA catch-all route to end so API routes match first

The catch-all @app.get('/{full_path:path}') was defined before API routes,
causing GET requests for /api/* endpoints to be intercepted and served
the admin SPA index.html instead of the actual API response. Moving
the catch-all to after all API routes ensures proper route resolution.
This commit is contained in:
Leo
2026-05-22 15:02:00 -04:00
parent 90a426bc9e
commit cb71bcaaef
+15 -16
View File
@@ -23,7 +23,7 @@ from typing import Optional
from fastapi import FastAPI, HTTPException, Query, Request, UploadFile, File
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import JSONResponse, StreamingResponse
from fastapi.responses import FileResponse, JSONResponse, StreamingResponse
from fastapi.staticfiles import StaticFiles
from pydantic import BaseModel
@@ -355,21 +355,6 @@ app.add_middleware(
# Mount Cantaloupe sync routes
app.include_router(cantaloupe_router)
# Serve admin frontend SPA (single index.html, no external assets needed)
from fastapi.responses import FileResponse
FRONTEND_INDEX = Path(__file__).parent / "static" / "index.html"
@app.get("/")
@app.get("/{full_path:path}")
async def serve_frontend(full_path: str = ""):
"""Serve the admin SPA — all routes return index.html."""
if FRONTEND_INDEX.is_file():
return FileResponse(str(FRONTEND_INDEX))
return JSONResponse({"detail": "Frontend not found"}, status_code=404)
# ─── Auth Middleware ────────────────────────────────────────────────────────
@@ -1621,3 +1606,17 @@ def reset_database(request: Request):
raise HTTPException(status_code=500, detail=f"Reset failed: {str(e)}")
conn.close()
return {"detail": "Database reset complete — all tables recreated with seed data."}
# ─── SPA Frontend (catch-all — MUST be last route) ────────────────────────
FRONTEND_INDEX = Path(__file__).parent / "static" / "index.html"
@app.get("/")
@app.get("/{full_path:path}")
async def serve_frontend(full_path: str = ""):
"""Serve the admin SPA — all routes return index.html."""
if FRONTEND_INDEX.is_file():
return FileResponse(str(FRONTEND_INDEX))
return JSONResponse({"detail": "Frontend not found"}, status_code=404)