I am working on an application that has quite a large number of endpoints. I have been using tags to group sets of API however the APIs themselves are quite different so I was wondering if there is a way of hosting multiple OpenAPI endoints.
E.g.
area1 -> /area1/swagger
area2 -> /area2/swagger
--- Not an actual solution, just some opinion / findings into how I feel it should be possible ---
I think this would work very well with APIRouter.
If you try right now you get a A response class is needed to generate OpenAPI which comes from line 161 in fastapi.openapi/utils.py:
161: assert route.response_class, "A response class is needed to generate OpenAPI"
162: route_response_media_type: Optional[str] = route.response_class.media_type
Removing the assert and replacing route_response_media_type with application/json actually makes it runnable, and It's actually not that far from being correct?
I've tried it with test_additional_response_extra.py test:
from fastapi import APIRouter, FastAPI
from fastapi.testclient import TestClient
from fastapi.openapi.utils import get_openapi
app = FastAPI()
router = APIRouter()
sub_router = APIRouter()
def custom_openapi():
if app.openapi_schema:
return app.openapi_schema
custom_open_schema = get_openapi(
title='FastAPI',
version='0.1.0',
routes=router.routes,
)
app.openapi_schema = custom_open_schema
return app.openapi_schema
app.openapi = custom_openapi
@app.get("/")
def read_another_item():
return {"lol": "yo"}
@sub_router.get("/")
def read_item():
return {"id": "foo"}
router.include_router(sub_router, prefix="/items")
app.include_router(router)
openapi_schema = {
'openapi': '3.0.2',
'info': {'title': 'FastAPI', 'version': '0.1.0'},
'paths': {
'/items/': {
'get': {
'responses': {
'200': {
'description': 'Successful Response',
'content': {'application/json': {'schema': {'type': 'string'}}}
}
},
'summary': 'Read Item',
'operationId': 'read_item_items__get',
}
}
},
}
client = TestClient(app)
def test_openapi_schema():
response = client.get("/openapi.json")
assert response.status_code == 200, response.text
assert response.json() == openapi_schema
def test_path_operation():
response = client.get("/items/")
assert response.status_code == 200, response.text
assert response.json() == {"id": "foo"}
The only difference is the inclusion of {'type': 'string'} inside schema, this doesn't happen when running under app.routes.
Obviously the example isn't complex, but I don't see a reason not to have this.
thanks for this. Will look later on in the week and let you know how i go
you can create two FastAPI apps and mount them in starlette
from fastapi import FastAPI
from starlette.applications import Starlette
from starlette.routing import Mount
api1 = FastAPI(title="API1")
api2 = FastAPI(title="API2")
@api1.get("/test")
def test_api1():
return "API1"
@api2.get("/test")
def test_api2():
return "API2"
app = Starlette(routes=[
Mount("/api1", api1),
Mount("/api2", api2)
])
@ArcLightSlavik -- thanks for looking in to this 馃憤
@SebastianLuebke thanks for your solution. It worked really well 馃憤
Most helpful comment
@ArcLightSlavik -- thanks for looking in to this 馃憤
@SebastianLuebke thanks for your solution. It worked really well 馃憤