Skip to content

在FastAPI 路由注释中支持 Mermaid 图表方案

背景

FastAPI 会提取路由函数的注释并添加到生成的 OpenAPI 文档中

希望能在 OpenAPI 的前端页面中支持显示mermaid图表

分析

FastAPI 在指定请求中返回redoc/docs两种风格的的OpenAPI前端显示页面

通过注入的方式,在前端页面中引入mermaid的 sdk, 即可让页面支持渲染mermaid图表

方案

  1. 构造替换装饰器函数, 在 HTML 中注入引用mermaid的代码
  2. 覆写模块函数
点击查看代码示例
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_htmlfastapi.applications.get_redoc_html 函数对象.

关于样式

如代码所示,使用pre标签展示流程图.

Redoc 的默认样式会导致mermaid 图表的背景色为黑色,不利于阅读,所以需要添加一个样式并通过!important 提高优先级。

查看代码示例 原有的样式
.hzUya pre {
    background-color: rgb(17, 23, 26);
}
添加的样式
pre.mermaid {
    background-color: lightsteelblue !important;
}