django1/django/middleware/exception.py

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