Response Validation#
When sending a JSON response to the client it makes sense to check that the structure matches a predefined structure. This is a form of Design by Contract and helps ensure that your software works as expected. This is done by validating the response data is correct against a schema you define. Quart-Schema allows validation of JSON data via decorating the route handler, as so,
from attrs import define
from quart_schema import validate_response
@define
class Todo:
effort: int
task: str
@app.route("/")
@validate_response(Todo)
async def index():
return data
from dataclasses import dataclass
from quart_schema import validate_response
@dataclass
class Todo:
effort: int
task: str
@app.route("/")
@validate_response(Todo)
async def index():
return data
from msgspec import Struct
from quart_schema import validate_response
class Todo(Struct):
effort: int
task: str
@app.route("/")
@validate_response(Todo)
async def index():
return data
from pydantic import BaseModel
from quart_schema import validate_response
class Todo(BaseModel):
effort: int
task: str
@app.route("/")
@validate_response(Todo)
async def index():
return data
will ensure that data
represents or is a Todo
object,
e.g. these responses are allowed. Note that the typical Quart response
return values are allowed, including status and headers,
return {"effort": 2, "task": "Finish the docs"}
return Todo(effort=2, task="Finish the docs")
return {"effort": 2, "task": "Finish the docs"}, 200
return {"effort": 2, "task": "Finish the docs"}, {"X-Header": "value"}
Handling multiple/different status codes#
The validate_response()
decorator’s
second argument is the status code the validation applies too. By
default this is assumed to be 200
, but can be changed to validate
responses that are sent with a different status code.
To validate a route that returns different different responses by status code the decorator can be used multiple times,
@app.route("/")
@validate_response(Todo, 200)
@validate_response(CreatedTodo, 201)
async def index():
if ...:
return Todo(), 200
else:
return CreatedTodo(), 201
Handling validation errors#
By default if the response result doesn’t satisfy the schema a
ResponseSchemaValidationError
error is raised and not handled,
resulting in a 500 internal server error response. You can alter this
by adding an error handler, for example,
from quart_schema import ResponseSchemaValidationError
@app.errorhandler(ResponseSchemaValidationError)
async def handle_response_validation_error():
return {"error": "VALIDATION"}, 500