如何在FastAPI中自定义错误响应?

dra*_*ken 4 python json pydantic fastapi

我有以下 FastAPI 后端:

from fastapi import FastAPI

app = FastAPI

class Demo(BaseModel):
    content: str = None
    
@app.post("/demo")
async def demoFunc(d:Demo):
    return d.content
Run Code Online (Sandbox Code Playgroud)

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

data = {"content":"some text here"}aaaa
Run Code Online (Sandbox Code Playgroud)

或者

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

resp = requests.post(url, json=data)
Run Code Online (Sandbox Code Playgroud)

422 unprocessable entity在以下情况下,它会抛出状态代码错误,返回字段中包含 Actual("some text here") 和 Extra("aaaaa") 数据data = {"content":"some text here"}aaaa

{
  "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
      }
    }
  ]
}
Run Code Online (Sandbox Code Playgroud)

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

{"error": {"message": "Invalid JSON body"},
                         "status": 0}
Run Code Online (Sandbox Code Playgroud)

Chr*_*ris 6

您正在传递无效的 JSON,因此服务器会正​​确响应错误422 Unprocessable Entity。您的测试客户端根本不应该在不抛出invalid syntax错误的情况下运行。因此,我猜测您通过 Swagger UI 提供的交互式自动文档发布了请求/docs,并收到了相关的 422 错误。

如果您真正想要的是处理错误,为了自定义错误或其他内容,您可以重写请求验证异常处理程序,如文档中所述(查看此讨论,以及此答案此答案演示了如何RequestValidationError仅针对特定路线进行自定义)。

工作示例:

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(),  # optionally include the errors
                "body": exc.body,
                 "custom msg": {"Your error message"}}),
    )

class Demo(BaseModel):
    content: str = None

@app.post("/demo")
async def some_func(d: Demo):
    return d.content
Run Code Online (Sandbox Code Playgroud)

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

from fastapi.responses import PlainTextResponse

@app.exception_handler(RequestValidationError)
async def validation_exception_handler(request, exc):
    return PlainTextResponse(str(exc), status_code=422) 
Run Code Online (Sandbox Code Playgroud)