diff --git a/fastapi/openapi/utils.py b/fastapi/openapi/utils.py index 808646cc2..eb6b29190 100644 --- a/fastapi/openapi/utils.py +++ b/fastapi/openapi/utils.py @@ -263,6 +263,7 @@ def get_openapi_path( separate_input_output_schemas: bool = True, ) -> Tuple[Dict[str, Any], Dict[str, Any], Dict[str, Any]]: path = {} + empty_responses: List[str] = [] security_schemes: Dict[str, Any] = {} definitions: Dict[str, Any] = {} assert route.methods is not None, "Methods must be a list" @@ -378,7 +379,7 @@ def get_openapi_path( additional_response, ) in route.responses.items(): process_response = additional_response.copy() - process_response.pop("model", None) + process_response_model = process_response.pop("model", None) status_code_key = str(additional_status_code).upper() if status_code_key == "DEFAULT": status_code_key = "default" @@ -388,6 +389,8 @@ def get_openapi_path( assert isinstance(process_response, dict), ( "An additional response must be a dict" ) + if not process_response and not process_response_model: + empty_responses.append(str(additional_status_code)) field = route.response_fields.get(additional_status_code) additional_field_schema: Optional[Dict[str, Any]] = None if field: @@ -439,6 +442,9 @@ def get_openapi_path( ) if route.openapi_extra: deep_dict_update(operation, route.openapi_extra) + if empty_responses: + for response_status_code in empty_responses: + del operation["responses"][response_status_code] path[method.lower()] = operation return path, security_schemes, definitions diff --git a/tests/test_additional_response_empty.py b/tests/test_additional_response_empty.py new file mode 100644 index 000000000..628386cbd --- /dev/null +++ b/tests/test_additional_response_empty.py @@ -0,0 +1,69 @@ +from typing import Dict + +from fastapi import FastAPI +from fastapi.testclient import TestClient +from pydantic import BaseModel + +app = FastAPI() + + +class Items(BaseModel): + items: Dict[str, int] + + +@app.post("/foo", responses={422: {}}) +def foo(items: Items): + pass # pragma: no cover + + +client = TestClient(app) + + +openapi_schema = { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/foo": { + "post": { + "summary": "Foo", + "operationId": "foo_foo_post", + "requestBody": { + "content": { + "application/json": { + "schema": {"$ref": "#/components/schemas/Items"} + } + }, + "required": True, + }, + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + } + }, + } + } + }, + "components": { + "schemas": { + "Items": { + "title": "Items", + "required": ["items"], + "type": "object", + "properties": { + "items": { + "title": "Items", + "type": "object", + "additionalProperties": {"type": "integer"}, + } + }, + } + } + }, +} + + +def test_additional_properties_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == openapi_schema