前言
今天久违地打开了了github仓库,发现shu-s-project居然有十五个star!又引起我写代码的兴趣了,于是clone下来准备先加几个API。调试过程中突然发现fastapi自带的docs文档打不开,控制台看了一下原来是静态资源请求失败,由于众所周知的原因,jsdelivr
已经被屏蔽了,自然导致docs打开一片空白。
先在网上搜了一下解决方案,有的说直接把静态资源放到本地,有的说改fastapi源码,把CDN地址切换到其他可以访问的地址。这两种方案我都不喜欢,前者意味着可能每个项目都要搞一套静态资源,而且失去了CDN的意义(当然本地访问无所谓),后者更是下策,稍微升个级可能又失效了。Github上也有相关讨论,参见It is suggested to change the CDN of Swagger and Redoc、a parameter of FastAPI to alter base url of cdn.jsdelivr.net。经过考虑,我决定采用Beipy的方案,即直接在主程序中写一个函数,主动替换CDN地址,这样不用修改源码。代码如下:
from fastapi import applications
from fastapi.openapi.docs import get_swagger_ui_html
def swagger_monkey_patch(*args, **kwargs):
"""
Wrap the function which is generating the HTML for the /docs endpoint and
overwrite the default values for the swagger js and css.
"""
return get_swagger_ui_html(
*args, **kwargs,
swagger_js_url="https://unpkg.zhimg.com/swagger-ui-dist@3.29/swagger-ui-bundle.js",
swagger_css_url="https://unpkg.zhimg.com/swagger-ui-dist@3.29/swagger-ui.css")
# Actual monkey patch
applications.get_swagger_ui_html = swagger_monkey_patch
原理见https://fastapi.tiangolo.com/reference/openapi/docs/,docs和redoc都有专门的函数生成,其参数中有引用的CDN地址,那我们只需要把函数的参数改掉就行了。
新的问题
想必大家也注意到了,替换的js和css地址是有版本号的,事实上可能不同的fastapi版本用的是不同版本的静态资源,如果我们替换的版本号和fastapi实际使用的版本不一样会怎么样?试了一下,果然报错:
这就麻烦了,难道我每次都要去源码查看CDN版本,再手动替换?这样的话还不如用本地的方案呢。
不过办法总比困难多,既然原始的get_swagger_ui_html函数给出了引用的CDN地址,那我们直接获取这个参数值,然后替换前缀不就行了(jsdelivr
和unpkg
基本上可以一一对应,所以我们只要replace即可,这里使用unpkg
,因为要比知乎的CDN全),顺着这个思路,很快代码就写好了。
最终解决
完整代码如下:
import inspect
def get_function_default_args(func):
'''获取函数默认参数'''
sign = inspect.signature(func)
return {
k: v.default
for k, v in sign.parameters.items()
if v.default is not inspect.Parameter.empty
}
def swagger_monkey_patch(*args, **kwargs):
"""
Wrap the function which is generating the HTML for the /docs endpoint and
overwrite the default values for the swagger js and css.
"""
param_dict = get_function_default_args(get_swagger_ui_html)
swagger_js_url = param_dict['swagger_js_url'].replace('https://cdn.jsdelivr.net/npm/', 'https://unpkg.com/')
swagger_css_url = param_dict['swagger_css_url'].replace('https://cdn.jsdelivr.net/npm/', 'https://unpkg.com/')
return get_swagger_ui_html(
*args, **kwargs,
swagger_js_url=swagger_js_url,
swagger_css_url=swagger_css_url
)
applications.get_swagger_ui_html = swagger_monkey_patch
注: redoc也可以这么改,引入fastapi.openapi.docs.get\_redoc\_html函数替换redoc_js_url
即可
问题解决。
版权属于:作者名称
本文链接:https://www.sitstars.com/archives/123/
转载时须注明出处及本声明