aiohttp-apispec
aiohttp-apispec copied to clipboard
Two errors in Schema
Ubuntu 18.04
Python 3.8.0
aiohttp==3.6.2
aiohttp-apispec==2.2.1
https://github.com/maximdanilchenko/aiohttp-apispec/blob/master/docs/usage.rst
class ResponseSchema(Schema):
msg = fields.Str()
data = fields.Dict()
@docs(tags=['mytag'],
summary='Test method summary',
description='Test method description')
@request_schema(RequestSchema(strict=True))
@response_schema(ResponseSchema(), 200)
async def index(request):
return web.json_response({'msg': 'done',
'data': {}})
- Run it, get error
Traceback (most recent call last):
...
@request_schema(RequestSchema(strict=True))
TypeError: __init__() got an unexpected keyword argument 'strict'
- Let's add not-in-schema field
@response_schema(ResponseSchema(), 200)
return web.json_response({'msg': 'done',
'data': {}, 'foo': 'bar'})
It seems that ResponseSchema
didn't validate response
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Server: Python/3.8 aiohttp/3.6.2
{
"data": {},
"foo": "bar",
"msg": "done"
}
But directly it will
>>> ResponseSchema().validate({'msg': 'done', 'data': {}, 'foo': 'bar'})
{'foo': ['Unknown field.']}
@elsimqoz did you add validation middlware to your app?
@maximdanilchenko yes
from aiohttp_apispec import setup_aiohttp_apispec, validation_middleware
app = Application(
...
middlewares=[error_middleware, validation_middleware],
)
setup_aiohttp_apispec(
...
error_callback=handle_validation_error,
)
=======
def format_http_error(http_error_cls, message: Optional[str] = None,
fields: Optional[Mapping] = None) -> HTTPException:
status = HTTPStatus(http_error_cls.status_code)
error = {
'code': status.name.lower(),
'message': message or status.description
}
if fields:
error['fields'] = fields
return http_error_cls(body={'error': error})
def handle_validation_error(error: ValidationError, *_):
raise format_http_error(HTTPBadRequest, 'Request validation has failed', error.messages)
@middleware
async def error_middleware(request: Request, handler):
try:
return await handler(request)
except HTTPException as err:
if not isinstance(err.body, JsonPayload):
err = format_http_error(err.__class__, err.text)
raise err
except ValidationError as err:
raise handle_validation_error(err)
except Exception:
log.exception('Unhandled exception')
raise format_http_error(HTTPInternalServerError)
Oh, @elsimqoz, sorry, I missed that you wrote about response validation. Yes, aiohttp-apispec cannot validate responses. And I don’t think it is necessary. If you don’t think so you are welcome for PR’s:)