wheezy.web / src / wheezy / web / middleware / errors.py

""" ``errors`` module.
"""

import sys

from traceback import format_exception_only

from wheezy.core.collections import defaultdict
from wheezy.http.response import internal_error
from wheezy.http.response import not_found
from wheezy.web.handlers.base import RedirectRouteHandler


class HTTPErrorMiddleware(object):
    """ http error middleware
    """

    def __init__(self, error_mapping, logger, extra_provider=None):
        assert error_mapping is not None
        self.error_mapping = error_mapping
        self.logger = logger
        self.extra_provider = extra_provider

    def __call__(self, request, following):
        assert following is not None
        try:
            response = following(request)
            if response is None:
                response = not_found()
        except (KeyboardInterrupt, SystemExit, MemoryError):
            raise
        except Exception:
            exc_info = sys.exc_info()
            extra = self.extra_provider and self.extra_provider(request) or {}
            self.logger.error(
                ''.join(format_exception_only(*exc_info[:2])).strip('\n'),
                exc_info=exc_info,
                extra=extra)
            sys.exc_clear()
            response = internal_error()
        status_code = response.status_code
        if status_code >= 400:
            error_route_name = self.error_mapping[status_code]
            route_name = request.environ['route_args']['route_name']
            if error_route_name != route_name:
                response = RedirectRouteHandler(request, error_route_name)
        return response


def http_error_middleware_factory(options):
    """ HTTP error middleware factory.
    """
    import logging
    if 'http_errors' in options:
        path_for = options['path_for']
        error_mapping = options['http_errors']
        assert isinstance(error_mapping, defaultdict)
        assert path_for(error_mapping.default_factory()) is not None
        for route_name in error_mapping.values():
            assert path_for(route_name) is not None
    else:
        error_mapping = defaultdict(str)
    if 'http_errors_logger' in options:
        logger = options['http_errors_logger']
    else:
        logger = logging.getLogger('unhandled')
        if not logger.handlers:
            logger.setLevel(logging.ERROR)
            logger.addHandler(logging.StreamHandler(sys.stderr))
    return HTTPErrorMiddleware(
        error_mapping,
        logger,
        options.get('http_errors_extra_provider', None),
    )
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.