Ticket #6213: common_middleware.3.py.diff
File common_middleware.3.py.diff, 9.1 KB (added by , 16 years ago) |
---|
-
django/middleware/common.py
40 40 if user_agent_regex.search(request.META['HTTP_USER_AGENT']): 41 41 return http.HttpResponseForbidden('<h1>Forbidden</h1>') 42 42 43 # Check for a redirect based on settings.APPEND_SLASH 44 # and settings.PREPEND_WWW 45 host = request.get_host() 46 old_url = [host, request.path] 47 new_url = old_url[:] 43 _response = _handle_redirects(request) 44 if _response: 45 return _response 48 46 49 if (settings.PREPEND_WWW and old_url[0] and50 not old_url[0].startswith('www.')):51 new_url[0] = 'www.' + old_url[0]52 53 # Append a slash if APPEND_SLASH is set and the URL doesn't have a54 # trailing slash and there is no pattern for the current path55 if settings.APPEND_SLASH and (not old_url[1].endswith('/')):56 try:57 urlresolvers.resolve(request.path)58 except urlresolvers.Resolver404:59 new_url[1] = new_url[1] + '/'60 if settings.DEBUG and request.method == 'POST':61 raise RuntimeError, (""62 "You called this URL via POST, but the URL doesn't end "63 "in a slash and you have APPEND_SLASH set. Django can't "64 "redirect to the slash URL while maintaining POST data. "65 "Change your form to point to %s%s (note the trailing "66 "slash), or set APPEND_SLASH=False in your Django "67 "settings.") % (new_url[0], new_url[1])68 69 if new_url != old_url:70 # Redirect if the target url exists71 try:72 urlresolvers.resolve(new_url[1])73 except urlresolvers.Resolver404:74 pass75 else:76 if new_url[0]:77 newurl = "%s://%s%s" % (78 request.is_secure() and 'https' or 'http',79 new_url[0], urlquote(new_url[1]))80 else:81 newurl = urlquote(new_url[1])82 if request.GET:83 newurl += '?' + request.GET.urlencode()84 return http.HttpResponsePermanentRedirect(newurl)85 86 47 return None 87 48 88 49 def process_response(self, request, response): 89 50 "Check for a flat page (for 404s) and calculate the Etag, if needed." 90 51 if response.status_code == 404: 52 _response = _handle_redirects(request, resolve=False) 53 if _response: 54 return _response 91 55 if settings.SEND_BROKEN_LINK_EMAILS: 92 56 # If the referrer was from an internal link or a non-search-engine site, 93 57 # send a note to the managers. … … 118 82 119 83 return response 120 84 85 def _handle_redirects(request, resolve=True): 86 host = request.get_host() 87 old_url = [host, request.path] 88 new_url = old_url[:] 89 90 if (settings.PREPEND_WWW and old_url[0] and 91 not old_url[0].startswith('www.')): 92 new_url[0] = 'www.' + old_url[0] 93 94 # Append a slash if APPEND_SLASH is set and the URL doesn't have a 95 # trailing slash and there is no pattern for the current path 96 if settings.APPEND_SLASH and (not old_url[1].endswith('/')): 97 if resolve: 98 try: 99 urlresolvers.resolve(request.path) 100 except urlresolvers.Resolver404: 101 new_url[1] = new_url[1] + '/' 102 else: 103 new_url[1] = new_url[1] + '/' 104 105 if new_url != old_url: 106 # Redirect if the target url exists 107 try: 108 if resolve and new_url[0] == new_url[0] and new_url[1] != old_url[1]: 109 urlresolvers.resolve(new_url[1]) 110 except urlresolvers.Resolver404: 111 pass 112 else: 113 if new_url[0]: 114 newurl = "%s://%s%s" % ( 115 request.is_secure() and 'https' or 'http', 116 new_url[0], urlquote(new_url[1])) 117 else: 118 newurl = urlquote(new_url[1]) 119 if request.GET: 120 newurl += '?' + request.GET.urlencode() 121 if settings.DEBUG and request.method == 'POST': 122 raise RuntimeError, ("" 123 "You called this URL via POST, but the URL doesn't end " 124 "in a slash and you have APPEND_SLASH set. Django can't " 125 "redirect to the slash URL while maintaining POST data. " 126 "Change your form to point to %s%s (note the trailing " 127 "slash), or set APPEND_SLASH=False in your Django " 128 "settings.") % (new_url[0], new_url[1]) 129 return http.HttpResponsePermanentRedirect(newurl) 130 121 131 def _is_ignorable_404(uri): 122 132 "Returns True if a 404 at the given URL *shouldn't* notify the site managers" 123 133 for start in settings.IGNORABLE_404_STARTS: -
tests/regressiontests/middleware/tests.py
1 1 # -*- coding: utf-8 -*- 2 2 3 3 from django.test import TestCase 4 from django.http import HttpRequest 4 from django.http import HttpRequest, HttpResponse, HttpResponseNotFound 5 5 from django.middleware.common import CommonMiddleware 6 6 from django.conf import settings 7 7 … … 89 89 self.assertEquals( 90 90 r['Location'], 91 91 'http://testserver/middleware/needsquoting%23/') 92 93 def test_append_slash_enabled_custom_middleware_slash(self): 94 """ 95 Tests that if APPEND_SLASH is True and some intermediate middleware 96 (e.g. FlatpageFallbackMiddleware) has processed the request and 97 returned a 404 response, then this is redirected. 98 """ 99 settings.APPEND_SLASH = True 100 request = self._get_request('custom/slash') 101 common_middleware = CommonMiddleware() 102 custom_middleware = CustomMiddleware() 103 response = common_middleware.process_request(request) 104 self.assertEquals(response, None) 105 response = custom_middleware.process_request(request) 106 self.assertEquals(response.status_code, 404) 107 response = custom_middleware.process_response(request, response) 108 self.assertEquals(response.status_code, 404) 109 response = common_middleware.process_response(request, response) 110 self.assertEquals(response.status_code, 301) 111 self.assertEquals( 112 response['Location'], 113 'http://testserver/middleware/custom/slash/') 114 115 def test_append_slash_disabled_custom_middleware_slash(self): 116 """ 117 Tests that if APPEND_SLASH is False and some intermediate middleware 118 (e.g. FlatpageFallbackMiddleware) has processed the request and 119 returned a 404 response, then this is not redirected. 120 """ 121 settings.APPEND_SLASH = False 122 request = self._get_request('custom/slash') 123 common_middleware = CommonMiddleware() 124 custom_middleware = CustomMiddleware() 125 response = common_middleware.process_request(request) 126 self.assertEquals(response, None) 127 response = custom_middleware.process_request(request) 128 self.assertEquals(response.status_code, 404) 129 response = custom_middleware.process_response(request, response) 130 self.assertEquals(response.status_code, 404) 131 response = common_middleware.process_response(request, response) 132 self.assertEquals(response.status_code, 404) 133 134 def test_append_slash_custom_middleware_slashless(self): 135 """ 136 Tests that whether APPEND_SLASH is True or not, and some intermediate 137 middleware (e.g. FlatpageFallbackMiddleware) has processed the request 138 and returned a response, this is not redirected. 139 """ 140 for append_slash in (True, False): 141 settings.APPEND_SLASH = append_slash 142 request = self._get_request('custom/noslash') 143 common_middleware = CommonMiddleware() 144 custom_middleware = CustomMiddleware() 145 response = common_middleware.process_request(request) 146 self.assertEquals(response, None) 147 response = custom_middleware.process_request(request) 148 self.assertContains(response, 'Custom middleware response') 149 response = custom_middleware.process_response(request, response) 150 self.assertContains(response, 'Custom middleware response') 151 response = common_middleware.process_response(request, response) 152 self.assertContains(response, 'Custom middleware response') 153 154 class CustomMiddleware(object): 155 def process_request(self, request): 156 if request.path in ('/middleware/custom/slash/', '/middleware/custom/noslash'): 157 return HttpResponse('Custom middleware response') 158 return HttpResponseNotFound() 159 def process_response(self, request, response): 160 return response