mirror of
https://github.com/django/django.git
synced 2025-10-24 06:06:09 +00:00
[1.10.x] Refs #26601 -- Improved backwards-compatibility of DEP 5 middleware exception handling.
Backport of 7d1b69dbe7 from master
This commit is contained in:
@@ -1,10 +1,58 @@
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.http import HttpResponse
|
||||
from django.utils.deprecation import MiddlewareMixin
|
||||
from django.http import Http404, HttpResponse
|
||||
from django.template import engines
|
||||
|
||||
log = []
|
||||
|
||||
|
||||
class ProcessExceptionMiddleware(MiddlewareMixin):
|
||||
class BaseMiddleware(object):
|
||||
def __init__(self, get_response):
|
||||
self.get_response = get_response
|
||||
|
||||
def __call__(self, request):
|
||||
return self.get_response(request)
|
||||
|
||||
|
||||
class ProcessExceptionMiddleware(BaseMiddleware):
|
||||
def process_exception(self, request, exception):
|
||||
return HttpResponse('Exception caught')
|
||||
|
||||
|
||||
class ProcessExceptionLogMiddleware(BaseMiddleware):
|
||||
def process_exception(self, request, exception):
|
||||
log.append('process-exception')
|
||||
|
||||
|
||||
class ProcessExceptionExcMiddleware(BaseMiddleware):
|
||||
def process_exception(self, request, exception):
|
||||
raise Exception('from process-exception')
|
||||
|
||||
|
||||
class ProcessViewMiddleware(BaseMiddleware):
|
||||
def process_view(self, request, view_func, view_args, view_kwargs):
|
||||
return HttpResponse('Processed view %s' % view_func.__name__)
|
||||
|
||||
|
||||
class ProcessViewNoneMiddleware(BaseMiddleware):
|
||||
def process_view(self, request, view_func, view_args, view_kwargs):
|
||||
log.append('processed view %s' % view_func.__name__)
|
||||
return None
|
||||
|
||||
|
||||
class TemplateResponseMiddleware(BaseMiddleware):
|
||||
def process_template_response(self, request, response):
|
||||
response.template_name = engines['django'].from_string('template-response middleware')
|
||||
return response
|
||||
|
||||
|
||||
class LogMiddleware(BaseMiddleware):
|
||||
def __call__(self, request):
|
||||
response = self.get_response(request)
|
||||
log.append((response.status_code, response.content))
|
||||
return response
|
||||
|
||||
|
||||
class NotFoundMiddleware(BaseMiddleware):
|
||||
def __call__(self, request):
|
||||
raise Http404('not found')
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
import sys
|
||||
|
||||
from django.conf import settings
|
||||
from django.core.exceptions import MiddlewareNotUsed
|
||||
from django.core.signals import got_request_exception
|
||||
from django.http import HttpResponse
|
||||
from django.template import engines
|
||||
from django.template.response import TemplateResponse
|
||||
from django.test import RequestFactory, SimpleTestCase, override_settings
|
||||
from django.test.utils import ignore_warnings, patch_logger
|
||||
from django.test import SimpleTestCase, override_settings
|
||||
from django.test.utils import ignore_warnings
|
||||
from django.utils.deprecation import MiddlewareMixin, RemovedInDjango20Warning
|
||||
|
||||
from .tests import MiddlewareNotUsedTests
|
||||
|
||||
|
||||
class TestException(Exception):
|
||||
pass
|
||||
@@ -512,14 +512,6 @@ 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=['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 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):
|
||||
|
||||
@@ -869,79 +861,6 @@ class BadMiddlewareTests(BaseMiddlewareExceptionTest):
|
||||
self.assert_middleware_usage(middleware, True, True, True, True, False)
|
||||
self.assert_middleware_usage(post_middleware, True, True, True, True, False)
|
||||
|
||||
_missing = object()
|
||||
|
||||
|
||||
@override_settings(ROOT_URLCONF='middleware_exceptions.urls')
|
||||
class RootUrlconfTests(SimpleTestCase):
|
||||
|
||||
@override_settings(ROOT_URLCONF=None)
|
||||
def test_missing_root_urlconf(self):
|
||||
# Removing ROOT_URLCONF is safe, as override_settings will restore
|
||||
# the previously defined settings.
|
||||
del settings.ROOT_URLCONF
|
||||
with self.assertRaises(AttributeError):
|
||||
self.client.get("/middleware_exceptions/view/")
|
||||
|
||||
|
||||
class MyMiddleware(object):
|
||||
|
||||
def __init__(self, get_response=None):
|
||||
raise MiddlewareNotUsed
|
||||
|
||||
def process_request(self, request):
|
||||
pass
|
||||
|
||||
|
||||
class MyMiddlewareWithExceptionMessage(object):
|
||||
|
||||
def __init__(self, get_response=None):
|
||||
raise MiddlewareNotUsed('spam eggs')
|
||||
|
||||
def process_request(self, request):
|
||||
pass
|
||||
|
||||
|
||||
@override_settings(
|
||||
DEBUG=True,
|
||||
ROOT_URLCONF='middleware_exceptions.urls',
|
||||
MIDDLEWARE=['django.middleware.common.CommonMiddleware'],
|
||||
)
|
||||
class MiddlewareNotUsedTests(SimpleTestCase):
|
||||
|
||||
rf = RequestFactory()
|
||||
|
||||
def test_raise_exception(self):
|
||||
request = self.rf.get('middleware_exceptions/view/')
|
||||
with self.assertRaises(MiddlewareNotUsed):
|
||||
MyMiddleware().process_request(request)
|
||||
|
||||
@override_settings(MIDDLEWARE=['middleware_exceptions.test_legacy.MyMiddleware'])
|
||||
def test_log(self):
|
||||
with patch_logger('django.request', 'debug') as calls:
|
||||
self.client.get('/middleware_exceptions/view/')
|
||||
self.assertEqual(len(calls), 1)
|
||||
self.assertEqual(
|
||||
calls[0],
|
||||
"MiddlewareNotUsed: 'middleware_exceptions.test_legacy.MyMiddleware'"
|
||||
)
|
||||
|
||||
@override_settings(MIDDLEWARE=['middleware_exceptions.test_legacy.MyMiddlewareWithExceptionMessage'])
|
||||
def test_log_custom_message(self):
|
||||
with patch_logger('django.request', 'debug') as calls:
|
||||
self.client.get('/middleware_exceptions/view/')
|
||||
self.assertEqual(len(calls), 1)
|
||||
self.assertEqual(
|
||||
calls[0],
|
||||
"MiddlewareNotUsed('middleware_exceptions.test_legacy.MyMiddlewareWithExceptionMessage'): spam eggs"
|
||||
)
|
||||
|
||||
@override_settings(DEBUG=False)
|
||||
def test_do_not_log_when_debug_is_false(self):
|
||||
with patch_logger('django.request', 'debug') as calls:
|
||||
self.client.get('/middleware_exceptions/view/')
|
||||
self.assertEqual(len(calls), 0)
|
||||
|
||||
|
||||
@ignore_warnings(category=RemovedInDjango20Warning)
|
||||
@override_settings(
|
||||
|
||||
133
tests/middleware_exceptions/tests.py
Normal file
133
tests/middleware_exceptions/tests.py
Normal file
@@ -0,0 +1,133 @@
|
||||
from django.conf import settings
|
||||
from django.core.exceptions import MiddlewareNotUsed
|
||||
from django.test import RequestFactory, SimpleTestCase, override_settings
|
||||
from django.test.utils import patch_logger
|
||||
|
||||
from . import middleware as mw
|
||||
|
||||
|
||||
@override_settings(ROOT_URLCONF='middleware_exceptions.urls')
|
||||
class MiddlewareTests(SimpleTestCase):
|
||||
def tearDown(self):
|
||||
mw.log = []
|
||||
|
||||
@override_settings(MIDDLEWARE=['middleware_exceptions.middleware.ProcessViewNoneMiddleware'])
|
||||
def test_process_view_return_none(self):
|
||||
response = self.client.get('/middleware_exceptions/view/')
|
||||
self.assertEqual(mw.log, ['processed view normal_view'])
|
||||
self.assertEqual(response.content, b'OK')
|
||||
|
||||
@override_settings(MIDDLEWARE=['middleware_exceptions.middleware.ProcessViewMiddleware'])
|
||||
def test_process_view_return_response(self):
|
||||
response = self.client.get('/middleware_exceptions/view/')
|
||||
self.assertEqual(response.content, b'Processed view normal_view')
|
||||
|
||||
@override_settings(MIDDLEWARE=['middleware_exceptions.middleware.TemplateResponseMiddleware'])
|
||||
def test_process_template_response(self):
|
||||
response = self.client.get('/middleware_exceptions/template_response/')
|
||||
self.assertEqual(response.content, b'template-response middleware')
|
||||
|
||||
@override_settings(MIDDLEWARE=['middleware_exceptions.middleware.LogMiddleware'])
|
||||
def test_view_exception_converted_before_middleware(self):
|
||||
response = self.client.get('/middleware_exceptions/permission_denied/')
|
||||
self.assertEqual(mw.log, [(response.status_code, response.content)])
|
||||
self.assertEqual(response.status_code, 403)
|
||||
|
||||
@override_settings(MIDDLEWARE=['middleware_exceptions.middleware.ProcessExceptionMiddleware'])
|
||||
def test_view_exception_handled_by_process_exception(self):
|
||||
response = self.client.get('/middleware_exceptions/error/')
|
||||
self.assertEqual(response.content, b'Exception caught')
|
||||
|
||||
@override_settings(MIDDLEWARE=[
|
||||
'middleware_exceptions.middleware.ProcessExceptionLogMiddleware',
|
||||
'middleware_exceptions.middleware.ProcessExceptionMiddleware',
|
||||
])
|
||||
def test_response_from_process_exception_short_circuits_remainder(self):
|
||||
response = self.client.get('/middleware_exceptions/error/')
|
||||
self.assertEqual(mw.log, [])
|
||||
self.assertEqual(response.content, b'Exception caught')
|
||||
|
||||
@override_settings(MIDDLEWARE=[
|
||||
'middleware_exceptions.middleware.LogMiddleware',
|
||||
'middleware_exceptions.middleware.NotFoundMiddleware',
|
||||
])
|
||||
def test_exception_in_middleware_converted_before_prior_middleware(self):
|
||||
response = self.client.get('/middleware_exceptions/view/')
|
||||
self.assertEqual(mw.log, [(404, response.content)])
|
||||
self.assertEqual(response.status_code, 404)
|
||||
|
||||
@override_settings(MIDDLEWARE=['middleware_exceptions.middleware.ProcessExceptionMiddleware'])
|
||||
def test_exception_in_render_passed_to_process_exception(self):
|
||||
response = self.client.get('/middleware_exceptions/exception_in_render/')
|
||||
self.assertEqual(response.content, b'Exception caught')
|
||||
|
||||
|
||||
@override_settings(ROOT_URLCONF='middleware_exceptions.urls')
|
||||
class RootUrlconfTests(SimpleTestCase):
|
||||
|
||||
@override_settings(ROOT_URLCONF=None)
|
||||
def test_missing_root_urlconf(self):
|
||||
# Removing ROOT_URLCONF is safe, as override_settings will restore
|
||||
# the previously defined settings.
|
||||
del settings.ROOT_URLCONF
|
||||
with self.assertRaises(AttributeError):
|
||||
self.client.get("/middleware_exceptions/view/")
|
||||
|
||||
|
||||
class MyMiddleware(object):
|
||||
|
||||
def __init__(self, get_response=None):
|
||||
raise MiddlewareNotUsed
|
||||
|
||||
def process_request(self, request):
|
||||
pass
|
||||
|
||||
|
||||
class MyMiddlewareWithExceptionMessage(object):
|
||||
|
||||
def __init__(self, get_response=None):
|
||||
raise MiddlewareNotUsed('spam eggs')
|
||||
|
||||
def process_request(self, request):
|
||||
pass
|
||||
|
||||
|
||||
@override_settings(
|
||||
DEBUG=True,
|
||||
ROOT_URLCONF='middleware_exceptions.urls',
|
||||
MIDDLEWARE=['django.middleware.common.CommonMiddleware'],
|
||||
)
|
||||
class MiddlewareNotUsedTests(SimpleTestCase):
|
||||
|
||||
rf = RequestFactory()
|
||||
|
||||
def test_raise_exception(self):
|
||||
request = self.rf.get('middleware_exceptions/view/')
|
||||
with self.assertRaises(MiddlewareNotUsed):
|
||||
MyMiddleware().process_request(request)
|
||||
|
||||
@override_settings(MIDDLEWARE=['middleware_exceptions.tests.MyMiddleware'])
|
||||
def test_log(self):
|
||||
with patch_logger('django.request', 'debug') as calls:
|
||||
self.client.get('/middleware_exceptions/view/')
|
||||
self.assertEqual(len(calls), 1)
|
||||
self.assertEqual(
|
||||
calls[0],
|
||||
"MiddlewareNotUsed: 'middleware_exceptions.tests.MyMiddleware'"
|
||||
)
|
||||
|
||||
@override_settings(MIDDLEWARE=['middleware_exceptions.tests.MyMiddlewareWithExceptionMessage'])
|
||||
def test_log_custom_message(self):
|
||||
with patch_logger('django.request', 'debug') as calls:
|
||||
self.client.get('/middleware_exceptions/view/')
|
||||
self.assertEqual(len(calls), 1)
|
||||
self.assertEqual(
|
||||
calls[0],
|
||||
"MiddlewareNotUsed('middleware_exceptions.tests.MyMiddlewareWithExceptionMessage'): spam eggs"
|
||||
)
|
||||
|
||||
@override_settings(DEBUG=False)
|
||||
def test_do_not_log_when_debug_is_false(self):
|
||||
with patch_logger('django.request', 'debug') as calls:
|
||||
self.client.get('/middleware_exceptions/view/')
|
||||
self.assertEqual(len(calls), 0)
|
||||
Reference in New Issue
Block a user