资讯动态

FastAPI 文档 UI 静态资源自定义:切换 CDN 与完全离线自托管

发布时间:2026/9/9 12:55:43 来源:尧图企业网站定制
FastAPI 文档 UI 静态资源自定义切换 CDN 与完全离线自托管【免费下载链接】fastapiFastAPI framework, high performance, easy to learn, fast to code, ready for production项目地址: https://gitcode.com/GitHub_Trending/fa/fastapiFastAPI 的交互式 API 文档由Swagger UI默认位于/docs与ReDoc默认位于/redoc渲染二者都需要加载若干 JavaScript 与 CSS 文件默认从公共 CDN 拉取。当你的部署环境无法访问默认 CDN或需要在内网、离线环境中使用文档时你可以利用 docs/ja/docs/how-to/custom-docs-ui-assets.md 介绍的两种方案——切换自定义 CDN与本地静态文件自托管——来完全掌控这些资源。读完本文你将掌握如何关闭 FastAPI 内置的文档路由、用内部 HTML 生成函数重建文档页面以及如何在同一个 FastAPI 应用中挂载StaticFiles实现断网也能看文档。一、背景文档页面为什么要加载资源Swagger UI 与 ReDoc 本质上是运行在浏览器里的前端单页应用它们需要一个渲染外壳一段 HTMLHTML 里再通过script、link引用一套 JS/CSS 来获得交互能力。打开 fastapi/applications.py 可以看到 FastAPI 应用在构造时的相关默认值参数默认值说明docs_url/docsSwagger UI 文档路由设为None可关闭redoc_url/redocReDoc 文档路由设为None可关闭openapi_url/openapi.jsonOpenAPI schema 路由设为None会连带自动禁用文档swagger_ui_oauth2_redirect_url/docs/oauth2-redirectSwagger UI 的 OAuth2 回调辅助页而 JS/CSS 的具体来源定义在 fastapi/openapi/docs.py 的函数默认参数中例如swagger_js_url默认https://cdn.jsdelivr.net/npm/swagger-ui-dist5/swagger-ui-bundle.jsswagger_css_url默认https://cdn.jsdelivr.net/npm/swagger-ui-dist5/swagger-ui.cssredoc_js_url默认https://cdn.jsdelivr.net/npm/redoc2/bundles/redoc.standalone.js也就是说只要替换这几个 URL就能把文档资源搬到你指定的任何位置。二、方案一让文档加载自定义 CDN适用场景默认cdn.jsdelivr.net在你的网络环境下不可达例如某些 URL 受限的地区或你希望统一走公司内部 CDN 以提升加载速度。改用https://unpkg.com/是最常见的例子。2.1 关闭自动文档路由FastAPI 创建应用时会自动注册/docs、/redoc路由见 fastapi/applications.py 的setup()方法并把这些路由的 HTML 生成逻辑连同默认 CDN URL 一起固定下来。因此第一步是把它们关掉改成手动接管from fastapi import FastAPI from fastapi.openapi.docs import ( get_redoc_html, get_swagger_ui_html, get_swagger_ui_oauth2_redirect_html, ) app FastAPI(docs_urlNone, redoc_urlNone)注意docs_urlNone与redoc_urlNone分别关掉两个文档入口openapi_url即/openapi.json仍然保留。从源码看文档路由的注册条件是if self.openapi_url and self.docs_url/if self.openapi_url and self.redoc_url所以只要你保留openapi_url后续手写的文档页面依然能通过app.openapi_url拿到 schema 地址。2.2 用内部 HTML 生成函数重建文档页关闭自动文档后需要自己注册/docs、/redoc两个path operation。FastAPI 在fastapi.openapi.docs模块里暴露了三个可复用的内部函数定义见 fastapi/openapi/docs.py函数作用get_swagger_ui_html(...)返回加载 Swagger UI 的HTMLResponseget_swagger_ui_oauth2_redirect_html()返回 Swagger UI 的 OAuth2 跳转辅助页HTMLResponseget_redoc_html(...)返回加载 ReDoc 的HTMLResponseget_swagger_ui_html的关键参数如下Swagger UI 侧openapi_url文档 HTML 去拉取 OpenAPI schema 的 URL这里直接复用app.openapi_urltitle页面标题通常用app.title拼接后缀oauth2_redirect_urlOAuth2 回调地址默认值可直接用app.swagger_ui_oauth2_redirect_urlswagger_js_urlSwagger UI 的JavaScript文件 URL即你替换成自定义 CDN 的那一项swagger_css_urlSwagger UI 的CSS文件 URL同样换成自定义 CDN。ReDoc 侧大同小异唯一的资源参数是redoc_js_url。完整实现对应 docs_src/custom_docs_ui/tutorial001_py310.pyfrom fastapi import FastAPI from fastapi.openapi.docs import ( get_redoc_html, get_swagger_ui_html, get_swagger_ui_oauth2_redirect_html, ) app FastAPI(docs_urlNone, redoc_urlNone) app.get(/docs, include_in_schemaFalse) async def custom_swagger_ui_html(): return get_swagger_ui_html( openapi_urlapp.openapi_url, titleapp.title - Swagger UI, oauth2_redirect_urlapp.swagger_ui_oauth2_redirect_url, swagger_js_urlhttps://unpkg.com/swagger-ui-dist5/swagger-ui-bundle.js, swagger_css_urlhttps://unpkg.com/swagger-ui-dist5/swagger-ui.css, ) app.get(app.swagger_ui_oauth2_redirect_url, include_in_schemaFalse) async def swagger_ui_redirect(): return get_swagger_ui_oauth2_redirect_html() app.get(/redoc, include_in_schemaFalse) async def redoc_html(): return get_redoc_html( openapi_urlapp.openapi_url, titleapp.title - ReDoc, redoc_js_urlhttps://unpkg.com/redoc2/bundles/redoc.standalone.js, )几点实现细节include_in_schemaFalse文档路由本身不应出现在生成的 OpenAPI schema / API 文档列表里OAuth2 回调路由的路径直接取app.swagger_ui_oauth2_redirect_url默认/docs/oauth2-redirect因此只要使用docs_urlNone时也会一并关闭、需要手工补回app.get(app.swagger_ui_oauth2_redirect_url, ...)意味着注册路径来自 FastAPI 实例属性而不是写死字符串便于后续统一修改。2.3 为什么要保留 OAuth2 跳转页get_swagger_ui_html生成的 HTML 里当传入oauth2_redirect_url时会拼接出oauth2RedirectUrl: window.location.origin ...配置。当你的 API 对接了 OAuth2 提供方后文档页上的Authorize授权流程需要先把浏览器带到认证服务器拿到凭据后再跳回文档页继续交互——Swagger UI 在后台完成这一过程而跳回这一步依赖的就是/docs/oauth2-redirect这个辅助页。因此只要 Swagger UI 需要支持 OAuth2 授权就必须保留这个路由。2.4 加一个普通接口用于验证为了确认改动没有破坏应用本身再注册一个普通的path operationapp.get(/users/{username}) async def read_user(username: str): return {message: fHello {username}}2.5 验证效果启动应用后访问 http://127.0.0.1:8000/docs在开发者工具中观察 Network 面板可以看到swagger-ui-bundle.js等资源是从unpkg.com加载的。仓库自带的测试也验证了这一行为见 tests/test_tutorial/test_custom_docs_ui/test_tutorial001.py测试通过断言响应文本中包含https://unpkg.com/swagger-ui-dist5/swagger-ui-bundle.js、https://unpkg.com/swagger-ui-dist5/swagger-ui.css等 URL 来确认自定义 CDN 已生效同时验证/docs/oauth2-redirect返回的是 Swagger UI 的 OAuth2 跳转脚本。三、方案二静态文件完全本地自托管离线可用适用场景应用运行在无法访问互联网的离线环境或隔离内网连 CDN 也够不到却仍需要完整的交互式 API 文档。思路很简单把文档需要的 JS/CSS 文件下载到项目本地用 FastAPI 自己的StaticFiles把它当成普通静态资源对外提供再让文档 HTML 的swagger_js_url等参数指向本站地址。对应示例见 docs_src/custom_docs_ui/tutorial002_py310.py。3.1 项目文件结构假设项目现在长这样. ├── app │ ├── __init__.py │ ├── main.py在项目根目录新建一个存放静态文件的static/目录. ├── app │ ├── __init__.py │ ├── main.py └── static/3.2 下载所需文件在你的开发机有网环境上把下列文件下载到static/目录——可直接用浏览器右键链接另存为文件名必须保持与下表一致用途文件获取地址Swagger UIswagger-ui-bundle.jshttps://cdn.jsdelivr.net/npm/swagger-ui-dist5/swagger-ui-bundle.jsSwagger UIswagger-ui.csshttps://cdn.jsdelivr.net/npm/swagger-ui-dist5/swagger-ui.cssReDocredoc.standalone.jshttps://cdn.jsdelivr.net/npm/redoc2/bundles/redoc.standalone.js完成后目录应为. ├── app │ ├── __init__.py │ ├── main.py └── static ├── redoc.standalone.js ├── swagger-ui-bundle.js └── swagger-ui.css说明这三个文件即上文中get_swagger_ui_html/get_redoc_html默认参数的本地版本下载版本号对齐源码中的默认值swagger-ui-dist5、redoc2即可保证功能一致。3.3 用 StaticFiles 挂载静态目录在main.py中导入并挂载StaticFilesfrom fastapi.staticfiles import StaticFiles app FastAPI(docs_urlNone, redoc_urlNone) app.mount(/static, StaticFiles(directorystatic), namestatic)app.mount(/static, ...)会把应用内static目录下的所有文件映射到 URL 前缀/static/下namestatic用于在模板或反向解析中引用这个挂载点。3.4 先验证静态文件能否访问启动应用访问 http://127.0.0.1:8000/static/redoc.standalone.js。浏览器应返回一段很长的压缩 JavaScript其开头类似/*! For license information please see redoc.standalone.js.LICENSE.txt */ !function(e,t){objecttypeof exportsobjecttypeof module?module.exportst(require(null)): ...能看到这段内容说明两件事应用能正确提供静态文件、文件也已放在正确位置。3.5 关闭自动文档把 URL 指向本站同样先把自动文档关掉docs_urlNone, redoc_urlNone然后像方案一那样重建文档路由区别在于这次资源 URL 写的是本站路径from fastapi import FastAPI from fastapi.openapi.docs import ( get_redoc_html, get_swagger_ui_html, get_swagger_ui_oauth2_redirect_html, ) from fastapi.staticfiles import StaticFiles app FastAPI(docs_urlNone, redoc_urlNone) app.mount(/static, StaticFiles(directorystatic), namestatic) app.get(/docs, include_in_schemaFalse) async def custom_swagger_ui_html(): return get_swagger_ui_html( openapi_urlapp.openapi_url, titleapp.title - Swagger UI, oauth2_redirect_urlapp.swagger_ui_oauth2_redirect_url, swagger_js_url/static/swagger-ui-bundle.js, swagger_css_url/static/swagger-ui.css, ) app.get(app.swagger_ui_oauth2_redirect_url, include_in_schemaFalse) async def swagger_ui_redirect(): return get_swagger_ui_oauth2_redirect_html() app.get(/redoc, include_in_schemaFalse) async def redoc_html(): return get_redoc_html( openapi_urlapp.openapi_url, titleapp.title - ReDoc, redoc_js_url/static/redoc.standalone.js, ) app.get(/users/{username}) async def read_user(username: str): return {message: fHello {username}}仓库测试 tests/test_tutorial/test_custom_docs_ui/test_tutorial002.py 同样验证了这一行为它断言/docs响应中包含/static/swagger-ui-bundle.js、/static/swagger-ui.css/redoc响应中包含/static/redoc.standalone.js并验证/users/john业务接口照常工作。3.6 离线验证关闭本机网络如断开 WiFi再次访问 http://127.0.0.1:8000/docs 并刷新页面——只要浏览器没把资源缓存掉、也确实断网页面仍能正常渲染出可交互的 API 文档。至此文档的 JS/CSS 已完全不依赖外部网络。3.7 追求零外网请求时的补充细节如果对完全离线要求严格从 fastapi/openapi/docs.py 的默认参数可以看出还有两处漏网的外部引用值得一并处理get_redoc_html的with_google_fonts参数默认是True生成的 ReDoc HTML 会额外引入https://fonts.googleapis.com/...的字体样式表。完全离线时可在调用处显式传with_google_fontsFalse关闭或接受文档可用、字体回退为默认的效果get_swagger_ui_html的swagger_favicon_url默认指向 FastAPI 官网的 favicon 图片get_redoc_html的redoc_favicon_url同理。介意的话可把 favicon 一并放进static/并传本地路径实现真正全站零外链。这些选项在你不干预时都不影响本教程的离线渲染结果但它们决定了是否仍存在个别发往公网的请求。四、底层原理路由注册与 HTML 生成理解为什么这样改能生效能帮你应对更复杂的定制需求。路由注册时机。FastAPI 的setup()方法fastapi/applications.py在初始化阶段按条件注册内置路由若openapi_url存在注册/openapi.json路由若openapi_url与docs_url同时存在调用get_swagger_ui_html并带上init_oauth、swagger_ui_parameters等配置注册 Swagger UI同时注册 OAuth2 跳转路由若openapi_url与redoc_url同时存在调用get_redoc_html注册 ReDoc。因此把docs_url、redoc_url设为None等于取消了这些自动路由而你自己写的装饰器路由随后接管同名路径——由于include_in_schemaFalse也不会污染 schema。HTML 的生成方式。get_swagger_ui_htmlfastapi/openapi/docs.py本质上是按模板拼接字符串把openapi_url塞进url: ...、把swagger_css_url/swagger_js_url塞进link与script src、把oauth2_redirect_url拼成oauth2RedirectUrl最终返回HTMLResponseget_redoc_html则生成带redoc spec-url...标签与redoc.standalone.js引用的页面。这也是为什么换一个 URL 参数就能让整个文档资源源切换——它们只是生成 HTML 时的字符串插值。可进一步定制的参数。在源码中get_swagger_ui_html还支持swagger_ui_parameters默认合并dom_id、layout、deepLinking等一组swagger_ui_default_parameters与init_oauth这些与本文主题相关的扩展能力在 fastapi/openapi/docs.py 中都有完整定义如需调整 Swagger UI 行为例如默认展开状态、OAuth 初始化选项可直接查阅。五、运行与回归验证本地运行两个示例示例代码位于 docs_src/custom_docs_ui/ 目录分别对应两个tutorial*_py310.pyfastapi dev docs_src/custom_docs_ui/tutorial001_py310.py或使用 uvicornuvicorn docs_src.custom_docs_ui.tutorial002_py310:app --reload若想跑仓库自带的回归测试可执行pytest tests/test_tutorial/test_custom_docs_ui/两个测试文件分别覆盖了自定义 CDN与本地静态文件两条链路是验证改动正确性的快捷参考。小结想换文档资源源docs_urlNone, redoc_urlNone关闭自动文档 → 用get_swagger_ui_html/get_redoc_html重建路由 → 把swagger_js_url、swagger_css_url、redoc_js_url指向目标 CDN想彻底离线把上述三个文件下载进static/→app.mount(/static, StaticFiles(directorystatic), namestatic)→ 文档路由的 URL 参数改成/static/...别忘了保留/docs/oauth2-redirect路由以支持 Swagger UI 的 OAuth2 授权流程追求零外网请求时可顺带处理with_google_fonts与 favicon 默认指向的外部资源。两种方案的完整可运行示例与配套测试都在本仓库内docs_src/custom_docs_ui/ 与 tests/test_tutorial/test_custom_docs_ui/可以直接对照源码做更深度的定制。【免费下载链接】fastapiFastAPI framework, high performance, easy to learn, fast to code, ready for production项目地址: https://gitcode.com/GitHub_Trending/fa/fastapi创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价