FastAPI生成OpenAPI.json后替换第三方文件,代码应放在哪里?
如何在FastAPI启动后自动替换默认OpenAPI Schema?
问题背景
FastAPI会自动生成并提供openapi.json访问接口,我需要将其替换为自定义的myopenapi.json文件。目前已有的替换代码如下:
from pathlib import Path import json app.openapi_schema = json.loads(Path(r"myopenapi.json").read_text())
如果把这段代码放在某个端点(比如/)中,调用该端点一次后,/docs界面会加载自定义的Schema,且原有端点仍能正常工作。但我希望在FastAPI完成配置、所有端点创建完成后自动完成替换,尝试将代码放在lifespan启动块中无效——执行到yield时,app.openapi_schema尚未生成。当前服务通过以下命令启动:
uvicorn.run(app, host=SERVER_HOST, port=SERVER_PORT, workers=1)
可行解决方案
方案1:所有路由定义完成后直接执行替换代码
FastAPI的路由是通过装饰器调用时注册的,只要将替换代码放在所有路由定义之后、启动命令之前,就能确保所有端点已注册完成,此时替换会直接生效,启动后访问/docs即可看到自定义Schema:
from pathlib import Path import json from fastapi import FastAPI app = FastAPI() # 先定义所有业务路由 @app.get("/") def read_root(): return {"Hello": "World"} @app.get("/items/{item_id}") def read_item(item_id: int): return {"item_id": item_id} # 所有路由注册完成后,加载自定义OpenAPI Schema app.openapi_schema = json.loads(Path("myopenapi.json").read_text()) # 启动服务 if __name__ == "__main__": import uvicorn uvicorn.run(app, host="0.0.0.0", port=8000, workers=1)
方案2:重写FastAPI的openapi()方法
如果需要更灵活的控制(比如动态加载Schema),可以重写app.openapi方法,直接返回自定义的Schema内容。这种方式会在第一次访问/docs或/openapi.json时加载自定义Schema,同样能满足启动后自动生效的需求:
from pathlib import Path import json from fastapi import FastAPI app = FastAPI() # 定义所有业务路由 @app.get("/") def read_root(): return {"Hello": "World"} # 重写openapi方法,返回自定义Schema def custom_openapi(): if app.openapi_schema: return app.openapi_schema # 加载自定义Schema文件 app.openapi_schema = json.loads(Path("myopenapi.json").read_text()) return app.openapi_schema app.openapi = custom_openapi # 启动服务 if __name__ == "__main__": import uvicorn uvicorn.run(app, host="0.0.0.0", port=8000, workers=1)
为什么lifespan中无效?
FastAPI默认采用懒加载生成openapi_schema——只有第一次访问/openapi.json或/docs时,才会调用默认的openapi()方法生成并缓存Schema。而lifespan的yield前阶段是应用启动但未处理任何请求的阶段,此时app.openapi_schema还未生成,替换操作自然无法生效。
内容的提问来源于stack exchange,提问作者576i
相关产品推荐
相关产品推荐

