Caio Fauza 4 days ago
committed by GitHub
parent
commit
b08478f186
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 4
      fastapi/applications.py
  2. 6
      fastapi/openapi/models.py
  3. 28
      fastapi/openapi/utils.py

4
fastapi/applications.py

@ -27,6 +27,7 @@ from fastapi.openapi.docs import (
get_swagger_ui_html, get_swagger_ui_html,
get_swagger_ui_oauth2_redirect_html, get_swagger_ui_oauth2_redirect_html,
) )
from fastapi.openapi.models import DefaultErrorSchema
from fastapi.openapi.utils import get_openapi from fastapi.openapi.utils import get_openapi
from fastapi.params import Depends from fastapi.params import Depends
from fastapi.types import DecoratedCallable, IncEx from fastapi.types import DecoratedCallable, IncEx
@ -695,6 +696,7 @@ class FastAPI(Starlette):
""" """
), ),
] = None, ] = None,
default_error_schema: Optional[DefaultErrorSchema] = None,
callbacks: Annotated[ callbacks: Annotated[
Optional[List[BaseRoute]], Optional[List[BaseRoute]],
Doc( Doc(
@ -871,6 +873,7 @@ class FastAPI(Starlette):
), ),
] = "3.1.0" ] = "3.1.0"
self.openapi_schema: Optional[Dict[str, Any]] = None self.openapi_schema: Optional[Dict[str, Any]] = None
self.default_error_schema = default_error_schema
if self.openapi_url: if self.openapi_url:
assert self.title, "A title must be provided for OpenAPI, e.g.: 'My API'" assert self.title, "A title must be provided for OpenAPI, e.g.: 'My API'"
assert self.version, "A version must be provided for OpenAPI, e.g.: '2.1.0'" assert self.version, "A version must be provided for OpenAPI, e.g.: '2.1.0'"
@ -987,6 +990,7 @@ class FastAPI(Starlette):
terms_of_service=self.terms_of_service, terms_of_service=self.terms_of_service,
contact=self.contact, contact=self.contact,
license_info=self.license_info, license_info=self.license_info,
default_error_schema=self.default_error_schema,
routes=self.routes, routes=self.routes,
webhooks=self.webhooks.routes, webhooks=self.webhooks.routes,
tags=self.openapi_tags, tags=self.openapi_tags,

6
fastapi/openapi/models.py

@ -228,6 +228,12 @@ class Example(TypedDict, total=False):
extra = "allow" extra = "allow"
class DefaultErrorSchema(BaseModel):
status: int
description: Optional[str] = None
model: BaseModel
class ParameterInType(Enum): class ParameterInType(Enum):
query = "query" query = "query"
header = "header" header = "header"

28
fastapi/openapi/utils.py

@ -23,7 +23,7 @@ from fastapi.dependencies.utils import (
) )
from fastapi.encoders import jsonable_encoder from fastapi.encoders import jsonable_encoder
from fastapi.openapi.constants import METHODS_WITH_BODY, REF_PREFIX, REF_TEMPLATE from fastapi.openapi.constants import METHODS_WITH_BODY, REF_PREFIX, REF_TEMPLATE
from fastapi.openapi.models import OpenAPI from fastapi.openapi.models import DefaultErrorSchema, OpenAPI
from fastapi.params import Body, ParamTypes from fastapi.params import Body, ParamTypes
from fastapi.responses import Response from fastapi.responses import Response
from fastapi.types import ModelNameMap from fastapi.types import ModelNameMap
@ -261,6 +261,7 @@ def get_openapi_path(
Tuple[ModelField, Literal["validation", "serialization"]], JsonSchemaValue Tuple[ModelField, Literal["validation", "serialization"]], JsonSchemaValue
], ],
separate_input_output_schemas: bool = True, separate_input_output_schemas: bool = True,
default_error_schema: Optional[DefaultErrorSchema] = None,
) -> Tuple[Dict[str, Any], Dict[str, Any], Dict[str, Any]]: ) -> Tuple[Dict[str, Any], Dict[str, Any], Dict[str, Any]]:
path = {} path = {}
security_schemes: Dict[str, Any] = {} security_schemes: Dict[str, Any] = {}
@ -418,7 +419,28 @@ def get_openapi_path(
openapi_response["description"] = description openapi_response["description"] = description
http422 = str(HTTP_422_UNPROCESSABLE_ENTITY) http422 = str(HTTP_422_UNPROCESSABLE_ENTITY)
all_route_params = get_flat_params(route.dependant) all_route_params = get_flat_params(route.dependant)
if (all_route_params or route.body_field) and not any( if default_error_schema is not None:
operation["responses"][default_error_schema["status"]] = {
"description": default_error_schema["description"],
"content": {
"application/json": {
"schema": {
"$ref": REF_PREFIX + default_error_schema["name"]
}
},
},
}
definitions.update(
{
default_error_schema["name"]: {
"title": default_error_schema["name"],
"type": "object",
"properties": default_error_schema["properties"],
"required": default_error_schema["required"],
}
}
)
elif (all_route_params or route.body_field) and not any(
status in operation["responses"] status in operation["responses"]
for status in [http422, "4XX", "default"] for status in [http422, "4XX", "default"]
): ):
@ -482,6 +504,7 @@ def get_openapi(
summary: Optional[str] = None, summary: Optional[str] = None,
description: Optional[str] = None, description: Optional[str] = None,
routes: Sequence[BaseRoute], routes: Sequence[BaseRoute],
default_error_schema: Optional[DefaultErrorSchema] = None,
webhooks: Optional[Sequence[BaseRoute]] = None, webhooks: Optional[Sequence[BaseRoute]] = None,
tags: Optional[List[Dict[str, Any]]] = None, tags: Optional[List[Dict[str, Any]]] = None,
servers: Optional[List[Dict[str, Union[str, Any]]]] = None, servers: Optional[List[Dict[str, Union[str, Any]]]] = None,
@ -526,6 +549,7 @@ def get_openapi(
model_name_map=model_name_map, model_name_map=model_name_map,
field_mapping=field_mapping, field_mapping=field_mapping,
separate_input_output_schemas=separate_input_output_schemas, separate_input_output_schemas=separate_input_output_schemas,
default_error_schema=default_error_schema,
) )
if result: if result:
path, security_schemes, path_definitions = result path, security_schemes, path_definitions = result

Loading…
Cancel
Save