Ejemplo n.º 1
0
def prepare_middleware(middleware=None):
    """Check middleware interface and prepare it to iterate.

    Args:
        middleware:  list (or object) of input middleware

    Returns:
        A middleware list
    """

    # PERF(kgriffs): do getattr calls once, in advance, so we don't
    # have to do them every time in the request path.
    prepared_middleware = []

    if middleware is None:
        middleware = []
    else:
        if not isinstance(middleware, list):
            middleware = [middleware]

    for component in middleware:
        process_request = util.get_bound_method(component, "process_request")
        process_resource = util.get_bound_method(component, "process_resource")
        process_response = util.get_bound_method(component, "process_response")

        if not (process_request or process_resource or process_response):
            msg = "{0} does not implement the middleware interface"
            raise TypeError(msg.format(component))

        prepared_middleware.append((process_request, process_resource, process_response))

    return prepared_middleware
Ejemplo n.º 2
0
def prepare_middleware(middleware=None):
    """Check middleware interface and prepare it to iterate.

    Args:
        middleware:  list (or object) of input middleware

    Returns:
        A middleware list
    """

    # PERF(kgriffs): do getattr calls once, in advance, so we don't
    # have to do them every time in the request path.
    prepared_middleware = []

    if middleware is None:
        middleware = []
    else:
        if not isinstance(middleware, list):
            middleware = [middleware]

    for component in middleware:
        process_request = util.get_bound_method(component, 'process_request')
        process_resource = util.get_bound_method(component, 'process_resource')
        process_response = util.get_bound_method(component, 'process_response')

        if not (process_request or process_resource or process_response):
            msg = '{0} does not implement the middleware interface'
            raise TypeError(msg.format(component))

        prepared_middleware.append(
            (process_request, process_resource, process_response))

    return prepared_middleware
Ejemplo n.º 3
0
def prepare_middleware(middleware=None, independent_middleware=False):
    """Check middleware interface and prepare it to iterate.

    Args:
        middleware: list (or object) of input middleware
        independent_middleware: bool whether should prepare request and
            response middleware independently

    Returns:
        list: A tuple of prepared middleware tuples
    """

    # PERF(kgriffs): do getattr calls once, in advance, so we don't
    # have to do them every time in the request path.
    request_mw = []
    resource_mw = []
    response_mw = []

    if middleware is None:
        middleware = []
    else:
        if not isinstance(middleware, list):
            middleware = [middleware]

    for component in middleware:
        process_request = util.get_bound_method(component,
                                                'process_request')
        process_resource = util.get_bound_method(component,
                                                 'process_resource')
        process_response = util.get_bound_method(component,
                                                 'process_response')

        if not (process_request or process_resource or process_response):
            msg = '{0} does not implement the middleware interface'
            raise TypeError(msg.format(component))

        # NOTE: depending on whether we want to execute middleware
        # independently, we group response and request middleware either
        # together or separately.
        if independent_middleware:
            if process_request:
                request_mw.append(process_request)
            if process_response:
                response_mw.insert(0, process_response)
        else:
            if process_request or process_response:
                request_mw.append((process_request, process_response))

        if process_resource:
            resource_mw.append(process_resource)

    return (tuple(request_mw), tuple(resource_mw), tuple(response_mw))
Ejemplo n.º 4
0
def prepare_middleware(middleware=None, independent_middleware=False):
    """Check middleware interface and prepare it to iterate.

    Args:
        middleware: list (or object) of input middleware
        independent_middleware: bool whether should prepare request and
            response middleware independently

    Returns:
        list: A tuple of prepared middleware tuples
    """

    # PERF(kgriffs): do getattr calls once, in advance, so we don't
    # have to do them every time in the request path.
    request_mw = []
    resource_mw = []
    response_mw = []

    if middleware is None:
        middleware = []
    else:
        if not isinstance(middleware, list):
            middleware = [middleware]

    for component in middleware:
        process_request = util.get_bound_method(component,
                                                'process_request')
        process_resource = util.get_bound_method(component,
                                                 'process_resource')
        process_response = util.get_bound_method(component,
                                                 'process_response')

        if not (process_request or process_resource or process_response):
            msg = '{0} does not implement the middleware interface'
            raise TypeError(msg.format(component))

        # NOTE: depending on whether we want to execute middleware
        # independently, we group response and request middleware either
        # together or separately.
        if independent_middleware:
            if process_request:
                request_mw.append(process_request)
            if process_response:
                response_mw.insert(0, process_response)
        else:
            if process_request or process_response:
                request_mw.append((process_request, process_response))

        if process_resource:
            resource_mw.append(process_resource)

    return (tuple(request_mw), tuple(resource_mw), tuple(response_mw))
Ejemplo n.º 5
0
    def add_middleware(self, mw):
        process_request = util.get_bound_method(mw, 'process_request')
        process_resource = util.get_bound_method(mw, 'process_resource')
        process_response = util.get_bound_method(mw, 'process_response')

        if process_request:
            self.req_mw.append(process_request)

        if process_resource:
            self.resc_mw.append(process_resource)

        if process_response:
            self.resp_mw.append(process_response)
Ejemplo n.º 6
0
def prepare_middleware(middleware=None):
    """Check middleware interface and prepare it to iterate.

    Args:
        middleware:  list (or object) of input middleware

    Returns:
        list: A list of prepared middleware tuples
    """

    # PERF(kgriffs): do getattr calls once, in advance, so we don't
    # have to do them every time in the request path.
    prepared_middleware = []

    if middleware is None:
        middleware = []
    else:
        if not isinstance(middleware, list):
            middleware = [middleware]

    for component in middleware:
        process_request = util.get_bound_method(component,
                                                'process_request')
        process_resource = util.get_bound_method(component,
                                                 'process_resource')
        process_response = util.get_bound_method(component,
                                                 'process_response')

        if not (process_request or process_resource or process_response):
            msg = '{0} does not implement the middleware interface'
            raise TypeError(msg.format(component))

        if process_response:
            # NOTE(kgriffs): Shim older implementations to ensure
            # backwards-compatibility.
            args = util.get_argnames(process_response)

            if len(args) == 3:  # (req, resp, resource)
                def let(process_response=process_response):
                    @wraps(process_response)
                    def shim(req, resp, resource, req_succeeded):
                        process_response(req, resp, resource)

                    return shim

                process_response = let()

        prepared_middleware.append((process_request, process_resource,
                                    process_response))

    return prepared_middleware
Ejemplo n.º 7
0
def prepare_middleware_ws(middleware):
    """Check middleware interfaces and prepare WebSocket methods for request handling.

    Note:
        This method is only applicable to ASGI apps.

    Arguments:
        middleware (iterable): An iterable of middleware objects.

    Returns:
        tuple: A two-item ``(request_mw, resource_mw)`` tuple, where
        *request_mw* is an ordered list of ``process_request_ws()`` methods,
        and *resource_mw* is an ordered list of ``process_resource_ws()``
        methods.
    """

    # PERF(kgriffs): do getattr calls once, in advance, so we don't
    # have to do them every time in the request path.
    request_mw = []
    resource_mw = []

    for component in middleware:
        process_request_ws = util.get_bound_method(component,
                                                   'process_request_ws')
        process_resource_ws = util.get_bound_method(component,
                                                    'process_resource_ws')

        for m in (process_request_ws, process_resource_ws):
            if not m:
                continue

            # NOTE(kgriffs): iscoroutinefunction() always returns False
            #   for cythonized functions.
            #
            #   https://github.com/cython/cython/issues/2273
            #   https://bugs.python.org/issue38225
            #
            if not iscoroutinefunction(m) and util.is_python_func(m):
                msg = '{} must be implemented as an awaitable coroutine.'
                raise CompatibilityError(msg.format(m))

        if process_request_ws:
            request_mw.append(process_request_ws)

        if process_resource_ws:
            resource_mw.append(process_resource_ws)

    return request_mw, resource_mw
Ejemplo n.º 8
0
def prepare_middleware(middleware, independent_middleware=False, asgi=False):
    """Check middleware interfaces and prepare the methods for request handling.

    Arguments:
        middleware (iterable): An iterable of middleware objects.

    Keyword Args:
        independent_middleware (bool): ``True`` if the request and
            response middleware methods should be treated independently
            (default ``False``)
        asgi (bool): ``True`` if an ASGI app, ``False`` otherwise
            (default ``False``)

    Returns:
        tuple: A tuple of prepared middleware method tuples
    """

    # PERF(kgriffs): do getattr calls once, in advance, so we don't
    # have to do them every time in the request path.
    request_mw = []
    resource_mw = []
    response_mw = []

    for component in middleware:
        # NOTE(kgriffs): Middleware that uses parts of the Request and Response
        #   interfaces that are the same between ASGI and WSGI (most of it is,
        #   and we should probably define this via ABC) can just implement
        #   the method names without the *_async postfix. If a middleware
        #   component wants to provide an alternative implementation that
        #   does some work that requires async def, or something specific about
        #   the ASGI Request/Response classes, the component can implement the
        #   *_async method in that case.
        #
        #   Middleware that is WSGI-only or ASGI-only can simply implement all
        #   methods without the *_async postfix. Regardless, components should
        #   clearly document their compatibility with WSGI vs. ASGI.

        if asgi:
            process_request = (
                util.get_bound_method(component, 'process_request_async') or
                _wrap_non_coroutine_unsafe(
                    util.get_bound_method(component, 'process_request')
                )
            )

            process_resource = (
                util.get_bound_method(component, 'process_resource_async') or
                _wrap_non_coroutine_unsafe(
                    util.get_bound_method(component, 'process_resource')
                )
            )

            process_response = (
                util.get_bound_method(component, 'process_response_async') or
                _wrap_non_coroutine_unsafe(
                    util.get_bound_method(component, 'process_response')
                )
            )

            for m in (process_request, process_resource, process_response):
                if m and not iscoroutinefunction(m):
                    msg = (
                        '{} must be implemented as an awaitable coroutine. If '
                        'you would like to retain compatibility '
                        'with WSGI apps, the coroutine versions of the '
                        'middleware methods may be implemented side-by-side '
                        'by applying an *_async postfix to the method names. '
                    )
                    raise CompatibilityError(msg.format(m))

        else:
            process_request = util.get_bound_method(component, 'process_request')
            process_resource = util.get_bound_method(component, 'process_resource')
            process_response = util.get_bound_method(component, 'process_response')

            for m in (process_request, process_resource, process_response):
                if m and iscoroutinefunction(m):
                    msg = (
                        '{} may not implement coroutine methods and '
                        'remain compatible with WSGI apps without '
                        'using the *_async postfix to explicitly identify '
                        'the coroutine version of a given middleware '
                        'method.'
                    )
                    raise CompatibilityError(msg.format(component))

        if not (process_request or process_resource or process_response):
            if asgi and (
                hasattr(component, 'process_startup') or hasattr(component, 'process_shutdown')
            ):
                # NOTE(kgriffs): This middleware only has ASGI lifespan
                #   event handlers
                continue

            msg = '{0} must implement at least one middleware method'
            raise TypeError(msg.format(component))

        # NOTE: depending on whether we want to execute middleware
        # independently, we group response and request middleware either
        # together or separately.
        if independent_middleware:
            if process_request:
                request_mw.append(process_request)
            if process_response:
                response_mw.insert(0, process_response)
        else:
            if process_request or process_response:
                request_mw.append((process_request, process_response))

        if process_resource:
            resource_mw.append(process_resource)

    return (tuple(request_mw), tuple(resource_mw), tuple(response_mw))
Ejemplo n.º 9
0
def prepare_middleware(middleware, independent_middleware=False, asgi=False):
    """Check middleware interfaces and prepare the methods for request handling.

    Arguments:
        middleware (iterable): An iterable of middleware objects.

    Keyword Args:
        independent_middleware (bool): ``True`` if the request and
            response middleware methods should be treated independently
            (default ``False``)
        asgi (bool): ``True`` if an ASGI app, ``False`` otherwise
            (default ``False``)

    Returns:
        tuple: A tuple of prepared middleware method tuples
    """

    # PERF(kgriffs): do getattr calls once, in advance, so we don't
    # have to do them every time in the request path.
    request_mw = []
    resource_mw = []
    response_mw = []

    for component in middleware:
        # NOTE(kgriffs): Middleware that supports both WSGI and ASGI can
        #   append an *_async postfix to the ASGI version of the method
        #   to distinguish the two. Otherwise, the prefix is unnecessary.

        if asgi:
            process_request = (
                util.get_bound_method(component, 'process_request_async')
                or _wrap_non_coroutine_unsafe(
                    util.get_bound_method(component, 'process_request')))

            process_resource = (
                util.get_bound_method(component, 'process_resource_async')
                or _wrap_non_coroutine_unsafe(
                    util.get_bound_method(component, 'process_resource')))

            process_response = (
                util.get_bound_method(component, 'process_response_async')
                or _wrap_non_coroutine_unsafe(
                    util.get_bound_method(component, 'process_response')))

            for m in (process_request, process_resource, process_response):
                # NOTE(kgriffs): iscoroutinefunction() always returns False
                #   for cythonized functions.
                #
                #   https://github.com/cython/cython/issues/2273
                #   https://bugs.python.org/issue38225
                #
                if m and not iscoroutinefunction(m) and util.is_python_func(m):
                    msg = (
                        '{} must be implemented as an awaitable coroutine. If '
                        'you would like to retain compatibility '
                        'with WSGI apps, the coroutine versions of the '
                        'middleware methods may be implemented side-by-side '
                        'by applying an *_async postfix to the method names. ')
                    raise CompatibilityError(msg.format(m))

        else:
            process_request = util.get_bound_method(component,
                                                    'process_request')
            process_resource = util.get_bound_method(component,
                                                     'process_resource')
            process_response = util.get_bound_method(component,
                                                     'process_response')

            for m in (process_request, process_resource, process_response):
                if m and iscoroutinefunction(m):
                    msg = ('{} may not implement coroutine methods and '
                           'remain compatible with WSGI apps without '
                           'using the *_async postfix to explicitly identify '
                           'the coroutine version of a given middleware '
                           'method.')
                    raise CompatibilityError(msg.format(component))

        if not (process_request or process_resource or process_response):
            if asgi and (hasattr(component, 'process_startup')
                         or hasattr(component, 'process_shutdown')):
                # NOTE(kgriffs): This middleware only has ASGI lifespan
                #   event handlers
                continue

            msg = '{0} must implement at least one middleware method'
            raise TypeError(msg.format(component))

        # NOTE: depending on whether we want to execute middleware
        # independently, we group response and request middleware either
        # together or separately.
        if independent_middleware:
            if process_request:
                request_mw.append(process_request)
            if process_response:
                response_mw.insert(0, process_response)
        else:
            if process_request or process_response:
                request_mw.append((process_request, process_response))

        if process_resource:
            resource_mw.append(process_resource)

    return (tuple(request_mw), tuple(resource_mw), tuple(response_mw))