Ticket #3228: smartslash-2.diff
File smartslash-2.diff, 7.6 KB (added by , 17 years ago) |
---|
-
django/middleware/common.py
1 1 from django.conf import settings 2 2 from django import http 3 3 from django.core.mail import mail_managers 4 from django.core import urlresolvers 4 5 import md5 5 6 import re 6 7 … … 14 15 this middleware appends missing slashes and/or prepends missing 15 16 "www."s. 16 17 18 - If APPEND_SLASH is set and the initial URL doesn't end with a 19 slash, and it is not found in urlpatterns, a new URL is formed by 20 appending a slash at the end. If this new URL is found in 21 urlpatterns, then an HTTP-redirect is returned to this new URL; 22 otherwise the initial URL is processed as usual. 23 17 24 - ETags: If the USE_ETAGS setting is set, ETags will be calculated from 18 25 the entire page content and Not Modified responses will be returned 19 26 appropriately. … … 31 38 if user_agent_regex.search(request.META['HTTP_USER_AGENT']): 32 39 return http.HttpResponseForbidden('<h1>Forbidden</h1>') 33 40 34 # Check for a redirect based on settings.APPEND_SLASH and settings.PREPEND_WWW 41 # Check for a redirect based on settings.APPEND_SLASH 42 # and settings.PREPEND_WWW 35 43 host = http.get_host(request) 36 44 old_url = [host, request.path] 37 45 new_url = old_url[:] 38 if settings.PREPEND_WWW and old_url[0] and not old_url[0].startswith('www.'): 46 47 if (settings.PREPEND_WWW and old_url[0] and 48 not old_url[0].startswith('www.')): 39 49 new_url[0] = 'www.' + old_url[0] 40 # Append a slash if append_slash is set and the URL doesn't have a 41 # trailing slash or a file extension. 42 if settings.APPEND_SLASH and (not old_url[1].endswith('/')) and ('.' not in old_url[1].split('/')[-1]): 43 new_url[1] = new_url[1] + '/' 44 if settings.DEBUG and request.method == 'POST': 45 raise RuntimeError, "You called this URL via POST, but the URL doesn't end in a slash and you have APPEND_SLASH set. Django can't redirect to the slash URL while maintaining POST data. Change your form to point to %s%s (note the trailing slash), or set APPEND_SLASH=False in your Django settings." % (new_url[0], new_url[1]) 50 51 # Append a slash if APPEND_SLASH is set and the URL doesn't have a 52 # trailing slash and there is no pattern for the current path 53 if settings.APPEND_SLASH and (not old_url[1].endswith('/')): 54 try: 55 urlresolvers.resolve(request.path) 56 except urlresolvers.Resolver404: 57 new_url[1] = new_url[1] + '/' 58 if settings.DEBUG and request.method == 'POST': 59 raise RuntimeError, "" 60 "You called this URL via POST, but the URL doesn't end" 61 "in a slash and you have APPEND_SLASH set. Django can't" 62 "redirect to the slash URL while maintaining POST data." 63 "Change your form to point to %s%s (note the trailing" 64 "slash), or set APPEND_SLASH=False in your Django" 65 "settings." % (new_url[0], new_url[1]) 66 46 67 if new_url != old_url: 47 # Redirect 48 if new_url[0]: 49 newurl = "%s://%s%s" % (request.is_secure() and 'https' or 'http', new_url[0], new_url[1]) 68 # Redirect if the target url exists 69 try: 70 urlresolvers.resolve(new_url[1]) 71 except urlresolvers.Resolver404: 72 pass 50 73 else: 51 newurl = new_url[1] 52 if request.GET: 53 newurl += '?' + request.GET.urlencode() 54 return http.HttpResponsePermanentRedirect(newurl) 74 if new_url[0]: 75 newurl = "%s://%s%s" % ( 76 request.is_secure() and 'https' or 'http', 77 new_url[0], new_url[1]) 78 else: 79 newurl = new_url[1] 80 if request.GET: 81 newurl += '?' + request.GET.urlencode() 82 return http.HttpResponsePermanentRedirect(newurl) 55 83 56 84 return None 57 85 -
tests/regressiontests/middleware/tests.py
1 # -*- coding: utf-8 -*- 2 3 import unittest 4 5 from django.http import HttpRequest 6 from django.middleware.common import CommonMiddleware 7 from django.conf import settings 8 9 class CommonMiddlewareTest(unittest.TestCase): 10 def setUp(self): 11 # blow cached urls from previous test cases 12 # django settings and urls are factored pretty badly for unit testing 13 from django.core import urlresolvers 14 keys = urlresolvers._resolver_cache.keys() 15 for key in keys: 16 del urlresolvers._resolver_cache[key] 17 settings.ROOT_URLCONF = 'regressiontests.middleware.urls' 18 19 def test_append_slash_have_slash(self): 20 # test that urls with slashes go unmolested 21 settings.APPEND_SLASH = True 22 request = HttpRequest() 23 request.path = '/slash/' 24 self.assertEquals(CommonMiddleware().process_request(request), None) 25 26 def test_append_slash_slashless_resource(self): 27 # test that matches to explicit slashless urls go unmolested 28 settings.APPEND_SLASH = True 29 request = HttpRequest() 30 request.path = '/noslash' 31 self.assertEquals(CommonMiddleware().process_request(request), None) 32 33 def test_append_slash_slashless_unknown(self): 34 # test that APPEND_SLASH doesn't redirect to unknown resources 35 settings.APPEND_SLASH = True 36 request = HttpRequest() 37 request.path = '/unknown' 38 self.assertEquals(CommonMiddleware().process_request(request), None) 39 40 def test_append_slash_redirect(self): 41 # test that APPEND_SLASH redirects slashless urls to a valid pattern 42 settings.APPEND_SLASH = True 43 request = HttpRequest() 44 request.path = '/slash' 45 r = CommonMiddleware().process_request(request) 46 self.assertEquals(r.status_code, 301) 47 self.assertEquals(r.headers['Location'], '/slash/') 48 49 def test_append_slash_no_redirect_on_POST_in_DEBUG(self): 50 settings.APPEND_SLASH = True 51 settings.DEBUG = True 52 request = HttpRequest() 53 request.path = '/slash' 54 request.method = 'POST' 55 self.assertRaises(RuntimeError, CommonMiddleware().process_request, 56 request) 57 58 def test_append_slash_disabled(self): 59 settings.APPEND_SLASH = False 60 request = HttpRequest() 61 request.path = '/slash' 62 self.assertEquals(CommonMiddleware().process_request(request), None) -
tests/regressiontests/middleware/urls.py
1 from django.conf.urls.defaults import patterns 2 3 urlpatterns = patterns('', 4 (r'^noslash$', 'view'), 5 (r'^slash/$', 'view'), 6 )