Commit f5d5867a authored by Sylvain Fankhauser's avatar Sylvain Fankhauser Committed by Tim Graham
Browse files

Fixed #24877 -- Added middleware handling of response.render() errors.

parent b91a2a49
Loading
Loading
Loading
Loading
+17 −10
Original line number Diff line number Diff line
@@ -146,15 +146,7 @@ class BaseHandler(object):
                try:
                    response = wrapped_callback(request, *callback_args, **callback_kwargs)
                except Exception as 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
                    response = self.process_exception_by_middleware(e, request)

            # Complain if the view returned None (a common error).
            if response is None:
@@ -176,7 +168,11 @@ class BaseHandler(object):
                            "%s.process_template_response didn't return an "
                            "HttpResponse object. It returned None instead."
                            % (middleware_method.__self__.__class__.__name__))
                try:
                    response = response.render()
                except Exception as e:
                    response = self.process_exception_by_middleware(e, request)

                response_is_rendered = True

        except http.Http404 as exc:
@@ -257,6 +253,17 @@ class BaseHandler(object):

        return response

    def process_exception_by_middleware(self, exception, request):
        """
        Pass the exception to the exception middleware. If no middleware
        return a response for this exception, raise it.
        """
        for middleware_method in self._exception_middleware:
            response = middleware_method(request, exception)
            if response:
                return response
        raise

    def handle_uncaught_exception(self, request, resolver, exc_info):
        """
        Processing for any otherwise uncaught exceptions (those that will
+3 −0
Original line number Diff line number Diff line
@@ -480,6 +480,9 @@ Requests and Responses
  :class:`~django.template.response.TemplateResponse`, commonly used with
  class-based views.

* Exceptions raised by the ``render()`` method are now passed to the
  ``process_exception()`` method of each middleware.

* Request middleware can now set :attr:`HttpRequest.urlconf
  <django.http.HttpRequest.urlconf>` to ``None`` to revert any changes made
  by previous middleware and return to using the :setting:`ROOT_URLCONF`.
+8 −0
Original line number Diff line number Diff line
from __future__ import unicode_literals

from django.http import HttpResponse


class ProcessExceptionMiddleware(object):
    def process_exception(self, request, exception):
        return HttpResponse('Exception caught')
+10 −0
Original line number Diff line number Diff line
@@ -486,6 +486,16 @@ class MiddlewareTests(BaseMiddlewareExceptionTest):
        # Check that the right middleware methods have been invoked
        self.assert_middleware_usage(middleware, True, True, True, True, False)

    @override_settings(
        MIDDLEWARE_CLASSES=['middleware_exceptions.middleware.ProcessExceptionMiddleware'],
    )
    def test_exception_in_render_passed_to_process_exception(self):
        # Repopulate the list of middlewares since it's already been populated
        # by setUp() before the MIDDLEWARE_CLASSES setting got overridden
        self.client.handler.load_middleware()
        response = self.client.get('/middleware_exceptions/exception_in_render/')
        self.assertEqual(response.content, b'Exception caught')


class BadMiddlewareTests(BaseMiddlewareExceptionTest):

+1 −0
Original line number Diff line number Diff line
@@ -8,6 +8,7 @@ urlpatterns = [
    url(r'^middleware_exceptions/error/$', views.server_error),
    url(r'^middleware_exceptions/null_view/$', views.null_view),
    url(r'^middleware_exceptions/permission_denied/$', views.permission_denied),
    url(r'^middleware_exceptions/exception_in_render/$', views.exception_in_render),

    url(r'^middleware_exceptions/template_response/$', views.template_response),
    url(r'^middleware_exceptions/template_response_error/$', views.template_response_error),
Loading