FastAPI挂载根路由后,通配路由无法触发的问题
问题原因
你挂载的StaticFiles到根路径后,会优先处理所有非/api的请求。当请求的路径(比如/whtever)在静态文件夹中找不到对应文件时,StaticFiles直接返回404,不会触发后续的通配路由。
简洁解决方案
方案一:自定义静态文件处理类(推荐,与Node serve -s build逻辑一致)
通过继承StaticFiles重写响应逻辑,让404请求自动返回index.html,无需额外通配路由:
from fastapi import FastAPI, HTTPException from starlette.staticfiles import StaticFiles import pathlib api_app = secure_authenticated_app() # 你的已授权API应用 app = FastAPI() # 先挂载API路由 app.mount("/api", api_app, name="api") # 定义支持SPA路由的静态文件处理类 class SPAStaticFiles(StaticFiles): async def get_response(self, path: str, scope): try: return await super().get_response(path, scope) except HTTPException as exc: if exc.status_code == 404: # 404时返回index.html,交给前端路由处理 return await super().get_response("index.html", scope) raise # 获取React构建文件夹路径 client_folder_path = pathlib.Path(__file__).parent.absolute().joinpath("build") # 挂载自定义静态文件服务到根路径 app.mount("", SPAStaticFiles(directory=client_folder_path, html=True), name="client")
方案二:通配路由统一处理静态资源与SPA路由
如果不想自定义类,可通过通配路由判断请求是否为静态文件,是则返回文件,否则返回index.html:
from fastapi import FastAPI, Response import pathlib import mimetypes api_app = secure_authenticated_app() app = FastAPI() app.mount("/api", api_app, name="api") client_folder_path = pathlib.Path(__file__).parent.absolute().joinpath("build") @app.get("/{full_path:path}") async def serve_spa(full_path: str): file_path = client_folder_path / full_path # 处理静态资源请求 if file_path.exists() and file_path.is_file(): with open(file_path, "rb") as f: content = f.read() # 自动识别文件MIME类型 mime_type, _ = mimetypes.guess_type(file_path) return Response(content=content, media_type=mime_type or "application/octet-stream") # 非静态资源路径返回index.html with open(client_folder_path / "index.html", "r") as f: content = f.read() return Response(content=content, media_type="text/html")
内容的提问来源于stack exchange,提问作者grreeenn
相关产品推荐
相关产品推荐

