Ir para o conteúdo

Recursos Estáticos Personalizados para a UI de Documentação (Hospedagem Própria)

A documentação da API usa Swagger UI e ReDoc, e cada um deles precisa de alguns arquivos JavaScript e CSS.

Por padrão, esses arquivos são fornecidos por um CDN.

Mas é possível personalizá-los, você pode definir um CDN específico ou providenciar os arquivos você mesmo.

CDN Personalizado para JavaScript e CSS

Vamos supor que você deseja usar um CDN diferente, por exemplo, você deseja usar https://unpkg.com/.

Isso pode ser útil se, por exemplo, você mora em um país que restringe algumas URLs.

Desativar a documentação automática

O primeiro passo é desativar a documentação automática, pois por padrão, ela usa o CDN padrão.

Para desativá-los, defina suas URLs como None ao criar seu aplicativo 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@next/bundles/redoc.standalone.js",
    )


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

Incluir a documentação personalizada

Agora você pode criar as operações de rota para a documentação personalizada.

Você pode reutilizar as funções internas do FastAPI para criar as páginas HTML para a documentação e passar os argumentos necessários:

  • openapi_url: a URL onde a página HTML para a documentação pode obter o esquema OpenAPI para a sua API. Você pode usar aqui o atributo app.openapi_url.
  • title: o título da sua API.
  • oauth2_redirect_url: você pode usar app.swagger_ui_oauth2_redirect_url aqui para usar o padrão.
  • swagger_js_url: a URL onde a página HTML para a sua documentação do Swagger UI pode obter o arquivo JavaScript. Este é o URL do CDN personalizado.
  • swagger_css_url: a URL onde a página HTML para a sua documentação do Swagger UI pode obter o arquivo CSS. Este é o URL do CDN personalizado.

E de forma semelhante para o 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}"}

Dica

A operação de rota para swagger_ui_redirect é um auxiliar para quando você usa OAuth2.

Se você integrar sua API com um provedor OAuth2, você poderá autenticar e voltar para a documentação da API com as credenciais adquiridas. E interagir com ela usando a autenticação OAuth2 real.

Swagger UI lidará com isso nos bastidores para você, mas ele precisa desse auxiliar de "redirecionamento".

Criar uma operação de rota para testar

Agora, para poder testar se tudo funciona, crie uma operação de rota:

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}"}

Teste

Agora, você deve ser capaz de ir para a documentação em http://127.0.0.1:8000/docs, e recarregar a página, ela carregará esses recursos do novo CDN.

Hospedagem Própria de JavaScript e CSS para a documentação

Hospedar o JavaScript e o CSS pode ser útil se, por exemplo, você precisa que seu aplicativo continue funcionando mesmo offline, sem acesso aberto à Internet, ou em uma rede local.

Aqui você verá como providenciar esses arquivos você mesmo, no mesmo aplicativo FastAPI, e configurar a documentação para usá-los.

Estrutura de Arquivos do Projeto

Vamos supor que a estrutura de arquivos do seu projeto se pareça com isso:

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

Agora crie um diretório para armazenar esses arquivos estáticos.

Sua nova estrutura de arquivos poderia se parecer com isso:

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

Baixe os arquivos

Baixe os arquivos estáticos necessários para a documentação e coloque-os no diretório static/.

Você provavelmente pode clicar com o botão direito em cada link e selecionar uma opção semelhante a Salvar link como....

Swagger UI usa os arquivos:

E o ReDoc usa os arquivos:

Depois disso, sua estrutura de arquivos deve se parecer com:

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

Prover os arquivos estáticos

  • Importe StaticFiles.
  • "Monte" a instância StaticFiles() em um caminho específico.
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}"}

Teste os arquivos estáticos

Inicialize seu aplicativo e vá para http://127.0.0.1:8000/static/redoc.standalone.js.

Você deverá ver um arquivo JavaScript muito longo para o ReDoc.

Esse arquivo pode começar com algo como:

/*!
 * ReDoc - OpenAPI/Swagger-generated API Reference Documentation
 * -------------------------------------------------------------
 *   Version: "2.0.0-rc.18"
 *   Repo: https://github.com/Redocly/redoc
 */
!function(e,t){"object"==typeof exports&&"object"==typeof m

...

Isso confirma que você está conseguindo fornecer arquivos estáticos do seu aplicativo e que você colocou os arquivos estáticos para a documentação no local correto.

Agora, podemos configurar o aplicativo para usar esses arquivos estáticos para a documentação.

Desativar a documentação automática para arquivos estáticos

Da mesma forma que ao usar um CDN personalizado, o primeiro passo é desativar a documentação automática, pois ela usa o CDN padrão.

Para desativá-los, defina suas URLs como None ao criar seu aplicativo 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}"}

Incluir a documentação personalizada para arquivos estáticos

E da mesma forma que com um CDN personalizado, agora você pode criar as operações de rota para a documentação personalizada.

Novamente, você pode reutilizar as funções internas do FastAPI para criar as páginas HTML para a documentação e passar os argumentos necessários:

  • openapi_url: a URL onde a página HTML para a documentação pode obter o esquema OpenAPI para a sua API. Você pode usar aqui o atributo app.openapi_url.
  • title: o título da sua API.
  • oauth2_redirect_url: Você pode usar app.swagger_ui_oauth2_redirect_url aqui para usar o padrão.
  • swagger_js_url: a URL onde a página HTML para a sua documentação do Swagger UI pode obter o arquivo JavaScript. Este é o URL do CDN personalizado. Este é o URL que seu aplicativo está fornecendo.
  • swagger_css_url: a URL onde a página HTML para a sua documentação do Swagger UI pode obter o arquivo CSS. Esse é o que seu aplicativo está fornecendo.

E de forma semelhante para o 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}"}

Dica

A operação de rota para swagger_ui_redirect é um auxiliar para quando você usa OAuth2.

Se você integrar sua API com um provedor OAuth2, você poderá autenticar e voltar para a documentação da API com as credenciais adquiridas. E, então, interagir com ela usando a autenticação OAuth2 real.

Swagger UI lidará com isso nos bastidores para você, mas ele precisa desse auxiliar de "redirect".

Criar uma operação de rota para testar arquivos estáticos

Agora, para poder testar se tudo funciona, crie uma operação de rota:

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}"}

Teste a UI de Arquivos Estáticos

Agora, você deve ser capaz de desconectar o WiFi, ir para a documentação em http://127.0.0.1:8000/docs, e recarregar a página.

E mesmo sem Internet, você será capaz de ver a documentação da sua API e interagir com ela.