diff options
| author | Florian Apolloner <florian@apolloner.eu> | 2016-05-02 12:37:49 -0400 |
|---|---|---|
| committer | Tim Graham <timograham@gmail.com> | 2016-05-17 07:20:56 -0400 |
| commit | 05c888ffb843ba3eff06cd07b3cef5bbb513a54f (patch) | |
| tree | 3ec9005aa282e5ccc8b0bd5e47ed3e3c0ae4e71a /django/middleware | |
| parent | c999c8d8f61dbfc9998620f668aa8c0c610e3845 (diff) | |
Refs #26601 -- Refactored BaseHandler to prepare for new-style middleware.
Diffstat (limited to 'django/middleware')
| -rw-r--r-- | django/middleware/exception.py | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/django/middleware/exception.py b/django/middleware/exception.py new file mode 100644 index 0000000000..437a82cf26 --- /dev/null +++ b/django/middleware/exception.py @@ -0,0 +1,78 @@ +from __future__ import unicode_literals + +import logging +import sys + +from django.conf import settings +from django.core import signals +from django.core.exceptions import PermissionDenied, SuspiciousOperation +from django.http import Http404 +from django.http.multipartparser import MultiPartParserError +from django.urls import get_resolver, get_urlconf +from django.utils.encoding import force_text +from django.views import debug + +logger = logging.getLogger('django.request') + + +class ExceptionMiddleware(object): + """ + Convert selected exceptions to HTTP responses. + + For example, convert Http404 to a 404 response either through handler404 + or through the debug view if settings.DEBUG=True. To ensure that + exceptions raised by other middleware are converted to the appropriate + response, this middleware is always automatically applied as the outermost + middleware. + """ + def __init__(self, get_response, handler=None): + from django.core.handlers.base import BaseHandler + self.get_response = get_response + self.handler = handler or BaseHandler() + + def __call__(self, request): + try: + response = self.get_response(request) + except Http404 as exc: + if settings.DEBUG: + response = debug.technical_404_response(request, exc) + else: + response = self.handler.get_exception_response(request, get_resolver(get_urlconf()), 404, exc) + + except PermissionDenied as exc: + logger.warning( + 'Forbidden (Permission denied): %s', request.path, + extra={'status_code': 403, 'request': request}, + ) + response = self.handler.get_exception_response(request, get_resolver(get_urlconf()), 403, exc) + + except MultiPartParserError as exc: + logger.warning( + 'Bad request (Unable to parse request body): %s', request.path, + extra={'status_code': 400, 'request': request}, + ) + response = self.handler.get_exception_response(request, get_resolver(get_urlconf()), 400, exc) + + except SuspiciousOperation as exc: + # The request logger receives events for any problematic request + # The security logger receives events for all SuspiciousOperations + security_logger = logging.getLogger('django.security.%s' % exc.__class__.__name__) + security_logger.error( + force_text(exc), + extra={'status_code': 400, 'request': request}, + ) + if settings.DEBUG: + return debug.technical_500_response(request, *sys.exc_info(), status_code=400) + + response = self.handler.get_exception_response(request, get_resolver(get_urlconf()), 400, exc) + + except SystemExit: + # Allow sys.exit() to actually exit. See tickets #1023 and #4701 + raise + + except Exception: # Handle everything else. + # Get the exception info now, in case another exception is thrown later. + signals.got_request_exception.send(sender=self.handler.__class__, request=request) + response = self.handler.handle_uncaught_exception(request, get_resolver(get_urlconf()), sys.exc_info()) + + return response |
