79 lines
3.2 KiB
Python
79 lines
3.2 KiB
Python
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
|