Last active
April 17, 2024 01:55
-
-
Save Kludex/1c515aa38d22ec28d514da6b6f36da9f to your computer and use it in GitHub Desktop.
Document each version on FastAPI
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from fastapi import APIRouter, FastAPI | |
from utils import create_versioning_docs | |
app = FastAPI(docs_url=None, redoc_url=None) | |
v1_router = APIRouter(prefix="/v1") | |
v2_router = APIRouter(prefix="/v2") | |
create_versioning_docs(v1_router) | |
create_versioning_docs(v2_router) | |
@v1_router.get("/") | |
def get_hello_world(): | |
return {"message": "Hello World"} | |
@v2_router.get("/") | |
def get_another_world(): | |
return {"message": "Another World"} | |
app.include_router(v1_router) | |
app.include_router(v2_router) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
fastapi==0.68.0 | |
uvicorn==0.14.0 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import copy | |
from collections import defaultdict | |
from typing import Any, DefaultDict, Dict, Optional | |
from fastapi import APIRouter, Request | |
from fastapi.openapi.docs import get_redoc_html, get_swagger_ui_html | |
custom_openapi: DefaultDict[str, Optional[Dict[str, Any]]] = defaultdict(lambda: None) | |
def create_versioning_docs(router: APIRouter) -> None: | |
prefix = router.prefix | |
@router.get("/openapi.json", include_in_schema=False, name=f"{prefix}_openapi") | |
async def get_openapi_json(request: Request): | |
global custom_openapi | |
version = request.url.path.strip("/").split("/")[0] | |
if custom_openapi[version] is None: | |
custom_openapi[version] = copy.deepcopy(request.app.openapi()) | |
# Remove other version tags on openapi schema. | |
for path in custom_openapi[version]["paths"].copy(): | |
if not path.startswith(f"/{version}"): | |
del custom_openapi[version]["paths"][path] | |
return custom_openapi[version] | |
@router.get("/docs", include_in_schema=False, name=f"{prefix}_swagger") | |
async def get_swagger(request: Request): | |
return get_swagger_ui_html( | |
openapi_url=f"{prefix}/openapi.json", | |
title=request.app.title + " - Swagger UI", | |
) | |
@router.get("/redoc", include_in_schema=False, name=f"{prefix}_redoc") | |
async def redoc_html(request: Request): | |
return get_redoc_html( | |
openapi_url=f"{prefix}/openapi.json", title=request.app.title + " - ReDoc" | |
) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hey @vicchi! Thanks for pointing out the issue! :)
Should be fine by now, can you confirm?