Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🐛 Fix support for strings in OpenAPI status codes: default, 1XX, 2XX, 3XX, 4XX, 5XX #5187

Merged
12 changes: 12 additions & 0 deletions fastapi/utils.py
Expand Up @@ -21,6 +21,18 @@
def is_body_allowed_for_status_code(status_code: Union[int, str, None]) -> bool:
if status_code is None:
return True
if status_code in [
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it'd be more efficient to have a set here instead of list?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That would be also more consistent below where its also doing set-based check. So here using instead:

    # https://swagger.io/docs/specification/describing-responses/#default
    # https://swagger.io/docs/specification/describing-responses/#status-codes
    if status_code in {
        "default",
        "2XX",
        "2xx",
        "3XX",
        "3xx",
        "4XX",
        "4xx",
        "5XX",
        "5xx",
    }:
        return True

Also adding a comment where these come from would be a good idea.

"default",
"2XX",
"2xx",
"3XX",
"3xx",
"4XX",
"4xx",
"5XX",
"5xx",
]:
return True
current_status_code = int(status_code)
return not (current_status_code < 200 or current_status_code in {204, 304})

Expand Down
63 changes: 63 additions & 0 deletions tests/test_additional_responses_router.py
@@ -1,5 +1,11 @@
from fastapi import APIRouter, FastAPI
from fastapi.testclient import TestClient
from pydantic import BaseModel


class ResponseModel(BaseModel):
message: str


app = FastAPI()
router = APIRouter()
Expand Down Expand Up @@ -33,6 +39,18 @@ async def c():
return "c"


@router.get(
"/d",
responses={
"400": {"description": "Error with str"},
"5xx": {"model": ResponseModel},
"default": {"model": ResponseModel},
},
)
async def d():
return "d"


app.include_router(router)

openapi_schema = {
Expand Down Expand Up @@ -81,6 +99,45 @@ async def c():
"operationId": "c_c_get",
}
},
"/d": {
"get": {
"responses": {
"400": {"description": "Error with str"},
"5XX": {
"description": "Server Error",
"content": {
"application/json": {
"schema": {"$ref": "#/components/schemas/ResponseModel"}
}
},
},
"200": {
"description": "Successful Response",
"content": {"application/json": {"schema": {}}},
},
"default": {
"description": "Default Response",
"content": {
"application/json": {
"schema": {"$ref": "#/components/schemas/ResponseModel"}
}
},
},
},
"summary": "D",
"operationId": "d_d_get",
}
},
},
"components": {
"schemas": {
"ResponseModel": {
"title": "ResponseModel",
"required": ["message"],
"type": "object",
"properties": {"message": {"title": "Message", "type": "string"}},
}
}
},
}

Expand Down Expand Up @@ -109,3 +166,9 @@ def test_c():
response = client.get("/c")
assert response.status_code == 200, response.text
assert response.json() == "c"


def test_d():
response = client.get("/d")
assert response.status_code == 200, response.text
assert response.json() == "d"