¿Cómo personalizar la respuesta de error en FastAPI?

Resuelto draaken asked hace 2 años • 2 respuestas

Tengo el siguiente backend FastAPI:

from fastapi import FastAPI

app = FastAPI

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

El problema es que cuando envío una solicitud a esta API con datos adicionales como:

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

o

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

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

arroja un error con código de estado 422 unprocessable entityde error con datos reales ("algo de texto aquí") y adicionales ("aaaaa") en el campo de retorno en caso de 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
      }
    }
  ]
}

Intenté poner la línea app=FastAPI()en un bloque try-catch, sin embargo, no funciona. ¿Hay alguna manera de poder manejar este problema con una respuesta propia en lugar de la respuesta automática mencionada anteriormente? Algo como esto:

{"error": {"message": "Invalid JSON body"},
                         "status": 0}
draaken avatar Feb 02 '22 15:02 draaken
Aceptado

Está pasando un JSON no válido y, por lo tanto, el servidor responde correctamente con el 422 Unprocessable Entityerror. Su cliente de prueba no debería poder ejecutarse en absoluto sin generar un invalid syntaxerror. Entonces, supongo que publicó la solicitud a través de los documentos automáticos interactivos proporcionados por Swagger UI en /docsy recibió el error 422 relevante.

Si lo que realmente desea es manejar el error, para personalizar el error o algo así, puede anular el controlador de excepción de validación de solicitud, como se describe en la documentación (consulte esta discusión , así como esta respuesta y esta respuesta que demuestra cómo personalizar RequestValidationErrorsolo para rutas específicas).

Ejemplo de trabajo:

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

O también puedes devolver un PlainTextResponsemensaje personalizado:

from fastapi.responses import PlainTextResponse

@app.exception_handler(RequestValidationError)
async def validation_exception_handler(request, exc):
    return PlainTextResponse(str(exc), status_code=422) 
Chris avatar Feb 02 '2022 11:02 Chris