在FastAPI Swagger UI docs中添加一个自定义javascript



我想加载我的自定义javascript文件或代码到FastAPI Swagger UI网页,以便在我创建FastAPI对象时添加一些动态交互。

例如,在Swagger UI on docs网页上,我想

<script src="custom_script.js"></script> 

<script> alert('worked!') </script>

我试着:

api = FastAPI(docs_url=None)
api.mount("/static", StaticFiles(directory="static"), name="static")
@api.get("/docs", include_in_schema=False)
async def custom_swagger_ui_html():
return get_swagger_ui_html(
openapi_url=api.openapi_url,
title=api.title + " - Swagger UI",
oauth2_redirect_url=api.swagger_ui_oauth2_redirect_url,
swagger_js_url="/static/sample.js",
swagger_css_url="/static/sample.css",
)

,但它不工作。是否有一种方法可以在FastAPI Swagger UI的文档网页上插入我的自定义javascript代码?

如果您看一下从fastapi.openapi.docs导入的get_swagger_ui_html函数,您将看到docs页面的HTML是通过字符串插值/连接手动构建的。修改这个函数以包含一个额外的脚本元素是很简单的,如下所示:

# custom_swagger.py
import json
from typing import Any, Dict, Optional
from fastapi.encoders import jsonable_encoder
from fastapi.openapi.docs import swagger_ui_default_parameters
from starlette.responses import HTMLResponse
def get_swagger_ui_html(
*,
openapi_url: str,
title: str,
swagger_js_url: str = "https://cdn.jsdelivr.net/npm/swagger-ui-dist@4/swagger-ui-bundle.js",
swagger_css_url: str = "https://cdn.jsdelivr.net/npm/swagger-ui-dist@4/swagger-ui.css",
swagger_favicon_url: str = "https://fastapi.tiangolo.com/img/favicon.png",
oauth2_redirect_url: Optional[str] = None,
init_oauth: Optional[Dict[str, Any]] = None,
swagger_ui_parameters: Optional[Dict[str, Any]] = None,
custom_js_url: Optional[str] = None,
) -> HTMLResponse:
current_swagger_ui_parameters = swagger_ui_default_parameters.copy()
if swagger_ui_parameters:
current_swagger_ui_parameters.update(swagger_ui_parameters)
html = f"""
<!DOCTYPE html>
<html>
<head>
<link type="text/css" rel="stylesheet" href="{swagger_css_url}">
<link rel="shortcut icon" href="{swagger_favicon_url}">
<title>{title}</title>
</head>
<body>
<div id="swagger-ui">
</div>
"""

if custom_js_url:
html += f"""
<script src="{custom_js_url}"></script>
"""
html += f"""
<script src="{swagger_js_url}"></script>
<!-- `SwaggerUIBundle` is now available on the page -->
<script>
const ui = SwaggerUIBundle({{
url: '{openapi_url}',
"""
for key, value in current_swagger_ui_parameters.items():
html += f"{json.dumps(key)}: {json.dumps(jsonable_encoder(value))},n"
if oauth2_redirect_url:
html += f"oauth2RedirectUrl: window.location.origin + '{oauth2_redirect_url}',"
html += """
presets: [
SwaggerUIBundle.presets.apis,
SwaggerUIBundle.SwaggerUIStandalonePreset
],
})"""
if init_oauth:
html += f"""
ui.initOAuth({json.dumps(jsonable_encoder(init_oauth))})
"""
html += """
</script>
</body>
</html>
"""
return HTMLResponse(html)

新增可选参数custom_js_url:

custom_js_url: Optional[str] = None,

如果为该参数提供了一个值,则在swagger_js_url的脚本元素之前直接插入一个脚本元素到DOM中(这是一个任意的选择,您可以根据您的需要更改自定义脚本元素的位置)。

if custom_js_url:
html += f"""
<script src="{custom_js_url}"></script>
"""

如果不提供值,生成的HTML与原函数相同。

请记住更新get_swagger_ui_html的导入语句,并更新/docs端点的函数,如下所示:

from fastapi import FastAPI
from fastapi.staticfiles import StaticFiles
from fastapi.openapi.docs import (
get_redoc_html,
get_swagger_ui_oauth2_redirect_html,
)
from custom_swagger import get_swagger_ui_html
import os
app = FastAPI(docs_url=None) 
path_to_static = os.path.join(os.path.dirname(__file__), 'static')
app.mount("/static", StaticFiles(directory=path_to_static), name="static")
@app.get("/docs", include_in_schema=False)
async def custom_swagger_ui_html():
return get_swagger_ui_html(
openapi_url=app.openapi_url,
title="My API",
oauth2_redirect_url=app.swagger_ui_oauth2_redirect_url,
swagger_js_url="/static/swagger-ui-bundle.js",
swagger_css_url="/static/swagger-ui.css",
# swagger_favicon_url="/static/favicon-32x32.png",
custom_js_url="/static/custom_script.js",
)

这仍然是一个相当黑客的解决方案,但我认为它是更干净,更易于维护比把一堆自定义的javascript在swagger-ui-bundle.js文件。

最后我让它工作了。我是这样做的:

from fastapi.openapi.docs import (
get_redoc_html,
get_swagger_ui_html,
get_swagger_ui_oauth2_redirect_html,
)
from fastapi.staticfiles import StaticFiles
api = FastAPI(docs_url=None) 
path_to_static = os.path.join(os.path.dirname(__file__), 'static')
logger.info(f"path_to_static: {path_to_static}")
api.mount("/static", StaticFiles(directory=path_to_static), name="static")
@api.get("/docs", include_in_schema=False)
async def custom_swagger_ui_html():
return get_swagger_ui_html(
openapi_url=api.openapi_url,
title="My API",
oauth2_redirect_url=api.swagger_ui_oauth2_redirect_url,
swagger_js_url="/static/custom_script.js",
# swagger_css_url="/static/swagger-ui.css",
# swagger_favicon_url="/static/favicon-32x32.png",
)

重要提示:

  1. 确保静态路径是正确的,所有文件都在静态文件夹中,默认情况下静态文件夹应该与创建FastAPI对象的脚本在同一个文件夹中。
  2. 例如:

-parent_folder
Build_FastAPI.py
-static_folder
custom_script.js
custom_css.css
  1. 在网上找到swagger-ui-bundle.js并复制粘贴其所有内容到custom_script.js,然后在custom_script.js的开头或结尾添加您的自定义javascript代码。
  2. 例如:

setTimeout(function(){alert('My custom script is working!')}, 5000);
...
.....
/*! For license information please see swagger-ui-bundle.js.LICENSE.txt */
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.SwaggerUIBundle=t():e.SwaggerUIBundle=t()}
...
.....
  1. 保存并刷新你的浏览器,你就成功了!

如果有人知道更好的答案,欢迎你,最好的将被接受!

最新更新