Django

Code

Changeset 9184

Show
Ignore:
Timestamp:
10/07/08 03:22:50 (2 months ago)
Author:
mtredinnick
Message:

Fixed #9199 -- We were erroneously only prepending "www" to the domain if we
also needed to append a slash (when PREPEND_WWW=True).

Based on a patch and tests from gonz. Thanks.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • django/trunk/django/middleware/common.py

    r8635 r9184  
    5454        # trailing slash and there is no pattern for the current path 
    5555        if settings.APPEND_SLASH and (not old_url[1].endswith('/')): 
    56             try: 
    57                 urlresolvers.resolve(request.path_info) 
    58             except urlresolvers.Resolver404: 
     56            if (not _is_valid_path(request.path_info) and 
     57                    _is_valid_path("%s/" % request.path_info)): 
    5958                new_url[1] = new_url[1] + '/' 
    6059                if settings.DEBUG and request.method == 'POST': 
     
    6766                    "settings.") % (new_url[0], new_url[1]) 
    6867 
    69         if new_url != old_url: 
    70             # Redirect if the target url exists 
    71             try: 
    72                 urlresolvers.resolve("%s/" % request.path_info) 
    73             except urlresolvers.Resolver404: 
    74                 pass 
    75             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.META['QUERY_STRING'] 
    84                 return http.HttpResponsePermanentRedirect(newurl) 
    85  
    86         return None 
     68        if new_url == old_url: 
     69            # No redirects required. 
     70            return 
     71        if new_url[0]: 
     72            newurl = "%s://%s%s" % ( 
     73                request.is_secure() and 'https' or 'http', 
     74                new_url[0], urlquote(new_url[1])) 
     75        else: 
     76            newurl = urlquote(new_url[1]) 
     77        if request.GET: 
     78            newurl += '?' + request.META['QUERY_STRING'] 
     79        return http.HttpResponsePermanentRedirect(newurl) 
    8780 
    8881    def process_response(self, request, response): 
     
    120113 
    121114def _is_ignorable_404(uri): 
    122     "Returns True if a 404 at the given URL *shouldn't* notify the site managers" 
     115    """ 
     116    Returns True if a 404 at the given URL *shouldn't* notify the site managers. 
     117    """ 
    123118    for start in settings.IGNORABLE_404_STARTS: 
    124119        if uri.startswith(start): 
     
    130125 
    131126def _is_internal_request(domain, referer): 
    132     "Return true if the referring URL is the same domain as the current request" 
     127    """ 
     128    Returns true if the referring URL is the same domain as the current request. 
     129    """ 
    133130    # Different subdomains are treated as different domains. 
    134131    return referer is not None and re.match("^https?://%s/" % re.escape(domain), referer) 
     132 
     133def _is_valid_path(path): 
     134    """ 
     135    Returns True if the given path resolves against the default URL resolver, 
     136    False otherwise. 
     137 
     138    This is a convenience method to make working with "is this a match?" cases 
     139    easier, avoiding unnecessarily indented try...except blocks. 
     140    """ 
     141    try: 
     142        urlresolvers.resolve(path) 
     143        return True 
     144    except urlresolvers.Resolver404: 
     145        return False 
     146 
  • django/trunk/tests/regressiontests/middleware/tests.py

    r8456 r9184  
    9090            r['Location'], 
    9191            'http://testserver/middleware/needsquoting%23/') 
     92 
     93    def test_prepend_www(self): 
     94        settings.PREPEND_WWW = True 
     95        settings.APPEND_SLASH = False 
     96        request = self._get_request('path/') 
     97        r = CommonMiddleware().process_request(request) 
     98        self.assertEquals(r.status_code, 301) 
     99        self.assertEquals( 
     100            r['Location'], 
     101            'http://www.testserver/middleware/path/') 
     102 
     103    def test_prepend_www_append_slash_have_slash(self): 
     104        settings.PREPEND_WWW = True 
     105        settings.APPEND_SLASH = True 
     106        request = self._get_request('slash/') 
     107        r = CommonMiddleware().process_request(request) 
     108        self.assertEquals(r.status_code, 301) 
     109        self.assertEquals(r['Location'], 
     110                          'http://www.testserver/middleware/slash/') 
     111 
     112    def test_prepend_www_append_slash_slashless(self): 
     113        settings.PREPEND_WWW = True 
     114        settings.APPEND_SLASH = True 
     115        request = self._get_request('slash') 
     116        r = CommonMiddleware().process_request(request) 
     117        self.assertEquals(r.status_code, 301) 
     118        self.assertEquals(r['Location'], 
     119                          'http://www.testserver/middleware/slash/')