diff options
| author | Russell Keith-Magee <russell@keith-magee.com> | 2010-10-30 07:19:04 +0000 |
|---|---|---|
| committer | Russell Keith-Magee <russell@keith-magee.com> | 2010-10-30 07:19:04 +0000 |
| commit | 52e0bcbc62c4df5d488b18f6a8e2cba798ec0807 (patch) | |
| tree | 3f2e6ab6e822f06bc44b7c891def8f55848bea00 /django/core | |
| parent | 20e09ca817ecea7b20314481aa017809169f60e4 (diff) | |
Fixed #14588 -- Corrected r14393 to ensure that response middlewares are are always applied. Includes a battery of tests to validate the expected behavior of the middleware cycle. Thanks to Petr Marhoun for the report.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@14398 bcc190cf-cafb-0310-a4f2-bffc1f526a37
Diffstat (limited to 'django/core')
| -rw-r--r-- | django/core/handlers/base.py | 79 |
1 files changed, 44 insertions, 35 deletions
diff --git a/django/core/handlers/base.py b/django/core/handlers/base.py index df79ad2029..6002d54443 100644 --- a/django/core/handlers/base.py +++ b/django/core/handlers/base.py @@ -78,39 +78,43 @@ class BaseHandler(object): urlconf = settings.ROOT_URLCONF urlresolvers.set_urlconf(urlconf) resolver = urlresolvers.RegexURLResolver(r'^/', urlconf) + response = None # Apply request middleware for middleware_method in self._request_middleware: response = middleware_method(request) if response: - return response + break - if hasattr(request, "urlconf"): - # Reset url resolver with a custom urlconf. - urlconf = request.urlconf - urlresolvers.set_urlconf(urlconf) - resolver = urlresolvers.RegexURLResolver(r'^/', urlconf) - - callback, callback_args, callback_kwargs = resolver.resolve( - request.path_info) + if response is None: + if hasattr(request, "urlconf"): + # Reset url resolver with a custom urlconf. + urlconf = request.urlconf + urlresolvers.set_urlconf(urlconf) + resolver = urlresolvers.RegexURLResolver(r'^/', urlconf) - # Apply view middleware - for middleware_method in self._view_middleware: - response = middleware_method(request, callback, callback_args, callback_kwargs) - if response: - return response + callback, callback_args, callback_kwargs = resolver.resolve( + request.path_info) - try: - response = callback(request, *callback_args, **callback_kwargs) - except Exception, e: - # If the view raised an exception, run it through exception - # middleware, and if the exception middleware returns a - # response, use that. Otherwise, reraise the exception. - for middleware_method in self._exception_middleware: - response = middleware_method(request, e) + # Apply view middleware + for middleware_method in self._view_middleware: + response = middleware_method(request, callback, callback_args, callback_kwargs) if response: - return response - raise + break + + if response is None: + try: + response = callback(request, *callback_args, **callback_kwargs) + except Exception, e: + # If the view raised an exception, run it through exception + # middleware, and if the exception middleware returns a + # response, use that. Otherwise, reraise the exception. + for middleware_method in self._exception_middleware: + response = middleware_method(request, e) + if response: + break + if response is None: + raise # Complain if the view returned None (a common error). if response is None: @@ -120,12 +124,6 @@ class BaseHandler(object): view_name = callback.__class__.__name__ + '.__call__' # If it's a class raise ValueError("The view %s.%s didn't return an HttpResponse object." % (callback.__module__, view_name)) - # Apply response middleware - for middleware_method in self._response_middleware: - response = middleware_method(request, response) - response = self.apply_response_fixes(request, response) - - return response except http.Http404, e: logger.warning('Not Found: %s' % request.path, extra={ @@ -134,14 +132,14 @@ class BaseHandler(object): }) if settings.DEBUG: from django.views import debug - return debug.technical_404_response(request, e) + response = debug.technical_404_response(request, e) else: try: callback, param_dict = resolver.resolve404() - return callback(request, **param_dict) + response = callback(request, **param_dict) except: try: - return self.handle_uncaught_exception(request, resolver, sys.exc_info()) + response = self.handle_uncaught_exception(request, resolver, sys.exc_info()) finally: receivers = signals.got_request_exception.send(sender=self.__class__, request=request) except exceptions.PermissionDenied: @@ -150,19 +148,30 @@ class BaseHandler(object): 'status_code': 403, 'request': request }) - return http.HttpResponseForbidden('<h1>Permission denied</h1>') + response = http.HttpResponseForbidden('<h1>Permission denied</h1>') except SystemExit: # Allow sys.exit() to actually exit. See tickets #1023 and #4701 raise except: # Handle everything else, including SuspiciousOperation, etc. # Get the exception info now, in case another exception is thrown later. receivers = signals.got_request_exception.send(sender=self.__class__, request=request) - return self.handle_uncaught_exception(request, resolver, sys.exc_info()) + response = self.handle_uncaught_exception(request, resolver, sys.exc_info()) finally: # Reset URLconf for this thread on the way out for complete # isolation of request.urlconf urlresolvers.set_urlconf(None) + try: + # Apply response middleware, regardless of the response + for middleware_method in self._response_middleware: + response = middleware_method(request, response) + response = self.apply_response_fixes(request, response) + except: # Any exception should be gathered and handled + receivers = signals.got_request_exception.send(sender=self.__class__, request=request) + response = self.handle_uncaught_exception(request, resolver, sys.exc_info()) + + return response + def handle_uncaught_exception(self, request, resolver, exc_info): """ Processing for any otherwise uncaught exceptions (those that will |
