mirror of https://github.com/tiangolo/fastapi.git
Merge e82a5ce4f7 into 272204c0c7
This commit is contained in:
commit
3291ef2dd8
|
|
@ -3,7 +3,7 @@ import inspect
|
||||||
import warnings
|
import warnings
|
||||||
from typing import Any, Dict, List, Optional, Sequence, Set, Tuple, Type, Union, cast
|
from typing import Any, Dict, List, Optional, Sequence, Set, Tuple, Type, Union, cast
|
||||||
|
|
||||||
from fastapi import routing
|
from fastapi import FastAPI, routing
|
||||||
from fastapi._compat import (
|
from fastapi._compat import (
|
||||||
JsonSchemaValue,
|
JsonSchemaValue,
|
||||||
ModelField,
|
ModelField,
|
||||||
|
|
@ -566,3 +566,100 @@ def get_openapi(
|
||||||
if external_docs:
|
if external_docs:
|
||||||
output["externalDocs"] = external_docs
|
output["externalDocs"] = external_docs
|
||||||
return jsonable_encoder(OpenAPI(**output), by_alias=True, exclude_none=True) # type: ignore
|
return jsonable_encoder(OpenAPI(**output), by_alias=True, exclude_none=True) # type: ignore
|
||||||
|
|
||||||
|
|
||||||
|
class ConsolidatedOpenAPI:
|
||||||
|
"""
|
||||||
|
ConsolidatedOpenAPI is a utility class for combining the OpenAPI schemas of a main FastAPI application and multiple sub-applications.
|
||||||
|
It generates a consolidated OpenAPI schema that includes the routes of both the main app and the sub-apps.
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
```python
|
||||||
|
app = FastAPI()
|
||||||
|
sub_app = FastAPI()
|
||||||
|
|
||||||
|
app.mount("/sub", sub_app, name="sub")
|
||||||
|
app.openapi = CustomOpenAPI(title="Consolidated API", app=app, sub_apps=[sub_app], version="1.0.0")
|
||||||
|
unicorn.run(app, host="localhost", port=8000)
|
||||||
|
```
|
||||||
|
Then you will see all the routes of the main app and the sub-apps in `http://localhost:8000/docs`.
|
||||||
|
Created by Zhengde Zhang on 2024-09-30.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
title: str,
|
||||||
|
app: FastAPI,
|
||||||
|
sub_apps: list[FastAPI],
|
||||||
|
version: str,
|
||||||
|
openapi_version: str = "3.1.0",
|
||||||
|
summary: Optional[str] = None,
|
||||||
|
description: Optional[str] = None,
|
||||||
|
tags: Optional[List[Dict[str, Any]]] = None,
|
||||||
|
servers: Optional[List[Dict[str, Union[str, Any]]]] = None,
|
||||||
|
terms_of_service: Optional[str] = None,
|
||||||
|
contact: Optional[Dict[str, Union[str, Any]]] = None,
|
||||||
|
license_info: Optional[Dict[str, Union[str, Any]]] = None,
|
||||||
|
separate_input_output_schemas: bool = True,
|
||||||
|
) -> None:
|
||||||
|
"""
|
||||||
|
Initializes the ConsolidatedOpenAPI class with the given parameters.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
title (str): The title of the API.
|
||||||
|
app (FastAPI): The main FastAPI application instance.
|
||||||
|
sub_apps (list[FastAPI]): A list of sub-application FastAPI instances.
|
||||||
|
version (str): The version of the API.
|
||||||
|
openapi_version (str, optional): The OpenAPI version. Defaults to "3.1.0".
|
||||||
|
summary (str, optional): A brief summary of the API. Defaults to None.
|
||||||
|
description (str, optional): A detailed description of the API. Defaults to None.
|
||||||
|
tags (List[Dict[str, Any]], optional): A list of tags for categorizing operations. Defaults to None.
|
||||||
|
servers (List[Dict[str, Union[str, Any]]], optional): A list of server objects providing connectivity information. Defaults to None.
|
||||||
|
terms_of_service (str, optional): A URL to the terms of service for the API. Defaults to None.
|
||||||
|
contact (Dict[str, Union[str, Any]], optional): Contact information for the API. Defaults to None.
|
||||||
|
license_info (Dict[str, Union[str, Any]], optional): Licensing information for the API. Defaults to None.
|
||||||
|
separate_input_output_schemas (bool, optional): Whether to generate separate schemas for input and output data. Defaults to True.
|
||||||
|
"""
|
||||||
|
self.title = title
|
||||||
|
self.version = version
|
||||||
|
self.app = app
|
||||||
|
self.sub_apps = sub_apps
|
||||||
|
self.kwargs = {
|
||||||
|
"openapi_version": openapi_version,
|
||||||
|
"summary": summary,
|
||||||
|
"description": description,
|
||||||
|
"tags": tags,
|
||||||
|
"servers": servers,
|
||||||
|
"terms_of_service": terms_of_service,
|
||||||
|
"contact": contact,
|
||||||
|
"license_info": license_info,
|
||||||
|
"separate_input_output_schemas": separate_input_output_schemas,
|
||||||
|
}
|
||||||
|
|
||||||
|
def __call__(self):
|
||||||
|
"""
|
||||||
|
Generates and returns the combined OpenAPI schema for the main app and sub-apps.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
dict: The combined OpenAPI schema.
|
||||||
|
"""
|
||||||
|
if self.app.openapi_schema:
|
||||||
|
return self.app.openapi_schema
|
||||||
|
openapi_schema = get_openapi(
|
||||||
|
title=self.title,
|
||||||
|
version=self.version,
|
||||||
|
routes=self.app.routes,
|
||||||
|
**self.kwargs,
|
||||||
|
)
|
||||||
|
for sub_app in self.sub_apps:
|
||||||
|
subapp_schema = sub_app.openapi()
|
||||||
|
sub_app_mount = [x for x in self.app.routes if x.app == sub_app]
|
||||||
|
assert (
|
||||||
|
len(sub_app_mount) == 1
|
||||||
|
), f"Faild to find the sub app {sub_app}, please mount the sub app to the main app using `app.mount(...)` first"
|
||||||
|
sub_app_mount_path = sub_app_mount[0].path
|
||||||
|
for path, path_item in subapp_schema["paths"].items():
|
||||||
|
openapi_schema["paths"][f"{sub_app_mount_path}" + path] = path_item
|
||||||
|
|
||||||
|
self.app.openapi_schema = openapi_schema
|
||||||
|
return self.app.openapi_schema
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue