app/django/core/handlers/base.py
changeset 323 ff1a9aa48cfd
parent 54 03e267d67478
equal deleted inserted replaced
322:6641e941ef1e 323:ff1a9aa48cfd
     1 import sys
     1 import sys
     2 
     2 
     3 from django import http
     3 from django import http
     4 from django.core import signals
     4 from django.core import signals
     5 from django.dispatch import dispatcher
     5 from django.utils.encoding import force_unicode
     6 
     6 
     7 class BaseHandler(object):
     7 class BaseHandler(object):
     8     # Changes that are always applied to a response (in this order).
     8     # Changes that are always applied to a response (in this order).
     9     response_fixes = [http.fix_location_header,
     9     response_fixes = [
    10             http.conditional_content_removal]
    10         http.fix_location_header,
       
    11         http.conditional_content_removal,
       
    12         http.fix_IE_for_attach,
       
    13         http.fix_IE_for_vary,
       
    14     ]
    11 
    15 
    12     def __init__(self):
    16     def __init__(self):
    13         self._request_middleware = self._view_middleware = self._response_middleware = self._exception_middleware = None
    17         self._request_middleware = self._view_middleware = self._response_middleware = self._exception_middleware = None
    14 
    18 
    15     def load_middleware(self):
    19     def load_middleware(self):
    54                 self._exception_middleware.insert(0, mw_instance.process_exception)
    58                 self._exception_middleware.insert(0, mw_instance.process_exception)
    55 
    59 
    56     def get_response(self, request):
    60     def get_response(self, request):
    57         "Returns an HttpResponse object for the given HttpRequest"
    61         "Returns an HttpResponse object for the given HttpRequest"
    58         from django.core import exceptions, urlresolvers
    62         from django.core import exceptions, urlresolvers
    59         from django.core.mail import mail_admins
       
    60         from django.conf import settings
    63         from django.conf import settings
    61 
    64 
    62         # Apply request middleware
    65         # Apply request middleware
    63         for middleware_method in self._request_middleware:
    66         for middleware_method in self._request_middleware:
    64             response = middleware_method(request)
    67             response = middleware_method(request)
    68         # Get urlconf from request object, if available.  Otherwise use default.
    71         # Get urlconf from request object, if available.  Otherwise use default.
    69         urlconf = getattr(request, "urlconf", settings.ROOT_URLCONF)
    72         urlconf = getattr(request, "urlconf", settings.ROOT_URLCONF)
    70 
    73 
    71         resolver = urlresolvers.RegexURLResolver(r'^/', urlconf)
    74         resolver = urlresolvers.RegexURLResolver(r'^/', urlconf)
    72         try:
    75         try:
    73             callback, callback_args, callback_kwargs = resolver.resolve(request.path)
    76             callback, callback_args, callback_kwargs = resolver.resolve(
       
    77                     request.path_info)
    74 
    78 
    75             # Apply view middleware
    79             # Apply view middleware
    76             for middleware_method in self._view_middleware:
    80             for middleware_method in self._view_middleware:
    77                 response = middleware_method(request, callback, callback_args, callback_kwargs)
    81                 response = middleware_method(request, callback, callback_args, callback_kwargs)
    78                 if response:
    82                 if response:
   102         except http.Http404, e:
   106         except http.Http404, e:
   103             if settings.DEBUG:
   107             if settings.DEBUG:
   104                 from django.views import debug
   108                 from django.views import debug
   105                 return debug.technical_404_response(request, e)
   109                 return debug.technical_404_response(request, e)
   106             else:
   110             else:
   107                 callback, param_dict = resolver.resolve404()
   111                 try:
   108                 return callback(request, **param_dict)
   112                     callback, param_dict = resolver.resolve404()
       
   113                     return callback(request, **param_dict)
       
   114                 except:
       
   115                     try:
       
   116                         return self.handle_uncaught_exception(request, resolver, sys.exc_info())
       
   117                     finally:
       
   118                         receivers = signals.got_request_exception.send(sender=self.__class__, request=request)
   109         except exceptions.PermissionDenied:
   119         except exceptions.PermissionDenied:
   110             return http.HttpResponseForbidden('<h1>Permission denied</h1>')
   120             return http.HttpResponseForbidden('<h1>Permission denied</h1>')
   111         except SystemExit:
   121         except SystemExit:
   112             # Allow sys.exit() to actually exit. See tickets #1023 and #4701
   122             # Allow sys.exit() to actually exit. See tickets #1023 and #4701
   113             raise
   123             raise
   114         except: # Handle everything else, including SuspiciousOperation, etc.
   124         except: # Handle everything else, including SuspiciousOperation, etc.
   115             # Get the exception info now, in case another exception is thrown later.
   125             # Get the exception info now, in case another exception is thrown later.
   116             exc_info = sys.exc_info()
   126             exc_info = sys.exc_info()
   117             receivers = dispatcher.send(signal=signals.got_request_exception, request=request)
   127             receivers = signals.got_request_exception.send(sender=self.__class__, request=request)
   118 
   128             return self.handle_uncaught_exception(request, resolver, exc_info)
   119             if settings.DEBUG_PROPAGATE_EXCEPTIONS:
   129 
   120                 raise
   130     def handle_uncaught_exception(self, request, resolver, exc_info):
   121             elif settings.DEBUG:
   131         """
   122                 from django.views import debug
   132         Processing for any otherwise uncaught exceptions (those that will
   123                 return debug.technical_500_response(request, *exc_info)
   133         generate HTTP 500 responses). Can be overridden by subclasses who want
   124             else:
   134         customised 500 handling.
   125                 # When DEBUG is False, send an error message to the admins.
   135 
   126                 subject = 'Error (%s IP): %s' % ((request.META.get('REMOTE_ADDR') in settings.INTERNAL_IPS and 'internal' or 'EXTERNAL'), request.path)
   136         Be *very* careful when overriding this because the error could be
   127                 try:
   137         caused by anything, so assuming something like the database is always
   128                     request_repr = repr(request)
   138         available would be an error.
   129                 except:
   139         """
   130                     request_repr = "Request repr() unavailable"
   140         from django.conf import settings
   131                 message = "%s\n\n%s" % (self._get_traceback(exc_info), request_repr)
   141         from django.core.mail import mail_admins
   132                 mail_admins(subject, message, fail_silently=True)
   142 
   133                 # Return an HttpResponse that displays a friendly error message.
   143         if settings.DEBUG_PROPAGATE_EXCEPTIONS:
   134                 callback, param_dict = resolver.resolve500()
   144             raise
   135                 return callback(request, **param_dict)
   145 
       
   146         if settings.DEBUG:
       
   147             from django.views import debug
       
   148             return debug.technical_500_response(request, *exc_info)
       
   149 
       
   150         # When DEBUG is False, send an error message to the admins.
       
   151         subject = 'Error (%s IP): %s' % ((request.META.get('REMOTE_ADDR') in settings.INTERNAL_IPS and 'internal' or 'EXTERNAL'), request.path)
       
   152         try:
       
   153             request_repr = repr(request)
       
   154         except:
       
   155             request_repr = "Request repr() unavailable"
       
   156         message = "%s\n\n%s" % (self._get_traceback(exc_info), request_repr)
       
   157         mail_admins(subject, message, fail_silently=True)
       
   158         # Return an HttpResponse that displays a friendly error message.
       
   159         callback, param_dict = resolver.resolve500()
       
   160         return callback(request, **param_dict)
   136 
   161 
   137     def _get_traceback(self, exc_info=None):
   162     def _get_traceback(self, exc_info=None):
   138         "Helper function to return the traceback as a string"
   163         "Helper function to return the traceback as a string"
   139         import traceback
   164         import traceback
   140         return '\n'.join(traceback.format_exception(*(exc_info or sys.exc_info())))
   165         return '\n'.join(traceback.format_exception(*(exc_info or sys.exc_info())))
   147         """
   172         """
   148         for func in self.response_fixes:
   173         for func in self.response_fixes:
   149             response = func(request, response)
   174             response = func(request, response)
   150         return response
   175         return response
   151 
   176 
       
   177 def get_script_name(environ):
       
   178     """
       
   179     Returns the equivalent of the HTTP request's SCRIPT_NAME environment
       
   180     variable. If Apache mod_rewrite has been used, returns what would have been
       
   181     the script name prior to any rewriting (so it's the script name as seen
       
   182     from the client's perspective), unless DJANGO_USE_POST_REWRITE is set (to
       
   183     anything).
       
   184     """
       
   185     from django.conf import settings
       
   186     if settings.FORCE_SCRIPT_NAME is not None:
       
   187         return force_unicode(settings.FORCE_SCRIPT_NAME)
       
   188 
       
   189     # If Apache's mod_rewrite had a whack at the URL, Apache set either
       
   190     # SCRIPT_URL or REDIRECT_URL to the full resource URL before applying any
       
   191     # rewrites. Unfortunately not every webserver (lighttpd!) passes this
       
   192     # information through all the time, so FORCE_SCRIPT_NAME, above, is still
       
   193     # needed.
       
   194     script_url = environ.get('SCRIPT_URL', u'')
       
   195     if not script_url:
       
   196         script_url = environ.get('REDIRECT_URL', u'')
       
   197     if script_url:
       
   198         return force_unicode(script_url[:-len(environ.get('PATH_INFO', ''))])
       
   199     return force_unicode(environ.get('SCRIPT_NAME', u''))
       
   200