summaryrefslogtreecommitdiff
path: root/django/middleware
diff options
context:
space:
mode:
Diffstat (limited to 'django/middleware')
-rw-r--r--django/middleware/exception.py78
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