【问题标题】:How to customise error response in FastAPI?如何在 FastAPI 中自定义错误响应?
【发布时间】:2022-10-07 00:24:39
【问题描述】:

我有以下 FastAPI 后端:

from fastapi import FastAPI

app = FastAPI

class Demo(BaseModel):
    content: str = None
    
@app.post(\"/demo\")
async def demoFunc(d:Demo):
    return d.content

问题是,当我向这个 API 发送带有额外数据的请求时,例如:

data = {\"content\":\"some text here\"}aaaa

或者

data = {\"content\":\"some text here\"aaaaaa}

resp = requests.post(url, json=data)

data = {\"content\":\"some text here\"}aaaa 的情况下,它会在返回字段中使用Actual(\"some text here\") 和Extra(\"aaaaa\") 数据引发状态码422 unprocessable entity 错误:

{
  \"detail\": [
    {
      \"loc\": [
        \"body\",
        47
      ],
      \"msg\": \"Extra data: line 4 column 2 (char 47)\",
      \"type\": \"value_error.jsondecode\",
      \"ctx\": {
        \"msg\": \"Extra data\",
        \"doc\": \"{\\n  \\\"content\\\": \\\"some text here\\\"}aaaaa\",
        \"pos\": 47,
        \"lineno\": 4,
        \"colno\": 2
      }
    }
  ]
}

我试图将行 app=FastAPI() 放在 try-catch 块中,但是它不起作用。有什么办法可以用自己的响应而不是上面提到的自动响应来处理这个问题? 像这样的东西:

{\"error\": {\"message\": \"Invalid JSON body\"},
                         \"status\": 0}
  • 你期望结果是什么?这是无效的 JSON,那么您要如何解析呢?
  • 我想显示自定义响应而不是来自 api 本身的自动响应。
  • 你见过fastapi.tiangolo.com/tutorial/handling-errors - 它告诉你如何覆盖特定的错误并自己处理响应。
  • 我看到了,但无法正确获取它。但是感谢克里斯,现在解决了,也谢谢@MatsLindh

标签: json fastapi pydantic


【解决方案1】:

你到底想要达到什么目的?您传递的 JSON 无效,服务器正确响应 422 unprocessable entity error。您的测试客户端根本不应该能够运行,而不会引发 invalid syntax 错误。所以,我猜你通过 OpenAPI 尝试过,并收到了相关的 422 错误。

如果您真正想要的是处理错误,为了自定义错误或其他内容,您可以覆盖请求验证异常,如documentation 中所述(另外,请查看此discussion)。下面是一个例子。

from fastapi import FastAPI, Body, Request, status
from fastapi.encoders import jsonable_encoder
from fastapi.exceptions import RequestValidationError
from fastapi.responses import JSONResponse
from pydantic import BaseModel

app = FastAPI()

@app.exception_handler(RequestValidationError)
async def validation_exception_handler(request: Request, exc: RequestValidationError):
    return JSONResponse(
        status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
        content=jsonable_encoder({"detail": exc.errors(),
                "body": exc.body,
                 "custom msg": {"Your error message"}}),
    )

class Demo(BaseModel):
    content: str = None

@app.post("/demo")
async def demoFunc(d:Demo):
    return d.content

或者,您也可以返回带有任何自定义消息的 PlainTextResponse

from fastapi.responses import PlainTextResponse
@app.exception_handler(RequestValidationError)
async def validation_exception_handler(request, exc):
    return PlainTextResponse(str(exc), status_code=400) 

【讨论】:

  • 我知道它是无效的 JSON 数据,这就是重点。实际上是跨站点脚本测试的情况,其中测试人员使用不同的方法来获取使用请求正文本身的信息。例如,可以在请求正文中放置一个脚本,例如:{"content":"some text"}<script>/*+Bad+script+here...+*/</script> 所以,我知道 API 会抛出 422 错误,但它也会返回我不想显示的请求正文本身。这就是为什么我问我如何才能捕捉到这个并显示我自己的错误消息
  • 我正在使用 JSONResponse 来显示我自己的消息,如下所述:return JSONResponse( status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, content={"error": {"message": "Invalid JSON body"}, "status": 0} )
  • 克里斯,我试过你的代码,但还是一样{ "detail": [ { "loc": [ "body", 45 ], "msg": "Expecting ',' delimiter: line 3 column 24 (char 45)", "type": "value_error.jsondecode", "ctx": { "msg": "Expecting ',' delimiter", "doc": "{\n \"gender\": \"male\",\n \"language\": \"English\"aaaaa\n}", "pos": 45, "lineno": 3, "colno": 24 } } ], "custom msg": { "error": { "message": "Invalid json format" }, "status": 0 } }
  • 没关系我修改了提供的答案,它现在有效。谢谢@Chris
猜你喜欢
  • 2021-11-29
  • 2015-06-16
  • 1970-01-01
  • 2022-09-30
  • 2019-02-07
  • 2020-10-03
  • 1970-01-01
  • 2017-04-10
  • 2020-01-14
相关资源
最近更新 更多