Ticket #6213: common_middleware.2.py.diff
File common_middleware.2.py.diff, 8.9 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 some intermediate middleware (e.g. 96 FlatpageFallbackMiddleware) has processed the request and returned a 97 response, this is not 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 if response is None: 105 response = custom_middleware.process_request(request) 106 response = custom_middleware.process_response(request, response) 107 response = common_middleware.process_response(request, response) 108 self.assertEquals(response.status_code, 301) 109 self.assertEquals( 110 response['Location'], 111 'http://testserver/middleware/custom/slash/') 112 113 def test_append_slash_disabled_custom_middleware_slash(self): 114 """ 115 Tests that if some intermediate middleware (e.g. 116 FlatpageFallbackMiddleware) has processed the request and returned a 117 response, this is not redirected. 118 """ 119 settings.APPEND_SLASH = False 120 request = self._get_request('custom/slash') 121 common_middleware = CommonMiddleware() 122 custom_middleware = CustomMiddleware() 123 response = common_middleware.process_request(request) 124 self.assertEquals(response, None) 125 response = custom_middleware.process_request(request) 126 self.assertEquals(response.status_code, 404) 127 response = custom_middleware.process_response(request, response) 128 self.assertEquals(response.status_code, 404) 129 response = common_middleware.process_response(request, response) 130 self.assertEquals(response.status_code, 404) 131 132 def test_append_slash_custom_middleware_slashless(self): 133 """ 134 Tests that if some intermediate middleware (e.g. 135 FlatpageFallbackMiddleware) has processed the request and returned a 136 response, this is not redirected. 137 """ 138 for append_slash in (True, False): 139 settings.APPEND_SLASH = append_slash 140 request = self._get_request('custom/noslash') 141 common_middleware = CommonMiddleware() 142 custom_middleware = CustomMiddleware() 143 response = common_middleware.process_request(request) 144 self.assertEquals(response, None) 145 response = custom_middleware.process_request(request) 146 self.assertContains(response, 'Custom middleware response') 147 response = custom_middleware.process_response(request, response) 148 self.assertContains(response, 'Custom middleware response') 149 response = common_middleware.process_response(request, response) 150 self.assertContains(response, 'Custom middleware response') 151 152 class CustomMiddleware(object): 153 def process_request(self, request): 154 if request.path in ('/middleware/custom/slash/', '/middleware/custom/noslash'): 155 return HttpResponse('Custom middleware response') 156 return HttpResponseNotFound() 157 def process_response(self, request, response): 158 return response