Use dark-themed swagger docs

This commit is contained in:
Peter Vacho 2024-11-27 16:12:38 +01:00
parent 7d72730101
commit b6b7c466db
Signed by: school
GPG key ID: 8CFC3837052871B4

View file

@ -1,10 +1,12 @@
from asyncio.exceptions import CancelledError
from collections.abc import AsyncIterator
from contextlib import asynccontextmanager
from typing import cast
from fastapi import FastAPI
from fastapi.openapi.docs import get_swagger_ui_html
from fastapi.requests import Request
from fastapi.responses import PlainTextResponse
from fastapi.responses import HTMLResponse, PlainTextResponse
from src.utils.logging import get_logger
@ -39,6 +41,7 @@ app = FastAPI(
"email": "p_vacho@utb.cz",
},
license_info={"name": "GPL-3.0-or-later"},
docs_url=None,
)
@ -46,3 +49,33 @@ app = FastAPI(
async def ping(_r: Request) -> PlainTextResponse:
"""Test whether the API works."""
return PlainTextResponse("pong")
@app.get("/docs", include_in_schema=False)
async def docs() -> HTMLResponse:
"""Custom endpoint to serve the Swagger UI documentation, but in dark theme.
Light theme should be considered a crime against humanity.
"""
html_resp = get_swagger_ui_html(
openapi_url=cast(str, 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",
)
# Swagger UI doesn't support dark theme out of the box
# https://github.com/swagger-api/swagger-ui/issues/5327
# Extract the HTML content from the default response and inject a dark mode CSS
html = cast(bytes, html_resp.body).decode()
dark_mode_css_url = "https://cdn.jsdelivr.net/gh/jcphlux/swagger-ui-themes@master/dist/swagger-dark-modern-ui.css"
# The hash can be generated with: openssl dgst -sha384 -binary style.css | openssl base64 -A
dark_mode_css_hash = "sha384-LUPDO6OZKHtaY6oPBOnbv5cmmD7ldzmDWHJe71Jlt+8+0YOTOLRzMkmUIfvVtYe+"
dark_mode_css_url = (
f'<link rel="stylesheet" type="text/css" href="{dark_mode_css_url}" '
f'integrity="{dark_mode_css_hash}" crossorigin="anonymous">'
)
html = html.replace("</head>", f"{dark_mode_css_url}</head>")
return HTMLResponse(html)