diff --git a/django/middleware/common.py b/django/middleware/common.py index c719f9e9a33..0bf0481df61 100644 --- a/django/middleware/common.py +++ b/django/middleware/common.py @@ -30,11 +30,16 @@ class CommonMiddleware(object): urlpatterns, then an HTTP-redirect is returned to this new URL; otherwise the initial URL is processed as usual. + This behavior can be customized by subclassing CommonMiddleware and + overriding the response_redirect_class attribute. + - ETags: If the USE_ETAGS setting is set, ETags will be calculated from the entire page content and Not Modified responses will be returned appropriately. """ + response_redirect_class = http.HttpResponsePermanentRedirect + def process_request(self, request): """ Check for denied User-Agents and rewrite the URL based on @@ -100,7 +105,7 @@ class CommonMiddleware(object): newurl += '?' + request.META['QUERY_STRING'].decode() except UnicodeDecodeError: pass - return http.HttpResponsePermanentRedirect(newurl) + return self.response_redirect_class(newurl) def process_response(self, request, response): """ diff --git a/docs/ref/middleware.txt b/docs/ref/middleware.txt index 3ba7d52b9d3..8f3f3094e92 100644 --- a/docs/ref/middleware.txt +++ b/docs/ref/middleware.txt @@ -66,6 +66,14 @@ Adds a few conveniences for perfectionists: for each request by MD5-hashing the page content, and it'll take care of sending ``Not Modified`` responses, if appropriate. +.. attribute:: CommonMiddleware.response_redirect_class + +.. versionadded:: 1.8 + +Defaults to :class:`~django.http.HttpResponsePermanentRedirect`. Subclass +``CommonMiddleware`` and override the attribute to customize the redirects +issued by the middleware. + .. class:: BrokenLinkEmailsMiddleware * Sends broken link notification emails to :setting:`MANAGERS` (see diff --git a/docs/releases/1.8.txt b/docs/releases/1.8.txt index d5bae559a71..e1bca107df2 100644 --- a/docs/releases/1.8.txt +++ b/docs/releases/1.8.txt @@ -304,6 +304,13 @@ Management Commands :setting:`FIXTURE_DIRS` contains duplicates or a default fixture directory path (``app_name/fixtures``), an exception is raised. +Middleware +^^^^^^^^^^ + +* The :attr:`CommonMiddleware.response_redirect_class + ` + attribute allows you to customize the redirects issued by the middleware. + Migrations ^^^^^^^^^^ diff --git a/tests/middleware/tests.py b/tests/middleware/tests.py index ec7f7633ba6..f0a89d719ac 100644 --- a/tests/middleware/tests.py +++ b/tests/middleware/tests.py @@ -9,7 +9,10 @@ from unittest import skipIf from django.conf import settings from django.core import mail -from django.http import HttpRequest, HttpResponse, StreamingHttpResponse +from django.http import ( + HttpRequest, HttpResponse, StreamingHttpResponse, HttpResponsePermanentRedirect, + HttpResponseRedirect, +) from django.middleware.clickjacking import XFrameOptionsMiddleware from django.middleware.common import CommonMiddleware, BrokenLinkEmailsMiddleware from django.middleware.http import ConditionalGetMiddleware @@ -242,6 +245,23 @@ class CommonMiddlewareTest(TestCase): response = CommonMiddleware().process_request(request) self.assertEqual(response.status_code, 301) + def test_response_redirect_class(self): + request = self._get_request('slash') + r = CommonMiddleware().process_request(request) + self.assertEqual(r.status_code, 301) + self.assertEqual(r.url, 'http://testserver/slash/') + self.assertIsInstance(r, HttpResponsePermanentRedirect) + + def test_response_redirect_class_subclass(self): + class MyCommonMiddleware(CommonMiddleware): + response_redirect_class = HttpResponseRedirect + + request = self._get_request('slash') + r = MyCommonMiddleware().process_request(request) + self.assertEqual(r.status_code, 302) + self.assertEqual(r.url, 'http://testserver/slash/') + self.assertIsInstance(r, HttpResponseRedirect) + @override_settings( IGNORABLE_404_URLS=(re.compile(r'foo'),),