]> git.ipfire.org Git - thirdparty/fastapi/fastapi.git/commitdiff
🐛 Ignore Response classes on return annotation (#5855)
authorMarcelo Trylesinski <marcelotryle@gmail.com>
Tue, 10 Jan 2023 12:45:18 +0000 (13:45 +0100)
committerGitHub <noreply@github.com>
Tue, 10 Jan 2023 12:45:18 +0000 (12:45 +0000)
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
fastapi/routing.py
tests/test_response_model_as_return_annotation.py

index 8c73b954f166ca6cdc410d0d409e98150ec47630..f131fa903e46fbb262c7f43093f6248afc3326ae 100644 (file)
@@ -42,6 +42,7 @@ from fastapi.utils import (
 from pydantic import BaseModel
 from pydantic.error_wrappers import ErrorWrapper, ValidationError
 from pydantic.fields import ModelField, Undefined
+from pydantic.utils import lenient_issubclass
 from starlette import routing
 from starlette.concurrency import run_in_threadpool
 from starlette.exceptions import HTTPException
@@ -356,7 +357,11 @@ class APIRoute(routing.Route):
         self.path = path
         self.endpoint = endpoint
         if isinstance(response_model, DefaultPlaceholder):
-            response_model = get_typed_return_annotation(endpoint)
+            return_annotation = get_typed_return_annotation(endpoint)
+            if lenient_issubclass(return_annotation, Response):
+                response_model = None
+            else:
+                response_model = return_annotation
         self.response_model = response_model
         self.summary = summary
         self.response_description = response_description
index f2056fecddee26eb0859f2ee82c6810e58e4ec9a..5d347ec34a4d4086e975fd8d55a2be97eb93ed8a 100644 (file)
@@ -2,6 +2,7 @@ from typing import List, Union
 
 import pytest
 from fastapi import FastAPI
+from fastapi.responses import JSONResponse, Response
 from fastapi.testclient import TestClient
 from pydantic import BaseModel, ValidationError
 
@@ -237,6 +238,16 @@ def no_response_model_annotation_union_return_model2() -> Union[User, Item]:
     return Item(name="Foo", price=42.0)
 
 
+@app.get("/no_response_model-annotation_response_class")
+def no_response_model_annotation_response_class() -> Response:
+    return Response(content="Foo")
+
+
+@app.get("/no_response_model-annotation_json_response_class")
+def no_response_model_annotation_json_response_class() -> JSONResponse:
+    return JSONResponse(content={"foo": "bar"})
+
+
 openapi_schema = {
     "openapi": "3.0.2",
     "info": {"title": "FastAPI", "version": "0.1.0"},
@@ -789,6 +800,30 @@ openapi_schema = {
                 },
             }
         },
+        "/no_response_model-annotation_response_class": {
+            "get": {
+                "summary": "No Response Model Annotation Response Class",
+                "operationId": "no_response_model_annotation_response_class_no_response_model_annotation_response_class_get",
+                "responses": {
+                    "200": {
+                        "description": "Successful Response",
+                        "content": {"application/json": {"schema": {}}},
+                    }
+                },
+            }
+        },
+        "/no_response_model-annotation_json_response_class": {
+            "get": {
+                "summary": "No Response Model Annotation Json Response Class",
+                "operationId": "no_response_model_annotation_json_response_class_no_response_model_annotation_json_response_class_get",
+                "responses": {
+                    "200": {
+                        "description": "Successful Response",
+                        "content": {"application/json": {"schema": {}}},
+                    }
+                },
+            }
+        },
     },
     "components": {
         "schemas": {
@@ -1049,3 +1084,15 @@ def test_no_response_model_annotation_union_return_model2():
     response = client.get("/no_response_model-annotation_union-return_model2")
     assert response.status_code == 200, response.text
     assert response.json() == {"name": "Foo", "price": 42.0}
+
+
+def test_no_response_model_annotation_return_class():
+    response = client.get("/no_response_model-annotation_response_class")
+    assert response.status_code == 200, response.text
+    assert response.text == "Foo"
+
+
+def test_no_response_model_annotation_json_response_class():
+    response = client.get("/no_response_model-annotation_json_response_class")
+    assert response.status_code == 200, response.text
+    assert response.json() == {"foo": "bar"}