Skip to content

Commit fba7493

Browse files
🐛 Ignore Response classes on return annotation (fastapi#5855)
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent 53973f7 commit fba7493

2 files changed

Lines changed: 53 additions & 1 deletion

File tree

fastapi/routing.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
from pydantic import BaseModel
4343
from pydantic.error_wrappers import ErrorWrapper, ValidationError
4444
from pydantic.fields import ModelField, Undefined
45+
from pydantic.utils import lenient_issubclass
4546
from starlette import routing
4647
from starlette.concurrency import run_in_threadpool
4748
from starlette.exceptions import HTTPException
@@ -356,7 +357,11 @@ def __init__(
356357
self.path = path
357358
self.endpoint = endpoint
358359
if isinstance(response_model, DefaultPlaceholder):
359-
response_model = get_typed_return_annotation(endpoint)
360+
return_annotation = get_typed_return_annotation(endpoint)
361+
if lenient_issubclass(return_annotation, Response):
362+
response_model = None
363+
else:
364+
response_model = return_annotation
360365
self.response_model = response_model
361366
self.summary = summary
362367
self.response_description = response_description

tests/test_response_model_as_return_annotation.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import pytest
44
from fastapi import FastAPI
5+
from fastapi.responses import JSONResponse, Response
56
from fastapi.testclient import TestClient
67
from pydantic import BaseModel, ValidationError
78

@@ -237,6 +238,16 @@ def no_response_model_annotation_union_return_model2() -> Union[User, Item]:
237238
return Item(name="Foo", price=42.0)
238239

239240

241+
@app.get("/no_response_model-annotation_response_class")
242+
def no_response_model_annotation_response_class() -> Response:
243+
return Response(content="Foo")
244+
245+
246+
@app.get("/no_response_model-annotation_json_response_class")
247+
def no_response_model_annotation_json_response_class() -> JSONResponse:
248+
return JSONResponse(content={"foo": "bar"})
249+
250+
240251
openapi_schema = {
241252
"openapi": "3.0.2",
242253
"info": {"title": "FastAPI", "version": "0.1.0"},
@@ -789,6 +800,30 @@ def no_response_model_annotation_union_return_model2() -> Union[User, Item]:
789800
},
790801
}
791802
},
803+
"/no_response_model-annotation_response_class": {
804+
"get": {
805+
"summary": "No Response Model Annotation Response Class",
806+
"operationId": "no_response_model_annotation_response_class_no_response_model_annotation_response_class_get",
807+
"responses": {
808+
"200": {
809+
"description": "Successful Response",
810+
"content": {"application/json": {"schema": {}}},
811+
}
812+
},
813+
}
814+
},
815+
"/no_response_model-annotation_json_response_class": {
816+
"get": {
817+
"summary": "No Response Model Annotation Json Response Class",
818+
"operationId": "no_response_model_annotation_json_response_class_no_response_model_annotation_json_response_class_get",
819+
"responses": {
820+
"200": {
821+
"description": "Successful Response",
822+
"content": {"application/json": {"schema": {}}},
823+
}
824+
},
825+
}
826+
},
792827
},
793828
"components": {
794829
"schemas": {
@@ -1049,3 +1084,15 @@ def test_no_response_model_annotation_union_return_model2():
10491084
response = client.get("/no_response_model-annotation_union-return_model2")
10501085
assert response.status_code == 200, response.text
10511086
assert response.json() == {"name": "Foo", "price": 42.0}
1087+
1088+
1089+
def test_no_response_model_annotation_return_class():
1090+
response = client.get("/no_response_model-annotation_response_class")
1091+
assert response.status_code == 200, response.text
1092+
assert response.text == "Foo"
1093+
1094+
1095+
def test_no_response_model_annotation_json_response_class():
1096+
response = client.get("/no_response_model-annotation_json_response_class")
1097+
assert response.status_code == 200, response.text
1098+
assert response.json() == {"foo": "bar"}

0 commit comments

Comments
 (0)