动态添加FastAPI端点时如何更新Swagger UI?
FastAPI动态端点同步更新Swagger UI的实现方案
核心原理:触发OpenAPI Schema重新生成
FastAPI的Swagger UI依赖缓存的OpenAPI Schema,要更新Swagger必须强制重新生成该Schema:
- 执行
app.openapi_schema = None清除缓存的Schema - 调用
app.setup()重新收集所有路由并生成新的Schema
这两步能实现刷新Swagger页面时看到更新后的端点,若需实现前端自动强制刷新,则需额外处理。
1. 基础版:手动刷新页面生效的实现
在你现有代码基础上,给增删端点的逻辑加入Schema重置步骤即可:
import fastapi import uvicorn from uvicorn.config import LOGGING_CONFIG app = fastapi.FastAPI() def update_swagger(): # 清除缓存的OpenAPI Schema app.openapi_schema = None # 重新初始化路由收集 app.setup() @app.get("/add") async def add(name: str): async def dynamic_controller(): return f"dynamic: {name}" app.add_api_route(f"/dyn/{name}", dynamic_controller, methods=["GET"]) update_swagger() # 新增Schema更新逻辑 return "ok" def route_matches(route, name): return route.path_format == f"/dyn/{name}" @app.get("/remove") async def remove(name: str): for i, r in enumerate(app.router.routes): if route_matches(r, name): del app.router.routes[i] update_swagger() # 新增Schema更新逻辑 return "ok" return "not found" def main(): uvicorn.run("dynamic_router:app", host="0.0.0.0", workers=1, log_config=LOGGING_CONFIG, port=5000) if __name__ == "__main__": main()
修改后,每次增删端点后刷新Swagger UI(默认路径/docs),即可看到最新的端点列表。
2. 进阶版:实现Swagger UI自动强制刷新
要让Swagger页面自动感知端点变化并刷新,可通过以下两种方案实现:
方案A:WebSocket推送更新通知
后端新增WebSocket接口,端点变化时向前端推送刷新信号,前端Swagger页面监听信号后自动刷新:
# 在原代码中添加WebSocket相关逻辑 from fastapi import WebSocket, WebSocketDisconnect active_connections = [] @app.websocket("/ws") async def websocket_endpoint(websocket: WebSocket): await websocket.accept() active_connections.append(websocket) try: while True: await websocket.receive_text() except WebSocketDisconnect: active_connections.remove(websocket) # 修改update_swagger函数,添加推送逻辑 async def update_swagger(): app.openapi_schema = None app.setup() # 向所有连接的WebSocket客户端发送刷新指令 for connection in active_connections: await connection.send_text("refresh_swagger")
然后自定义FastAPI的Swagger文档模板,在模板中加入WebSocket监听代码,收到信号时调用location.reload()刷新页面。
方案B:定时轮询后端端点列表
若不想使用WebSocket,可让前端定时请求后端的端点列表接口,对比本地缓存的端点信息,发现变化时自动刷新:
- 后端新增接口返回当前所有动态端点:
@app.get("/dyn/routes") async def get_dynamic_routes(): return {"routes": [r.path_format for r in app.router.routes if r.path_format.startswith("/dyn/")]}
- 自定义Swagger模板,添加JavaScript定时轮询逻辑(比如每5秒请求一次
/dyn/routes),对比前后结果,若不同则触发页面刷新。
3. Router机制下的适配说明
你在编辑2中使用APIRouter的方案逻辑是正确的,若未看到Swagger更新,可能是浏览器缓存了旧的OpenAPI Schema,此时可通过以下方式验证:
- 强制刷新浏览器(Ctrl+F5)
- 点击Swagger页面右上角的「Reload」按钮
该方案中update_swagger()函数的逻辑完全有效,app.setup()会重新收集所有已注册的Router路由信息。
关键注意事项
- 必须使用单worker模式(代码中
workers=1),多worker环境下每个worker的路由状态独立,动态增删仅会影响当前worker - 若需Swagger正确展示动态端点的参数、响应模型等信息,需在调用
app.add_api_route()时完整定义这些元数据
内容的提问来源于stack exchange,提问作者GregoirePelegrin
相关产品推荐
相关产品推荐

