from speakers.common.registry import registry from fastapi import FastAPI from fastapi.staticfiles import StaticFiles from starlette.responses import HTMLResponse from typing import Any, Optional from pathlib import Path def MakeFastAPIOffline( app: FastAPI, static_dir="/static", static_url="/static-offline-docs", docs_url: Optional[str] = "/docs", redoc_url: Optional[str] = "/redoc", ) -> None: """patch the FastAPI obj that doesn't rely on CDN for the documentation page""" from fastapi import Request from fastapi.openapi.docs import ( get_redoc_html, get_swagger_ui_html, get_swagger_ui_oauth2_redirect_html, ) openapi_url = app.openapi_url swagger_ui_oauth2_redirect_url = app.swagger_ui_oauth2_redirect_url def remove_route(url: str) -> None: ''' remove original route from app ''' index = None for i, r in enumerate(app.routes): if r.path.lower() == url.lower(): index = i break if isinstance(index, int): app.routes.pop(i) # Set up static file mount app.mount( static_url, StaticFiles(directory=Path(f"{registry.get_path('server_library_root')}{static_dir}").as_posix()), name="static-offline-docs", ) if docs_url is not None: remove_route(docs_url) remove_route(swagger_ui_oauth2_redirect_url) # Define the doc and redoc pages, pointing at the right files @app.get(docs_url, include_in_schema=False) async def custom_swagger_ui_html(request: Request) -> HTMLResponse: root = request.scope.get("root_path") favicon = f"{root}{static_url}/favicon.png" return get_swagger_ui_html( openapi_url=f"{root}{openapi_url}", title=app.title + " - Swagger UI", oauth2_redirect_url=swagger_ui_oauth2_redirect_url, swagger_js_url=f"{root}{static_url}/swagger-ui-bundle.js", swagger_css_url=f"{root}{static_url}/swagger-ui.css", swagger_favicon_url=favicon, ) @app.get(swagger_ui_oauth2_redirect_url, include_in_schema=False) async def swagger_ui_redirect() -> HTMLResponse: return get_swagger_ui_oauth2_redirect_html() if redoc_url is not None: remove_route(redoc_url) @app.get(redoc_url, include_in_schema=False) async def redoc_html(request: Request) -> HTMLResponse: root = request.scope.get("root_path") favicon = f"{root}{static_url}/favicon.png" return get_redoc_html( openapi_url=f"{root}{openapi_url}", title=app.title + " - ReDoc", redoc_js_url=f"{root}{static_url}/redoc.standalone.js", with_google_fonts=False, redoc_favicon_url=favicon, )