行业资讯
📅 2026/9/7 17:01:33
FastAPI 文档静态资源自定义指南:切换自定义 CDN 与自托管 Swagger UI / ReDoc 资产
FastAPI 文档静态资源自定义指南切换自定义 CDN 与自托管 Swagger UI / ReDoc 资产【免费下载链接】fastapiFastAPI framework, high performance, easy to learn, fast to code, ready for production项目地址: https://gitcode.com/GitHub_Trending/fa/fastapi本文基于 FastAPI 官方文档 Custom Docs UI Static Assets (Self-Hosting) 编写讲解如何摆脱 API 文档页面对公共 CDN 的默认依赖将 Swagger UI 与 ReDoc 所需的 JavaScript/CSS 文件指向自定义 CDN或完全自托管self-hosting到本应用内使文档在离线环境、内网环境中依然可用。读完本文你将掌握get_swagger_ui_html()、get_redoc_html()等 FastAPI 内置 HTML 生成函数的完整参数用法以及如何用StaticFiles挂载静态资源的完整可运行方案。1. 背景默认文档为什么依赖 CDNFastAPI 的 API 文档使用Swagger UI/docs和ReDoc/redoc两套前端它们各自需要若干 JavaScript 与 CSS 文件。默认情况下这些文件通过 CDN 加载——FastAPI 生成的文档 HTML 中只包含指向 CDN 的script与link标签浏览器直接从公共 CDN 拉取资源。从源码 fastapi/openapi/docs.py 可以确认默认值get_swagger_ui_html()的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.cssget_redoc_html()的redoc_js_url默认为https://cdn.jsdelivr.net/npm/redoc2/bundles/redoc.standalone.js并且默认通过 Google Fonts 加载字体with_google_fontsTrue。这意味着默认文档页的运行依赖外网可达。如果所在网络环境限制某些 URL例如公司内网、特定地区的网络限制就需要自定义文档静态资源的来源。官方文档给出了两种方案自定义 CDN把资源 URL 换成你信任/可达的另一个 CDN例如https://unpkg.com/自托管把资源文件下载到本地由同一个 FastAPI 应用自己提供静态文件服务实现完全离线可用。两种方案的前置步骤相同先禁用 FastAPI 的自动文档路由再手动创建文档的 path operation。2. 方案一使用自定义 CDN对应示例代码见 docs_src/custom_docs_ui/tutorial001_py310.py。2.1 禁用自动文档FastAPI 创建时会自动注册/docs、/redoc等文档路由它们使用的是默认 CDN。要替换资源来源需要把这些 URL 置为None来关闭自动文档from fastapi import FastAPI app FastAPI(docs_urlNone, redoc_urlNone)从源码 fastapi/applications.py 的setup()方法可以印证这一机制只有当self.openapi_url and self.docs_url同时为真时才会注册 Swagger UI 路由self.openapi_url and self.redoc_url为真时才会注册 ReDoc 路由。因此docs_urlNone, redoc_urlNone会让这两组自动路由完全不注册而/openapi.jsonopenapi_url保持不变这正是后续自定义文档页需要的 OpenAPI schema 来源。2.2 创建自定义文档 path operationFastAPI 把生成文档 HTML 的能力封装为可复用函数定义在 fastapi/openapi/docs.pyget_swagger_ui_html()生成 Swagger UI 的 HTML 页面get_redoc_html()生成 ReDoc 的 HTML 页面get_swagger_ui_oauth2_redirect_html()生成 OAuth2 重定向辅助页。关键参数说明均取自源码签名参数所属函数含义openapi_url两者文档页 HTML 加载 OpenAPI schema 的地址直接使用app.openapi_url即默认的/openapi.jsontitle两者HTMLtitle内容通常显示在浏览器标签页swagger_js_urlSwagger UI文档页加载JavaScript文件的 URL此处传入自定义 CDN 地址swagger_css_urlSwagger UI文档页加载CSS文件的 URL此处传入自定义 CDN 地址redoc_js_urlReDoc文档页加载 ReDocJavaScript文件的 URLoauth2_redirect_urlSwagger UIOAuth2 重定向地址使用app.swagger_ui_oauth2_redirect_url即可获得默认值swagger_favicon_url/redoc_favicon_url两者浏览器标签页的 favicon默认指向 FastAPI 官方图片可按需替换以换用https://unpkg.com/为例完整代码如下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) 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, )关于swagger_ui_redirect这个 path operation它是 OAuth2 场景的辅助路由。当 API 集成了 OAuth2 提供商后Swagger UI 会把浏览器弹到授权页授权完成后需要一个本地页面把凭据带回文档页Swagger UI 在幕后处理整个流程但必须有这个redirect辅助页配合。如果你的 API 完全不涉及 OAuth2可以省略该路由oauth2_redirect_url传None即可。2.3 添加测试接口并验证为方便确认功能正常添加一个普通 path operationapp.get(/users/{username}) async def read_user(username: str): return {message: fHello {username}}启动应用后访问http://127.0.0.1:8000/docs并刷新页面文档页的 JS/CSS 就会从你指定的新 CDN 加载OpenAPI schema 仍来自本应用的/openapi.json。3. 方案二自托管 JavaScript 与 CSS对应示例代码见 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 UI使用两个文件swagger-ui-bundle.js来自https://cdn.jsdelivr.net/npm/swagger-ui-dist5/swagger-ui-bundle.jsswagger-ui.css来自https://cdn.jsdelivr.net/npm/swagger-ui-dist5/swagger-ui.cssReDoc使用一个文件redoc.standalone.js来自https://cdn.jsdelivr.net/npm/redoc2/bundles/redoc.standalone.js放置完成后结构如下. ├── app │ ├── __init__.py │ ├── main.py └── static ├── redoc.standalone.js ├── swagger-ui-bundle.js └── swagger-ui.css3.3 由 FastAPI 提供静态文件只需两步导入StaticFiles再把一个StaticFiles()实例挂载mount到指定路径from fastapi.staticfiles import StaticFiles app FastAPI(docs_urlNone, redoc_urlNone) app.mount(/static, StaticFiles(directorystatic), namestatic)这里同样先通过docs_urlNone, redoc_urlNone禁用自动文档因为自动文档默认引用 CDN。启动应用后访问http://127.0.0.1:8000/static/redoc.standalone.js应当能看到一段很长的 ReDoc JavaScript 源码可能类似/*! For license information please see redoc.standalone.js.LICENSE.txt */ !function(e,t){objecttypeof exportsobjecttypeof module?module.exportst(require(null)): ...看到文件内容即说明静态文件服务正常、文件放置位置正确。3.4 让文档页引用本地资源与自定义 CDN 的方式完全相同只是 URL 从外部 CDN 换成本应用自己的静态路径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}}参数要点与 2.2 节相同区别在于swagger_js_url、swagger_css_url、redoc_js_url现在指向你自己应用正在提供的/static/路径。OAuth2 redirect 辅助路由的作用同上按需保留。3.5 验证离线可用启动应用断开 WiFi访问http://127.0.0.1:8000/docs并刷新。即使没有任何互联网连接文档页依然完整加载并可交互——因为 JS、CSS、OpenAPI schema 全部来自本地应用本身。4. 源码层面的原理佐证HTML 模板生成get_swagger_ui_html()在 fastapi/openapi/docs.py 中用 f-string 拼装完整 HTMLlink relstylesheet href{swagger_css_url}与script src{swagger_js_url}直接采用你传入的 URLget_redoc_html()则生成redoc spec-url...自定义元素加上script src{redoc_js_url}。因此换 CDN/自托管在机制上等价于替换这两个 URL 字符串。参数注入的转义处理源码中的_html_safe_json()会把参数序列化为 JSON 并转义、、防止内嵌script标签时的注入问题swagger_ui_parameters会与swagger_ui_default_parameters包含dom_id、layout、deepLinking等默认配置合并后注入页面。自动文档的注册逻辑fastapi/applications.py 的setup()中Swagger UI、OAuth2 redirect、ReDoc 三类路由分别在docs_url、swagger_ui_oauth2_redirect_url、redoc_url非空时注册且生成的页面会拼接root_path前缀以适配子路径部署——手动创建自定义文档时若应用带root_path可参考此逻辑自行处理。测试用例tests/test_local_docs.py 用inspect.signature取出各 URL 参数的默认值断言默认 CDN 地址确实出现在生成的 HTML 中同时用自定义 URL 验证替换生效此外还断言 ReDoc HTML 默认包含 Google Fonts、with_google_fontsFalse时不含——后者对自托管离线场景是一个值得注意的细节ReDoc 默认仍会尝试加载 Google Fonts追求完全离线时可以显式传with_google_fontsFalse。5. 小结目标关键操作换用其他 CDNFastAPI(docs_urlNone, redoc_urlNone)禁用自动文档用get_swagger_ui_html()/get_redoc_html()自建文档路由传入自定义swagger_js_url/swagger_css_url/redoc_js_url自托管离线资源额外app.mount(/static, StaticFiles(directorystatic))把三个前端文件放入static/URL 改为/static/...两条路线复用同一套内置函数仅资源 URL 不同/openapi.json保持由本应用提供因此文档的数据源始终来自自己的 API可复制可运行的完整示例分别位于 docs_src/custom_docs_ui/tutorial001_py310.py 与 docs_src/custom_docs_ui/tutorial002_py310.py。【免费下载链接】fastapiFastAPI framework, high performance, easy to learn, fast to code, ready for production项目地址: https://gitcode.com/GitHub_Trending/fa/fastapi创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考