Ticket #3228: smartslash-3.1.diff

File smartslash-3.1.diff, 10.2 KB (added by Andy Gayton <andy-django@…>, 16 years ago)

fixed typo in docs/middleware.txt

  • django/middleware/common.py

     
    55from django import http
    66from django.core.mail import mail_managers
    77from django.utils.http import urlquote
     8from django.core import urlresolvers
    89
    910class CommonMiddleware(object):
    1011    """
     
    1617          this middleware appends missing slashes and/or prepends missing
    1718          "www."s.
    1819
     20            - If APPEND_SLASH is set and the initial URL doesn't end with a
     21              slash, and it is not found in urlpatterns, a new URL is formed by
     22              appending a slash at the end. If this new URL is found in
     23              urlpatterns, then an HTTP-redirect is returned to this new URL;
     24              otherwise the initial URL is processed as usual.
     25
    1926        - ETags: If the USE_ETAGS setting is set, ETags will be calculated from
    2027          the entire page content and Not Modified responses will be returned
    2128          appropriately.
     
    3340                if user_agent_regex.search(request.META['HTTP_USER_AGENT']):
    3441                    return http.HttpResponseForbidden('<h1>Forbidden</h1>')
    3542
    36         # Check for a redirect based on settings.APPEND_SLASH and settings.PREPEND_WWW
     43        # Check for a redirect based on settings.APPEND_SLASH
     44        # and settings.PREPEND_WWW
    3745        host = request.get_host()
    3846        old_url = [host, request.path]
    3947        new_url = old_url[:]
    40         if settings.PREPEND_WWW and old_url[0] and not old_url[0].startswith('www.'):
     48
     49        if (settings.PREPEND_WWW and old_url[0] and
     50                not old_url[0].startswith('www.')):
    4151            new_url[0] = 'www.' + old_url[0]
    42         # Append a slash if append_slash is set and the URL doesn't have a
    43         # trailing slash or a file extension.
    44         if settings.APPEND_SLASH and (not old_url[1].endswith('/')) and ('.' not in old_url[1].split('/')[-1]):
    45             new_url[1] = new_url[1] + '/'
    46             if settings.DEBUG and request.method == 'POST':
    47                 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])
     52
     53        # Append a slash if APPEND_SLASH is set and the URL doesn't have a
     54        # trailing slash and there is no pattern for the current path
     55        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
    4869        if new_url != old_url:
    49             # Redirect
    50             if new_url[0]:
    51                 newurl = "%s://%s%s" % (request.is_secure() and 'https' or 'http', new_url[0], urlquote(new_url[1]))
     70            # Redirect if the target url exists
     71            try:
     72                urlresolvers.resolve(new_url[1])
     73            except urlresolvers.Resolver404:
     74                pass
    5275            else:
    53                 newurl = urlquote(new_url[1])
    54             if request.GET:
    55                 newurl += '?' + request.GET.urlencode()
    56             return http.HttpResponsePermanentRedirect(newurl)
     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)
    5785
    5886        return None
    5987
  • tests/regressiontests/middleware/tests.py

     
     1# -*- coding: utf-8 -*-
     2
     3import unittest
     4
     5from django.test import TestCase
     6from django.http import HttpRequest
     7from django.middleware.common import CommonMiddleware
     8from django.conf import settings
     9
     10class CommonMiddlewareTest(TestCase):
     11    def _get_request(self, path):
     12        request = HttpRequest()
     13        request.META = {
     14            'SERVER_NAME': 'testserver',
     15            'SERVER_PORT': 80,
     16        }
     17        request.path = "/middleware/%s" % path
     18        return request
     19
     20    def test_append_slash_have_slash(self):
     21        """
     22        tests that urls with slashes go unmolested
     23        """
     24        settings.APPEND_SLASH = True
     25        request = self._get_request('slash/')
     26        self.assertEquals(CommonMiddleware().process_request(request), None)
     27
     28    def test_append_slash_slashless_resource(self):
     29        """
     30        tests that matches to explicit slashless urls go unmolested
     31        """
     32        settings.APPEND_SLASH = True
     33        request = self._get_request('noslash')
     34        self.assertEquals(CommonMiddleware().process_request(request), None)
     35
     36    def test_append_slash_slashless_unknown(self):
     37        """
     38        tests that APPEND_SLASH doesn't redirect to unknown resources
     39        """
     40        settings.APPEND_SLASH = True
     41        request = self._get_request('unknown')
     42        self.assertEquals(CommonMiddleware().process_request(request), None)
     43
     44    def test_append_slash_redirect(self):
     45        """
     46        tests that APPEND_SLASH redirects slashless urls to a valid pattern
     47        """
     48        settings.APPEND_SLASH = True
     49        request = self._get_request('slash')
     50        r = CommonMiddleware().process_request(request)
     51        self.assertEquals(r.status_code, 301)
     52        self.assertEquals(r['Location'], 'http://testserver/middleware/slash/')
     53
     54    def test_append_slash_no_redirect_on_POST_in_DEBUG(self):
     55        """
     56        tests that while in debug mode, an exception is raised with a warning
     57        when a failed attempt is made to POST to an url which would normally be
     58        redirected to a slashed version
     59        """
     60        settings.APPEND_SLASH = True
     61        settings.DEBUG = True
     62        request = self._get_request('slash')
     63        request.method = 'POST'
     64        self.assertRaises(
     65            RuntimeError,
     66            CommonMiddleware().process_request,
     67            request)
     68        try:
     69            CommonMiddleware().process_request(request)
     70        except RuntimeError, e:
     71            self.assertTrue('end in a slash' in str(e))
     72
     73    def test_append_slash_disabled(self):
     74        """
     75        tests disabling append slash functionality
     76        """
     77        settings.APPEND_SLASH = False
     78        request = self._get_request('slash')
     79        self.assertEquals(CommonMiddleware().process_request(request), None)
     80
     81    def test_append_slash_quoted(self):
     82        """
     83        tests that urls which require quoting are redirected to their slash
     84        version ok
     85        """
     86        settings.APPEND_SLASH = True
     87        request = self._get_request('needsquoting#')
     88        r = CommonMiddleware().process_request(request)
     89        self.assertEquals(r.status_code, 301)
     90        self.assertEquals(
     91            r['Location'],
     92            'http://testserver/middleware/needsquoting%23/')
     93
  • tests/regressiontests/middleware/urls.py

     
     1from django.conf.urls.defaults import patterns
     2
     3urlpatterns = patterns('',
     4    (r'^noslash$', 'view'),
     5    (r'^slash/$', 'view'),
     6    (r'^needsquoting#/$', 'view'),
     7)
  • tests/urls.py

     
    1414   
    1515    # django built-in views
    1616    (r'^views/', include('regressiontests.views.urls')),
     17
     18    # test urlconf for middleware tests
     19    (r'^middleware/', include('regressiontests.middleware.urls')),
    1720)
  • docs/middleware.txt

     
    5858  which should be a list of strings.
    5959
    6060* Performs URL rewriting based on the ``APPEND_SLASH`` and ``PREPEND_WWW``
    61   settings. If ``APPEND_SLASH`` is ``True``, URLs that lack a trailing
    62   slash will be redirected to the same URL with a trailing slash, unless the
    63   last component in the path contains a period. So ``foo.com/bar`` is
    64   redirected to ``foo.com/bar/``, but ``foo.com/bar/file.txt`` is passed
    65   through unchanged.
     61  settings.
    6662
     63  **New in Django development version:** If ``APPEND_SLASH`` is ``True`` and
     64  the initial URL doesn't end with a slash, and it is not found in urlpatterns,
     65  a new URL is formed by appending a slash at the end. If this new URL is found
     66  in urlpatterns, then an HTTP-redirect is returned to this new URL; otherwise
     67  the initial URL is processed as usual.
     68
     69  So ``foo.com/bar`` will be redirected to ``foo.com/bar/`` if you do not
     70  have a valid urlpattern for ``foo.com/bar``, and do have a valid urlpattern
     71  for ``foo.com/bar/``.
     72 
    6773  If ``PREPEND_WWW`` is ``True``, URLs that lack a leading "www." will be
    6874  redirected to the same URL with a leading "www."
    6975
Back to Top