FastAPI 0.104.1中204状态码返回体断言错误求助
FastAPI 204状态码响应报错解决方案
问题背景
将FastAPI从0.85.2升级到0.104.1后,修改用户语言的PUT接口抛出错误:
AssertionError: Status code 204 must not have a response body
尝试将空return替换为return Response(status_code=HTTP_204_NO_CONTENT.value)后问题仍未解决。
接口代码
@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()
错误类定义
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} )
解决方案
1. 移除全局response_class配置
204状态码要求响应无内容,而ORJSONResponse会默认尝试序列化响应体,即使返回空值,FastAPI新版本的严格校验会触发断言错误。去掉该配置后,FastAPI会自动为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, # 保留状态码配置 )
2. 明确返回无内容的Response对象
如果需要为错误响应保留ORJSONResponse,可以在成功分支明确返回不带内容的Response,确保没有任何响应体被生成:
from fastapi import Response, status # 替换成功分支的return语句 return Response( status_code=status.HTTP_204_NO_CONTENT, content=None, media_type=None )
3. 修正返回类型注解
204响应没有返回体,将原有的-> NO_CONTENT_RESPONSE改为-> None,避免FastAPI对返回类型的校验冲突:
async def patch_me_users_language( request: Request, session=fastapi.Depends(get_db) ) -> None:
原因说明
FastAPI 0.100+版本对HTTP规范的校验更加严格,严格遵循RFC 7231中204状态码的定义:响应必须不包含任何内容。旧版本中ORJSONResponse返回空值时可能不会生成响应体,但新版本会触发断言检查,确保204响应完全符合规范。
内容的提问来源于stack exchange,提问作者Stoecki
相关产品推荐
相关产品推荐

