Skip to content

Instantly share code, notes, and snippets.

@Kludex
Last active April 17, 2024 01:55
Show Gist options
  • Save Kludex/1c515aa38d22ec28d514da6b6f36da9f to your computer and use it in GitHub Desktop.
Save Kludex/1c515aa38d22ec28d514da6b6f36da9f to your computer and use it in GitHub Desktop.
Document each version on FastAPI
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)
fastapi==0.68.0
uvicorn==0.14.0
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"
)
@Kludex
Copy link
Author

Kludex commented Sep 8, 2021

Hey @vicchi! Thanks for pointing out the issue! :)

Should be fine by now, can you confirm?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment