FastAPI中如何用include_in_schema实现条件路由隐藏多文档接口
问题
我通过挂载子应用在FastAPI中实现了两个Swagger文档:内部开发者用的/docs,外部客户用的/external_API/docs,二者共享同一路由router。我想仅在/external_API/docs里隐藏部分接口(比如/admin_something),/docs则显示全部接口。已知用include_in_schema=False能隐藏路由,但需要实现条件控制:访问外部文档时隐藏指定接口,访问内部文档时显示全部。我试过用判断root_path的自定义函数结合include_in_schema,但没成功,求可行的实现方案。
现有代码
main.py
from fastapi import FastAPI from route import router as users_router app = FastAPI() # 仅面向内部开发者的Swagger文档 app.include_router(users_router) externalAPI = FastAPI() # 仅面向外部客户的Swagger文档 externalAPI.include_router(users_router) # 将子应用挂载到主应用 app.mount("/external_API", externalAPI)
route.py
from fastapi import APIRouter router = APIRouter() @router.get('/admin_something', include_in_schema=True) def route_admin_use_only(): ... @router.get('/user_something', include_in_schema=True) def route_public_use(): ...
尝试过的自定义函数(未成功)
def only_internal(request : Request): """ 当root_path为空时返回True(表示显示所有路由) """ root_path = request.scope.get("root_path") if not root_path == "": return False return True
未成功的应用方式
# 期望访问"/external_API/docs"时隐藏该接口 @router.get('/admin_something', include_in_schema=only_internal) def route_admin_use_only(): ... # 期望该接口始终可见 @router.get('/user_something', include_in_schema=Depends(only_internal)) def route_public_use(): ...
可行实现方案
下面提供三种不同场景的解决方案,按需选择:
方案1:挂载时动态过滤接口(无需修改原路由)
核心是给外部应用复制一份路由,然后修改指定接口的include_in_schema属性,再挂载到外部应用上:
from fastapi import FastAPI from route import router as base_router # 内部应用:显示全部接口 app = FastAPI() app.include_router(base_router) # 外部应用:复制路由并隐藏指定接口 externalAPI = FastAPI() # 复制基础路由的配置 external_router = base_router.__class__(prefix=base_router.prefix, tags=base_router.tags) for route in base_router.routes: # 匹配需要隐藏的接口路径 if route.path == "/admin_something": route.include_in_schema = False external_router.routes.append(route) externalAPI.include_router(external_router) app.mount("/external_API", externalAPI)
方案2:自定义OpenAPI文档生成逻辑(动态过滤)
直接修改外部应用的OpenAPI文档生成逻辑,在生成Swagger时删除指定接口:
from fastapi import FastAPI, Request from route import router as users_router app = FastAPI() app.include_router(users_router) externalAPI = FastAPI() externalAPI.include_router(users_router) # 自定义外部应用的OpenAPI生成函数 def custom_openapi(): if externalAPI.openapi_schema: return externalAPI.openapi_schema # 生成原始OpenAPI结构 openapi_schema = externalAPI.openapi() # 过滤掉需要隐藏的接口路径 paths_to_remove = [path for path in openapi_schema["paths"] if "/admin_something" in path] for path in paths_to_remove: del openapi_schema["paths"][path] externalAPI.openapi_schema = openapi_schema return openapi_schema externalAPI.openapi = custom_openapi app.mount("/external_API", externalAPI)
方案3:拆分路由(最直观易维护)
把内部专用接口和公共接口拆分到不同的APIRouter中,内部应用挂载两个路由,外部应用只挂载公共路由:
修改后的route.py
from fastapi import APIRouter # 公共路由:内部、外部均可见 public_router = APIRouter() @public_router.get('/user_something', include_in_schema=True) def route_public_use(): ... # 内部专用路由:仅内部可见 internal_router = APIRouter() @internal_router.get('/admin_something', include_in_schema=True) def route_admin_use_only(): ...
修改后的main.py
from fastapi import FastAPI from route import public_router, internal_router # 内部应用:挂载公共+内部路由 app = FastAPI() app.include_router(public_router) app.include_router(internal_router) # 外部应用:仅挂载公共路由 externalAPI = FastAPI() externalAPI.include_router(public_router) app.mount("/external_API", externalAPI)
内容的提问来源于stack exchange,提问作者MyHeadOverflow
相关产品推荐
相关产品推荐

