P0: Add StaticFiles mount + root redirect to install wizard

Critical fix: FastAPI was not serving any static files, causing all
frontend pages (install.html, login.html, etc.) to return 404.

Changes:
- Add StaticFiles mount at /app/ for web/app/ directory (html=True)
- Redirect root path / to /app/install.html in install mode
- Remove redundant "/" path bypass in InstallModeMiddleware
- Production Nginx still serves static files directly (no conflict)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Your Name
2026-05-22 12:24:32 +08:00
parent dfc37f6e90
commit cea5730804
+13 -2
View File
@@ -25,6 +25,7 @@ from pathlib import Path
from fastapi import FastAPI, Request, Response
from fastapi.middleware.cors import CORSMiddleware
from fastapi.staticfiles import StaticFiles
from starlette.middleware.base import BaseHTTPMiddleware
from server.config import settings
@@ -268,10 +269,14 @@ class InstallModeMiddleware(BaseHTTPMiddleware):
async def dispatch(self, request: Request, call_next):
if INSTALL_MODE:
path = request.url.path
# Redirect root to install wizard
if path == "/":
from fastapi.responses import RedirectResponse
return RedirectResponse(url="/app/install.html")
# Allow: install API, static files, health check
if path.startswith("/api/install/") or path.startswith("/app/") or path == "/health":
return await call_next(request)
if path == "/" or path.startswith("/ws/"):
if path.startswith("/ws/"):
return await call_next(request)
# Block everything else
from fastapi.responses import JSONResponse
@@ -327,4 +332,10 @@ app.include_router(webssh_router)
app.include_router(sync_v2_router)
# Global Search
app.include_router(search_router)
app.include_router(search_router)
# ── Static files: serve web/app/ at /app/ (HTML pages + JS/CSS assets) ──
# In production, Nginx serves these directly; this is for dev/standalone mode.
WEB_APP_DIR = ROOT_DIR / "web" / "app"
if WEB_APP_DIR.is_dir():
app.mount("/app", StaticFiles(directory=str(WEB_APP_DIR), html=True), name="static_app")