maximdanilchenko/aiohttp-apispec

Customize HTTP status on validation error

v-v-vishnevskiy opened this issue · 1 comments

I offer this idea:

from aiohttp import web
from webargs.aiohttpparser import AIOHTTPParser

from .utils import issubclass_py37fix


def validation_middleware(status: int = AIOHTTPParser.DEFAULT_VALIDATION_STATUS):

    class Parser(AIOHTTPParser):
        DEFAULT_VALIDATION_STATUS = status

    parser = Parser()

    @web.middleware
    async def middleware(request: web.Request, handler) -> web.Response:
        """
        Validation middleware for aiohttp web app

        Usage:

        .. code-block:: python

            app.middlewares.append(validation_middleware)


        """
        orig_handler = request.match_info.handler
        if not hasattr(orig_handler, "__schemas__"):
            if not issubclass_py37fix(orig_handler, web.View):
                return await handler(request)
            sub_handler = getattr(orig_handler, request.method.lower(), None)
            if sub_handler is None:
                return await handler(request)
            if not hasattr(sub_handler, "__schemas__"):
                return await handler(request)
            schemas = sub_handler.__schemas__
        else:
            schemas = orig_handler.__schemas__
        kwargs = {}
        for schema in schemas:
            data = await parser.parse(
                schema["schema"], request, locations=schema["locations"]
            )
            if data:
                kwargs.update(data)
        kwargs.update(request.match_info)
        request[request.app["_apispec_request_data_name"]] = kwargs
        return await handler(request)
    return middleware

and app.middlewares.insert(0, validation_middleware(400))

Hi!
Yes, that's a good idea! But it should be a new function in api (like create_validation_middleware).

I already add error_callback parameter to setup_aiohttp_apispec so you can make your custom error handler.

And if we will decide to add this middleware fabric to the library, it should not have conflicts in interface with setup_aiohttp_apispec.