Перейти к содержанию

Свои статические ресурсы UI документации (самостоятельный хостинг)

Документация API использует Swagger UI и ReDoc, и для каждого из них нужны некоторые файлы JavaScript и CSS.

По умолчанию эти файлы отдаются с CDN.

Но это можно настроить: вы можете указать конкретный CDN или отдавать файлы самостоятельно.

Пользовательский CDN для JavaScript и CSS

Допустим, вы хотите использовать другой CDN, например https://unpkg.com/.

Это может быть полезно, если, например, вы живёте в стране, где некоторые URL ограничены.

Отключить автоматическую документацию

Первый шаг — отключить автоматическую документацию, так как по умолчанию она использует стандартный CDN.

Чтобы отключить её, установите их URL в значение None при создании вашего приложения FastAPI:

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@2/bundles/redoc.standalone.js",
    )


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

Подключить пользовательскую документацию

Теперь вы можете создать операции пути для пользовательской документации.

Вы можете переиспользовать внутренние функции FastAPI для создания HTML-страниц документации и передать им необходимые аргументы:

  • openapi_url: URL, по которому HTML-страница документации сможет получить схему OpenAPI для вашего API. Здесь можно использовать атрибут app.openapi_url.
  • title: заголовок вашего API.
  • oauth2_redirect_url: здесь можно использовать app.swagger_ui_oauth2_redirect_url, чтобы оставить значение по умолчанию.
  • swagger_js_url: URL, по которому HTML для документации Swagger UI сможет получить файл JavaScript. Это URL вашего пользовательского CDN.
  • swagger_css_url: URL, по которому HTML для документации Swagger UI сможет получить файл CSS. Это URL вашего пользовательского CDN.

Аналогично и для 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@2/bundles/redoc.standalone.js",
    )


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

Совет

Операция пути для swagger_ui_redirect — это вспомогательный эндпоинт на случай, когда вы используете OAuth2.

Если вы интегрируете свой API с провайдером OAuth2, вы сможете аутентифицироваться и вернуться к документации API с полученными учётными данными, а затем взаимодействовать с ним, используя реальную аутентификацию OAuth2.

Swagger UI сделает это за вас «за кулисами», но для этого ему нужен этот вспомогательный «redirect» эндпоинт.

Создайте операцию пути, чтобы проверить

Чтобы убедиться, что всё работает, создайте операцию пути:

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@2/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.

Вы должны увидеть очень длинный JavaScript-файл для ReDoc.

Он может начинаться примерно так:

/*! For license information please see redoc.standalone.js.LICENSE.txt */
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("null")):
...

Это подтверждает, что ваше приложение умеет отдавать статические файлы и что вы поместили файлы документации в нужное место.

Теперь можно настроить приложение так, чтобы документация использовала эти статические файлы.

Отключить автоматическую документацию для статических файлов

Так же, как и при использовании пользовательского CDN, первым шагом будет отключение автоматической документации, так как по умолчанию она использует CDN.

Чтобы отключить её, установите их URL в значение None при создании вашего приложения FastAPI:

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: URL, по которому HTML-страница документации сможет получить схему OpenAPI для вашего API. Здесь можно использовать атрибут app.openapi_url.
  • title: заголовок вашего API.
  • oauth2_redirect_url: здесь можно использовать app.swagger_ui_oauth2_redirect_url, чтобы оставить значение по умолчанию.
  • swagger_js_url: URL, по которому HTML для документации Swagger UI сможет получить файл JavaScript. Это тот файл, который теперь отдаёт ваше собственное приложение.
  • swagger_css_url: URL, по которому HTML для документации Swagger UI сможет получить файл CSS. Это тот файл, который теперь отдаёт ваше собственное приложение.

Аналогично и для 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}"}

Совет

Операция пути для swagger_ui_redirect — это вспомогательный эндпоинт на случай, когда вы используете OAuth2.

Если вы интегрируете свой API с провайдером OAuth2, вы сможете аутентифицироваться и вернуться к документации API с полученными учётными данными, а затем взаимодействовать с ним, используя реальную аутентификацию OAuth2.

Swagger UI сделает это за вас «за кулисами», но для этого ему нужен этот вспомогательный «redirect» эндпоинт.

Создайте операцию пути для теста статических файлов

Чтобы убедиться, что всё работает, создайте операцию пути:

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 со статическими файлами

Теперь вы можете отключить Wi‑Fi, открыть свою документацию по адресу http://127.0.0.1:8000/docs и перезагрузить страницу.

Даже без Интернета вы сможете видеть документацию к своему API и взаимодействовать с ним.