fastapi 错误:AssertionError:状态代码 204 不得有响应正文

fastapi Error: AssertionError: Status code 204 must not have a response body

提问人:Stoecki 提问时间:11/17/2023 最后编辑:Karl KnechtelStoecki 更新时间:11/17/2023 访问量:39

问:

我使用 FastAPI 有以下代码:

@router.put(
    "/api/v1/me/language",
    tags=["users"],
    responses={
        400: {"model": BadRequest},
        401: {"model": Unauthorized},
        403: {"model": Forbidden},
        404: {"model": NotFound},
        500: {"model": InternalServerError}
    },
    response_class=fastapi.responses.ORJSONResponse,
    status_code=204,
)
async def patch_me_users_language(
    request: Request, session=fastapi.Depends(get_db)
) -> NO_CONTENT_RESPONSE:
    content_bytes = await request.body()
    content = content_bytes.decode("utf-8").upper()

    if content in set(COUNTRIES):
        db_result = DBUser.get_by_uuid(
            request.state.user_uuid, session
        )
        if db_result:
            try:
                db_result.update({"language": content}, session)
                # Tried it already with 'return Response(status_code=HTTP_204_NO_CONTENT.value)'
                return
            except pydantic.error_wrappers.ValidationError as e:
                return http_err.UnprocessableEntity(detail=e.errors()).render()
        else:
            return http_err.InternalServerError(
                detail=f"User for this valid token does not exist."
            ).render()
    else:
        return http_err.UnprocessableEntity(
            detail=[
                {
                    "loc": ["body"],
                    "msg": "Expected the content to contain a valid language/country code",
                    "type": "value_error",
                }
            ]
        ).render()

其中是子类的实例,定义如下:http_errHttpErrors

class HttpErrors(pydantic.BaseModel):
    """
    Base class for HTTP error responses. The render method is used to translate instances of this class into
    fastapi.responses.ORJSONResponse responses.
    """
    status: int
    detail: str

    def render(self) -> fastapi.responses.ORJSONResponse:
        """
        Translates a class instance into a fastapi.responses.ORJSONResponse
        :return: fastapi.responses.ORJSONResponse
        """
        logger.info(f"Returned error response: status: {self.status}, msg: {self.content}")
        return fastapi.responses.ORJSONResponse(
            status_code=self.status,
            content=self.content()
        )

    def content(self):
        return {'detail': self.detail}

    def json_content(self):
        return json.dumps(self.content())


class BadRequest(HttpErrors):
    status = 400


class Unauthorized(HttpErrors):
    status = 401


class Forbidden(HttpErrors):
    status = 403


class NotFound(HttpErrors):
    status = 404


class UnprocessableEntity(pydantic.BaseModel):
    status = 422
    detail: List[dict]

    def render(self) -> fastapi.responses.ORJSONResponse:
        return fastapi.responses.ORJSONResponse(
            status_code=self.status,
            content={'detail': self.detail}
        )

这在 FastAPI 0.85.2 中有效,但在 0.104.1 中我收到一个错误,上面写着

AssertionError: Status code 204 must not have a response body

根据代码中的注释,我尝试将空替换为 ,但这不起作用。returnreturn Response(status_code=HTTP_204_NO_CONTENT.value)

我应该如何正确处理空响应?我假设它取决于注释()中的模型定义,但在这里找不到任何东西。router.put(...)

蟒蛇 FastAPI

评论

0赞 Karl Knechtel 11/17/2023
您是否尝试使用日志记录或调试器或读取堆栈跟踪来检查在导致问题的情况下采用的代码路径?您是否能够确定响应正文由什么组成,或者它来自哪里?
0赞 Tim Roberts 11/17/2023
这是你的“成功”回应,对吧?你为什么不发回一个成功代码,比如?这是处理成功交易的正常方式。{ "status": "ok" }
0赞 Stoecki 11/17/2023
因为我复制了一个以这种方式返回它的现有应用程序

答:

3赞 Yurii Motov 11/17/2023 #1
response_class=fastapi.responses.ORJSONResponse,
status_code=204,

我猜,当你的返回status_code是 204(无内容)时,你不能指定响应模型。 尝试删除响应模型


@router.put(
    "/api/v1/me/language",
    tags=["users"],
    responses={
        400: {"model": BadRequest},
        401: {"model": Unauthorized},
        403: {"model": Forbidden},
        404: {"model": NotFound},
        500: {"model": InternalServerError}
    },
    status_code=204,
)
async def patch_me_users_language(
    request: Request, session=fastapi.Depends(get_db)
) -> None:
... 

在成功的情况下使用或只是退出功能return Nonereturn

评论

1赞 Stoecki 11/17/2023
谢谢,删除response_class和返回值的类型注释(或将其更改为 None)有效