mirror of https://github.com/tiangolo/fastapi.git
Fix: adding additional_responses on `.include_router()`
This commit is contained in:
parent
84a300ef84
commit
95679ca5e6
|
|
@ -346,7 +346,7 @@ class Tag(BaseModel):
|
||||||
|
|
||||||
class BaseAdditionalResponse(BaseModel):
|
class BaseAdditionalResponse(BaseModel):
|
||||||
description: str
|
description: str
|
||||||
content_type: str = None
|
content_type: Optional[str] = None
|
||||||
|
|
||||||
|
|
||||||
class AdditionalResponse(BaseAdditionalResponse):
|
class AdditionalResponse(BaseAdditionalResponse):
|
||||||
|
|
@ -356,7 +356,7 @@ class AdditionalResponse(BaseAdditionalResponse):
|
||||||
# NOTE: waiting for pydantic to allow `typing.Type[BasicModel]` type
|
# NOTE: waiting for pydantic to allow `typing.Type[BasicModel]` type
|
||||||
# so, going for `Any` and extra validation on
|
# so, going for `Any` and extra validation on
|
||||||
# routing methods
|
# routing methods
|
||||||
models: Optional[List[Any]] = PSchema([], title="Additional Response Models")
|
models: List[Any] = PSchema([], title="Additional Response Models")
|
||||||
|
|
||||||
|
|
||||||
class AdditionalResponseDescription(BaseAdditionalResponse):
|
class AdditionalResponseDescription(BaseAdditionalResponse):
|
||||||
|
|
|
||||||
|
|
@ -206,7 +206,7 @@ def get_openapi_path(
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for add_response_code, add_response in route.additional_responses.items():
|
for add_response_code, add_response in route.additional_responses.items():
|
||||||
add_response_schema = {}
|
add_response_schema: Dict[str, Any] = {}
|
||||||
if (
|
if (
|
||||||
add_response.content_type or route.content_type.media_type
|
add_response.content_type or route.content_type.media_type
|
||||||
) == "application/json" and add_response.schema_field is not None:
|
) == "application/json" and add_response.schema_field is not None:
|
||||||
|
|
|
||||||
|
|
@ -150,7 +150,7 @@ class APIRoute(routing.Route):
|
||||||
add_response.status_code not in existed_codes
|
add_response.status_code not in existed_codes
|
||||||
), f"(Duplicated Status Code): Response with status code [{add_response.status_code}] already defined!"
|
), f"(Duplicated Status Code): Response with status code [{add_response.status_code}] already defined!"
|
||||||
existed_codes.append(add_response.status_code)
|
existed_codes.append(add_response.status_code)
|
||||||
response_models = [m for m in add_response.models]
|
response_models: List[Any] = [m for m in add_response.models]
|
||||||
valid_response_models = True
|
valid_response_models = True
|
||||||
try:
|
try:
|
||||||
valid_response_models = all(
|
valid_response_models = all(
|
||||||
|
|
@ -306,56 +306,6 @@ class APIRouter(routing.Router):
|
||||||
), "A path prefix must not end with '/', as the routes will start with '/'"
|
), "A path prefix must not end with '/', as the routes will start with '/'"
|
||||||
for route in router.routes:
|
for route in router.routes:
|
||||||
if isinstance(route, APIRoute):
|
if isinstance(route, APIRoute):
|
||||||
# really ugly hack and repitition
|
|
||||||
prev_add_resp = route.additional_responses
|
|
||||||
existed_codes = [422, route.status_code] + [
|
|
||||||
int(c) for c in prev_add_resp.keys()
|
|
||||||
]
|
|
||||||
for add_response in additional_responses:
|
|
||||||
assert (
|
|
||||||
add_response.status_code not in existed_codes
|
|
||||||
), f"(Duplicated Status Code): Response with status code [{add_response.status_code}] already defined!"
|
|
||||||
existed_codes.append(add_response.status_code)
|
|
||||||
response_models = [m for m in add_response.models]
|
|
||||||
valid_response_models = True
|
|
||||||
try:
|
|
||||||
valid_response_models = all(
|
|
||||||
[issubclass(m, BaseModel) for m in response_models]
|
|
||||||
)
|
|
||||||
except AttributeError as ae:
|
|
||||||
valid_response_models = False
|
|
||||||
if not valid_response_models:
|
|
||||||
raise ValueError(
|
|
||||||
"All response models must be"
|
|
||||||
"a subclass of `pydantic.BaseModel`"
|
|
||||||
"model."
|
|
||||||
)
|
|
||||||
if (
|
|
||||||
add_response.content_type == "application/json"
|
|
||||||
or lenient_issubclass(route.content_type, JSONResponse)
|
|
||||||
):
|
|
||||||
if len(response_models):
|
|
||||||
schema_field = Field(
|
|
||||||
name=f"Additional_response_{add_response.status_code}",
|
|
||||||
type_=Union[tuple(response_models)],
|
|
||||||
class_validators=[],
|
|
||||||
default=None,
|
|
||||||
required=False,
|
|
||||||
model_config=UnconstrainedConfig,
|
|
||||||
schema=Schema(None),
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
schema_field = None
|
|
||||||
else:
|
|
||||||
schema_field = None
|
|
||||||
add_resp_description = AdditionalResponseDescription(
|
|
||||||
description=add_response.description,
|
|
||||||
content_type=add_response.content_type,
|
|
||||||
schema_field=schema_field,
|
|
||||||
)
|
|
||||||
route.additional_responses[
|
|
||||||
add_response.status_code
|
|
||||||
] = add_resp_description
|
|
||||||
self.add_api_route(
|
self.add_api_route(
|
||||||
prefix + route.path,
|
prefix + route.path,
|
||||||
route.endpoint,
|
route.endpoint,
|
||||||
|
|
@ -365,7 +315,7 @@ class APIRouter(routing.Router):
|
||||||
summary=route.summary,
|
summary=route.summary,
|
||||||
description=route.description,
|
description=route.description,
|
||||||
response_description=route.response_description,
|
response_description=route.response_description,
|
||||||
additional_responses=route.additional_responses,
|
additional_responses=additional_responses,
|
||||||
deprecated=route.deprecated,
|
deprecated=route.deprecated,
|
||||||
methods=route.methods,
|
methods=route.methods,
|
||||||
operation_id=route.operation_id,
|
operation_id=route.operation_id,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue