fastapi: 解决docs文档打开swaggerui时速度慢

一,原因

FastAPI 默认从国外的公共 CDN(如 cdn.jsdelivr.net)动态加载 Swagger 的 CSS 和 JS 静态资源文件。
在国内或特定的生产局域网环境下,由于网络阻断或延迟,就会导致页面卡死或加载长达十几秒。  
在生产环境中,最标准且最彻底的解决办法就是把这些 CDN 文件下载下来,由你的本地 FastAPI 服务器作为静态文件直接提供服务(即自托管 / Self-Hosting)。

二,解决:

1,下载ui文件

$ mkdir swagger
$ cd swagger/ 
$ curl -o swagger-ui.css  https://cdn.jsdelivr.net/npm/swagger-ui-dist@5/swagger-ui.css
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  174k  100  174k    0     0   172k      0  0:00:01  0:00:01 --:--:--  172k 
$ curl -o swagger-ui-bundle.js https://cdn.jsdelivr.net/npm/swagger-ui-dist@5/swagger-ui-bundle.js
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 1502k  100 1502k    0     0   127k      0  0:00:11  0:00:11 --:--:--  293k
$ curl -o favicon.png https://fastapi.tiangolo.com/img/favicon.png
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  5043  100  5043    0     0   8215      0 --:--:-- --:--:-- --:--:--  8213
$ ls
favicon.png  swagger-ui-bundle.js  swagger-ui.css

2,代码:

# 创建独立隔离的管理后台子应用
admin_app = FastAPI(
    title="管理后台系统",
    dependencies=[Depends(verify_admin_user),],  # 👈 核心:作为子应用全局依赖
    docs_url=None,     # 关闭自带的文档
)

'''
# 3. 自定义 /docs 接口,手动引用本地文件
@admin_app.get("/docs", include_in_schema=False)
async def custom_swagger_ui_html():
    return get_swagger_ui_html(
        openapi_url=admin_app.openapi_url,          # 使用 app 自身的 openapi 路由
        title=admin_app.title + " - 离线本地文档",
        swagger_js_url="/static/swagger/swagger-ui-bundle.js", # 指向本地挂载的 JS
        swagger_css_url="/static/swagger/swagger-ui.css",     # 指向本地挂载的 CSS
        swagger_favicon_url="/static/swagger/favicon.png"     # 指向本地挂载的图标
    )
'''


# 3. 自定义 /docs 接口(【核心修正点】)
@admin_app.get("/docs", include_in_schema=False)
async def custom_swagger_ui_html(request: Request):
    # 【核心修正 1】:动态获取子项目相对于父项目的根路径(比如 "/admin")
    root_path = request.scope.get("root_path", "")

    return get_swagger_ui_html(
        # 【核心修正 2】:让文档去找子项目自己的 openapi.json,而不是父项目的
        openapi_url=f"{root_path}{admin_app.openapi_url}",
        title=admin_app.title + " - Admin后台离线文档",
        # 【核心修正 3】:静态资源路径也必须拼接 root_path,否则会去根目录下找,导致404或找错
        swagger_js_url=f"/static/swagger/swagger-ui-bundle.js",
        swagger_css_url=f"/static/swagger/swagger-ui.css",
        swagger_favicon_url=f"/static/swagger/favicon.png"
    )

说明:代码中被注释掉的部分是单一项目的代码,
未被注释的是父子项目中当前项目的代码,
略有区别:增加了一个{root_path}

三,测试效果:

image

posted @ 2026-07-22 17:35  刘宏缔的架构森林  阅读(0)  评论(0)    收藏  举报