import os from fastapi import FastAPI, HTTPException from fastapi.responses import FileResponse from fastapi.staticfiles import StaticFiles from plugin.base import Plugin from uvicorn.server import logger class SpaProxy(Plugin): def __init__(self, app: FastAPI, dist: str = "dist"): self.app = app self.dist = dist self.name = "SPA Proxy" self.version = "1.0.0" def install(self): # --- [新增] 挂载前端静态文件 -- frontend_dir = os.path.join(os.getcwd(), self.dist) if not os.path.isdir(frontend_dir): return # 1. 挂载静态资源(如 /assets/...) assets_dir = os.path.join(frontend_dir, "assets") if os.path.isdir(assets_dir): self.app.mount("/assets", StaticFiles(directory=assets_dir), name="assets") # 2. 【关键】兜底路由:处理所有未被 API 匹配的路径(支持前端路由如 /analysis) @self.app.get("/{full_path:path}") async def serve_frontend(full_path: str): # 如果请求的是 API 路径,不应走到这里(因为 API 路由已先注册) index_path = os.path.join(frontend_dir, "index.html") if os.path.isfile(index_path): return FileResponse(index_path) raise HTTPException(status_code=404, detail="Frontend not found") # 3. 显式处理根路径(可选,但更清晰) @self.app.get("/") async def root(): return await serve_frontend("") # self.app.add_api_route( # "/{full_path:path}", # serve_frontend, # methods=["GET"], # response_class=FileResponse, # ) logger.info(f"前端静态文件挂载: {frontend_dir} ✅")