Skip to content

自定义文档UI静态资源(自托管)

API文档使用**Swagger UI**和**ReDoc**,每个都需要一些JavaScript和CSS文件。

默认情况下,这些文件是从CDN提供的。

但你可以自定义它,可以设置特定的CDN,或者自己提供这些文件。

自定义JavaScript和CSS的CDN

假设你想使用不同的CDN,例如你想使用https://unpkg.com/

这在某些情况下可能很有用,例如你所在的国家限制了一些URL。

禁用自动文档

第一步是禁用自动文档,因为默认情况下,这些文档使用默认的CDN。

要禁用它们,在创建FastAPI应用时将它们的URL设置为None

from fastapi import FastAPI
from fastapi.openapi.docs import (
    get_redoc_html,
    get_swagger_ui_html,
    get_swagger_ui_oauth2_redirect_html,
)

app = FastAPI(docs_url=None, redoc_url=None)


@app.get("/docs", include_in_schema=False)
async def custom_swagger_ui_html():
    return get_swagger_ui_html(
        openapi_url=app.openapi_url,
        title=app.title + " - Swagger UI",
        oauth2_redirect_url=app.swagger_ui_oauth2_redirect_url,
        swagger_js_url="https://unpkg.com/swagger-ui-dist@5/swagger-ui-bundle.js",
        swagger_css_url="https://unpkg.com/swagger-ui-dist@5/swagger-ui.css",
    )


@app.get(app.swagger_ui_oauth2_redirect_url, include_in_schema=False)
async def swagger_ui_redirect():
    return get_swagger_ui_oauth2_redirect_html()


@app.get("/redoc", include_in_schema=False)
async def redoc_html():
    return get_redoc_html(
        openapi_url=app.openapi_url,
        title=app.title + " - ReDoc",
        redoc_js_url="https://unpkg.com/redoc@next/bundles/redoc.standalone.js",
    )


@app.get("/users/{username}")
async def read_user(username: str):
    return {"message": f"Hello {username}"}

包含自定义文档

现在你可以为自定义文档创建*路径操作*。

你可以重用FastAPI的内部函数来创建文档的HTML页面,并传递所需的参数:

  • openapi_url:文档HTML页面获取API的OpenAPI模式的URL。你可以在这里使用app.openapi_url属性。
  • title:你的API的标题。
  • oauth2_redirect_url:你可以在这里使用app.swagger_ui_oauth2_redirect_url来使用默认值。
  • swagger_js_url:你的Swagger UI文档获取**JavaScript**文件的URL。这是自定义CDN的URL。
  • swagger_css_url:你的Swagger UI文档获取**CSS**文件的URL。这是自定义CDN的URL。

对于ReDoc也是类似的...

from fastapi import FastAPI
from fastapi.openapi.docs import (
    get_redoc_html,
    get_swagger_ui_html,
    get_swagger_ui_oauth2_redirect_html,
)

app = FastAPI(docs_url=None, redoc_url=None)


@app.get("/docs", include_in_schema=False)
async def custom_swagger_ui_html():
    return get_swagger_ui_html(
        openapi_url=app.openapi_url,
        title=app.title + " - Swagger UI",
        oauth2_redirect_url=app.swagger_ui_oauth2_redirect_url,
        swagger_js_url="https://unpkg.com/swagger-ui-dist@5/swagger-ui-bundle.js",
        swagger_css_url="https://unpkg.com/swagger-ui-dist@5/swagger-ui.css",
    )


@app.get(app.swagger_ui_oauth2_redirect_url, include_in_schema=False)
async def swagger_ui_redirect():
    return get_swagger_ui_oauth2_redirect_html()


@app.get("/redoc", include_in_schema=False)
async def redoc_html():
    return get_redoc_html(
        openapi_url=app.openapi_url,
        title=app.title + " - ReDoc",
        redoc_js_url="https://unpkg.com/redoc@next/bundles/redoc.standalone.js",
    )


@app.get("/users/{username}")
async def read_user(username: str):
    return {"message": f"Hello {username}"}

Tip

swagger_ui_redirect的*路径操作*是一个帮助程序,当你使用OAuth2时。

如果你将API与OAuth2提供者集成,你将能够进行身份验证并使用获得的凭证返回到API文档。并使用真实的OAuth2身份验证与其交互。

Swagger UI会在幕后为你处理这些,但它需要这个“重定向”帮助程序。

创建一个*路径操作*来测试它

现在,为了能够测试一切是否正常,创建一个*路径操作*:

from fastapi import FastAPI
from fastapi.openapi.docs import (
    get_redoc_html,
    get_swagger_ui_html,
    get_swagger_ui_oauth2_redirect_html,
)

app = FastAPI(docs_url=None, redoc_url=None)


@app.get("/docs", include_in_schema=False)
async def custom_swagger_ui_html():
    return get_swagger_ui_html(
        openapi_url=app.openapi_url,
        title=app.title + " - Swagger UI",
        oauth2_redirect_url=app.swagger_ui_oauth2_redirect_url,
        swagger_js_url="https://unpkg.com/swagger-ui-dist@5/swagger-ui-bundle.js",
        swagger_css_url="https://unpkg.com/swagger-ui-dist@5/swagger-ui.css",
    )


@app.get(app.swagger_ui_oauth2_redirect_url, include_in_schema=False)
async def swagger_ui_redirect():
    return get_swagger_ui_oauth2_redirect_html()


@app.get("/redoc", include_in_schema=False)
async def redoc_html():
    return get_redoc_html(
        openapi_url=app.openapi_url,
        title=app.title + " - ReDoc",
        redoc_js_url="https://unpkg.com/redoc@next/bundles/redoc.standalone.js",
    )


@app.get("/users/{username}")
async def read_user(username: str):
    return {"message": f"Hello {username}"}

测试它

现在,你应该能够访问你的文档在http://127.0.0.1:8000/docs,并重新加载页面,它将从新的CDN加载这些资源。

自托管文档的JavaScript和CSS

自托管JavaScript和CSS在某些情况下可能很有用,例如,你需要你的应用在离线时、没有开放互联网访问或局域网中继续工作。

在这里,你将看到如何自己在FastAPI应用中提供这些文件,并配置文档使用它们。

项目文件结构

假设你的项目文件结构如下:

.
├── app
│   ├── __init__.py
│   ├── main.py

现在创建一个目录来存储这些静态文件。

你的新文件结构可能如下:

.
├── app
│   ├── __init__.py
│   ├── main.py
└── static/

下载文件

下载文档所需的静态文件并将它们放在static/目录中。

你可以右键点击每个链接并选择类似于另存为...的选项。

**Swagger UI**使用以下文件:

而**ReDoc**使用以下文件:

之后,你的文件结构可能如下:

.
├── app
│   ├── __init__.py
│   ├── main.py
└── static
    ├── redoc.standalone.js
    ├── swagger-ui-bundle.js
    └── swagger-ui.css

提供静态文件

  • 导入StaticFiles
  • 在特定路径上“挂载”一个StaticFiles()实例。
from fastapi import FastAPI
from fastapi.openapi.docs import (
    get_redoc_html,
    get_swagger_ui_html,
    get_swagger_ui_oauth2_redirect_html,
)
from fastapi.staticfiles import StaticFiles

app = FastAPI(docs_url=None, redoc_url=None)

app.mount("/static", StaticFiles(directory="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=app.title + " - Swagger UI",
        oauth2_redirect_url=app.swagger_ui_oauth2_redirect_url,
        swagger_js_url="/static/swagger-ui-bundle.js",
        swagger_css_url="/static/swagger-ui.css",
    )


@app.get(app.swagger_ui_oauth2_redirect_url, include_in_schema=False)
async def swagger_ui_redirect():
    return get_swagger_ui_oauth2_redirect_html()


@app.get("/redoc", include_in_schema=False)
async def redoc_html():
    return get_redoc_html(
        openapi_url=app.openapi_url,
        title=app.title + " - ReDoc",
        redoc_js_url="/static/redoc.standalone.js",
    )


@app.get("/users/{username}")
async def read_user(username: str):
    return {"message": f"Hello {username}"}

测试静态文件

启动你的应用程序并访问http://127.0.0.1:8000/static/redoc.standalone.js

你应该会看到一个非常长的**ReDoc**的JavaScript文件。

它可能以类似以下的内容开始:

/*!
 * ReDoc - 由OpenAPI/Swagger生成的API参考文档
 * -------------------------------------------------------------
 *   版本: "2.0.0-rc.18"
 *   仓库: https://github.com/Redocly/redoc
 */
!function(e,t){"object"==typeof exports&&"object"==typeof m

...
这确认了你的应用能够提供静态文件服务,并且你将文档的静态文件放置在了正确的位置。

现在我们可以配置应用,使其使用这些静态文件来提供文档。

禁用自动文档的静态文件

与使用自定义CDN时一样,第一步是禁用自动文档,因为这些文档默认使用CDN。

要禁用它们,请在创建FastAPI应用时将它们的URL设置为None

from fastapi import FastAPI
from fastapi.openapi.docs import (
    get_redoc_html,
    get_swagger_ui_html,
    get_swagger_ui_oauth2_redirect_html,
)
from fastapi.staticfiles import StaticFiles

app = FastAPI(docs_url=None, redoc_url=None)

app.mount("/static", StaticFiles(directory="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=app.title + " - Swagger UI",
        oauth2_redirect_url=app.swagger_ui_oauth2_redirect_url,
        swagger_js_url="/static/swagger-ui-bundle.js",
        swagger_css_url="/static/swagger-ui.css",
    )


@app.get(app.swagger_ui_oauth2_redirect_url, include_in_schema=False)
async def swagger_ui_redirect():
    return get_swagger_ui_oauth2_redirect_html()


@app.get("/redoc", include_in_schema=False)
async def redoc_html():
    return get_redoc_html(
        openapi_url=app.openapi_url,
        title=app.title + " - ReDoc",
        redoc_js_url="/static/redoc.standalone.js",
    )


@app.get("/users/{username}")
async def read_user(username: str):
    return {"message": f"Hello {username}"}

包含自定义文档的静态文件

与使用自定义CDN时相同,现在你可以为自定义文档创建*路径操作*。

同样,你可以重用FastAPI的内部函数来创建文档的HTML页面,并传递所需的参数:

  • openapi_url:文档HTML页面获取API的OpenAPI模式所在的URL。你可以在这里使用app.openapi_url属性。
  • title:你的API的标题。
  • oauth2_redirect_url:你可以在这里使用app.swagger_ui_oauth2_redirect_url来使用默认值。
  • swagger_js_url:你的Swagger UI文档的HTML页面获取**JavaScript**文件的URL。这是你的应用现在正在提供的文件
  • swagger_css_url:你的Swagger UI文档的HTML页面获取**CSS**文件的URL。这是你的应用现在正在提供的文件

对于ReDoc也是类似的...

from fastapi import FastAPI
from fastapi.openapi.docs import (
    get_redoc_html,
    get_swagger_ui_html,
    get_swagger_ui_oauth2_redirect_html,
)
from fastapi.staticfiles import StaticFiles

app = FastAPI(docs_url=None, redoc_url=None)

app.mount("/static", StaticFiles(directory="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=app.title + " - Swagger UI",
        oauth2_redirect_url=app.swagger_ui_oauth2_redirect_url,
        swagger_js_url="/static/swagger-ui-bundle.js",
        swagger_css_url="/static/swagger-ui.css",
    )


@app.get(app.swagger_ui_oauth2_redirect_url, include_in_schema=False)
async def swagger_ui_redirect():
    return get_swagger_ui_oauth2_redirect_html()


@app.get("/redoc", include_in_schema=False)
async def redoc_html():
    return get_redoc_html(
        openapi_url=app.openapi_url,
        title=app.title + " - ReDoc",
        redoc_js_url="/static/redoc.standalone.js",
    )


@app.get("/users/{username}")
async def read_user(username: str):
    return {"message": f"Hello {username}"}

Tip

swagger_ui_redirect的*路径操作*是一个在你使用OAuth2时的辅助工具。

如果你将API与OAuth2提供者集成,你将能够进行身份验证并使用获得的凭证返回到API文档。并使用真实的OAuth2认证与其交互。

Swagger UI会在幕后为你处理这些,但它需要这个“重定向”辅助工具。

创建一个*路径操作*来测试静态文件

现在,为了能够测试一切是否正常工作,创建一个*路径操作*:

from fastapi import FastAPI
from fastapi.openapi.docs import (
    get_redoc_html,
    get_swagger_ui_html,
    get_swagger_ui_oauth2_redirect_html,
)
from fastapi.staticfiles import StaticFiles

app = FastAPI(docs_url=None, redoc_url=None)

app.mount("/static", StaticFiles(directory="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=app.title + " - Swagger UI",
        oauth2_redirect_url=app.swagger_ui_oauth2_redirect_url,
        swagger_js_url="/static/swagger-ui-bundle.js",
        swagger_css_url="/static/swagger-ui.css",
    )


@app.get(app.swagger_ui_oauth2_redirect_url, include_in_schema=False)
async def swagger_ui_redirect():
    return get_swagger_ui_oauth2_redirect_html()


@app.get("/redoc", include_in_schema=False)
async def redoc_html():
    return get_redoc_html(
        openapi_url=app.openapi_url,
        title=app.title + " - ReDoc",
        redoc_js_url="/static/redoc.standalone.js",
    )


@app.get("/users/{username}")
async def read_user(username: str):
    return {"message": f"Hello {username}"}

测试静态文件UI

现在,你应该能够断开WiFi,访问你的文档页面 http://127.0.0.1:8000/docs,并重新加载页面。

即使在无网络的情况下,你也应该能够查看API的文档并与其交互。