在FastAPI 路由注释中支持 Mermaid 图表方案
背景
FastAPI 会提取路由函数的注释并添加到生成的 OpenAPI 文档中
希望能在 OpenAPI 的前端页面中支持显示mermaid图表
分析
FastAPI 在指定请求中返回redoc/docs两种风格的的OpenAPI前端显示页面
通过注入的方式,在前端页面中引入mermaid的 sdk, 即可让页面支持渲染mermaid图表
方案
- 构造替换装饰器函数, 在 HTML 中注入引用
mermaid的代码 - 覆写模块函数
点击查看代码示例
import importlib
from functools import wraps
from typing import Callable
import fastapi
import fastapi.applications
import fastapi.openapi.docs
from fastapi.responses import HTMLResponse
def add_mermaid_support(func: Callable[..., HTMLResponse]):
"""在</head>标签前插入mermaid js
https://mermaid-js.github.io/mermaid/#/n00b-gettingStarted?id=requirements-for-the-mermaid-api
"""
mermaid_js = '''
<script type="module">
import mermaid from 'https://unpkg.com/mermaid@9/dist/mermaid.esm.min.mjs';
mermaid.initialize({ startOnLoad: true });
</script>
<style type="text/css">
pre.mermaid {
background-color: lightsteelblue !important;
}
</style>
'''
@wraps(func)
def decorator(*args, **kwargs) -> HTMLResponse:
res = func(*args, **kwargs)
content = res.body.decode(res.charset)
index = content.find("</head>")
if index != -1:
content = content[:index] + mermaid_js + content[index:]
return HTMLResponse(content)
return decorator
# A
fastapi.openapi.docs.get_swagger_ui_html = add_mermaid_support(fastapi.openapi.docs.get_swagger_ui_html)
fastapi.openapi.docs.get_redoc_html = add_mermaid_support(fastapi.openapi.docs.get_redoc_html)
importlib.reload(fastapi.applications)
# B
# fastapi.applications.get_swagger_ui_html = add_mermaid_support(fastapi.openapi.docs.get_swagger_ui_html)
# fastapi.applications.get_redoc_html = add_mermaid_support(fastapi.openapi.docs.get_redoc_html)
# app = FastAPI()
@router.get('/')
def hello():
"""
<pre class="mermaid">
graph TD
A[Client] -->|tcp_123| B
B(Load Balancer)
B -->|tcp_456| C[Server1]
B -->|tcp_456| D[Server2]
</pre>
"""
return "hello world"
回顾
对于模块函数的覆写
fastapi.applications模块通过 from import 语法导入并使用相应的函数对象, 所以需要通过 imp.reload(fastapi.applications)重载模块.
或者直接修改 fastapi.applications.get_swagger_ui_html 和 fastapi.applications.get_redoc_html 函数对象.
关于样式
如代码所示,使用pre标签展示流程图.
而 Redoc 的默认样式会导致mermaid 图表的背景色为黑色,不利于阅读,所以需要添加一个样式并通过!important 提高优先级。
查看代码示例
原有的样式.hzUya pre {
background-color: rgb(17, 23, 26);
}
pre.mermaid {
background-color: lightsteelblue !important;
}