QwertYou
QwertYou

Reputation: 381

Can't get correct server response on validation error (spectree + flask )

I have a problem with my API on Flask, using spectree. I have one endpoint with one "POST" method, which takes some data, validates it, and if successful, returns {"status": "OK"}, and in case of validation error, returns a 400 code and a message that there was a validation error. It is rather not what I have, but what I wanted to achieve. I suggest taking a look at the code to better understand what I mean:

from flask import Flask
from spectree import SpecTree, Response
from pydantic import BaseModel

class Error(BaseModel):
    code:int = 400
    message:str = 'Validation Failed'

class Unit(BaseModel):
    id: int

app = Flask(__name__)
api = SpecTree('flask', app=app, title='API', version='v1.0', path='docs')

@app.post('/imports')
@api.validate(json=Unit, validation_error_status=400, resp=Response(HTTP_400=Error))
def imports():
    return {'status': 'OK'}, 200

That is, as you can see, following the documentation, I set validation_error_status=400 so that when validation fails, the client receives a response with a 400 code (wow?). I also set resp=Response(HTTP_400=Error) so that when a 400 error occurs, the client receives an Error response. Thus, on a validation error, the API client should receive a response corresponding to the Error model (see below)

Now, if I send a request that is not valid, that is, id will not be int, but for example "fkfld", I will receive the following response:

[
  {
    "loc": [
      "id"
    ],
    "msg": "value is not a valid integer",
    "type": "type_error.integer"
  }
]

I thought the answer would be:

{
  "code": 400,
  "message": "Validation Failed"
}

I use:

I tried very hard to understand what my mistake was, but I could not. I've read the documentation, but my problem is only related to:

What is Response and how to use it?

To build a response for the endpoint, you need to declare the status code with format HTTP_{code} and corresponding data (optional).

Please help me figure this out, I really want to understand my mistakes and how to do it right.

Upvotes: 1

Views: 556

Answers (1)

SomeGuy
SomeGuy

Reputation: 11

You can achieve this by using the before_handler.

def before_handler(req, resp, err, instance):
    """Change the error message to the format we expect. This is only for validation errors"""
    if err:
        resp.text = json.dumps({"error": "ValidationError", "message": str(err)})

spec = SpecTree("falcon", validation_error_status=400, before=before_handler)

And if you specify HTTP_400=SomeErrorModel in your @spec.validate(), your custom error will get validated on that model as well.

Upvotes: 0

Related Questions