Download Install Tutorial Docs FAQ Tools WikiLicense Team IRC Planet Involvement Shop Book

Changeset 1369

Show
Ignore:
Timestamp:
09/16/06 15:08:31
Author:
fumanchu
Message:

Fix for #562 (Redirect for slash doesn't use tools.proxy.base). Moved slash checking into new tools.trailing_slash(missing=True, extra=False), which is on by default. The core now sets request.is_index to allow such tools to work. In addition, if that tool is off, mismatched slashes will be corrected in cherrypy.url.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/cherrypy/__init__.py

    r1368 r1369  
    172172     
    173173    if request.app: 
    174         if path == "": 
    175             path = request.path_info 
    176         if not path.startswith("/"): 
    177             path = _urljoin(request.path_info, path) 
     174        if path[:1] != "/": 
     175            # Append/remove trailing slash from path_info as needed 
     176            # (this is to support mistyped URL's without redirecting; 
     177            # if you want to redirect, use tools.trailing_slash). 
     178            pi = request.path_info 
     179            if request.is_index is True: 
     180                if pi[-1:] != '/': 
     181                    pi = pi + '/' 
     182            elif request.is_index is False: 
     183                if pi[-1:] == '/' and pi != '/': 
     184                    pi = pi[:-1] 
     185             
     186            if path == "": 
     187                path = pi 
     188            else: 
     189                path = _urljoin(pi, path) 
     190         
    178191        if script_name is None: 
    179192            script_name = request.app.script_name 
  • trunk/cherrypy/_cpconfig.py

    r1336 r1369  
    121121        'tools.log_tracebacks.on': True, 
    122122        'tools.log_headers.on': True, 
     123        'tools.trailing_slash.on': True, 
    123124        } 
    124125     
  • trunk/cherrypy/_cprequest.py

    r1362 r1369  
    201201                    object_trail.insert(i+1, ("default", defhandler, conf, curpath)) 
    202202                    request.config = set_conf() 
     203                    request.is_index = False 
    203204                    return defhandler, names[i:-1] 
    204205             
     
    210211                request.config = set_conf() 
    211212                if i == num_candidates: 
    212                     # We found the extra ".index". Check that path_info 
    213                     # has a trailing slash (otherwise, do a redirect)
    214                     self.check_missing_slash() 
     213                    # We found the extra ".index". Mark request so tools 
     214                    # can redirect if path_info has no trailing slash
     215                    request.is_index = True 
    215216                else: 
    216                     # We're not at an 'index' handler. Check that path_info 
    217                     # had NO trailing slash (if it did, do a redirect). 
    218                     self.check_extra_slash() 
     217                    # We're not at an 'index' handler. Mark request so tools 
     218                    # can redirect if path_info has NO trailing slash. 
     219                    # Note that this also includes handlers which take 
     220                    # positional parameters (virtual paths). 
     221                    request.is_index = False 
    219222                return candidate, names[i:-1] 
    220223         
     
    222225        request.config = set_conf() 
    223226        return None, [] 
    224      
    225     def check_missing_slash(self): 
    226         """Redirect if path_info has no trailing slash (if configured).""" 
    227         request = cherrypy.request 
    228         pi = request.path_info 
    229          
    230         # Must use config here because configure probably hasn't run yet. 
    231         if request.config.get("request.redirect_on_missing_slash", 
    232                               request.redirect_on_missing_slash): 
    233             if pi[-1:] != '/': 
    234                 new_url = cherrypy.url(pi + '/', request.query_string) 
    235                 raise cherrypy.HTTPRedirect(new_url) 
    236      
    237     def check_extra_slash(self): 
    238         """Redirect if path_info has trailing slash (if configured).""" 
    239         request = cherrypy.request 
    240         pi = request.path_info 
    241          
    242         # Must use config here because configure hasn't run yet. 
    243         if request.config.get("request.redirect_on_extra_slash", 
    244                               request.redirect_on_extra_slash): 
    245             # If pi == '/', don't redirect to ''! 
    246             if pi[-1:] == '/' and pi != '/': 
    247                 new_url = cherrypy.url(pi[:-1], request.query_string) 
    248                 raise cherrypy.HTTPRedirect(new_url) 
    249227 
    250228 
     
    357335    config = None 
    358336    recursive_redirect = False 
    359     redirect_on_extra_slash = False 
    360     redirect_on_missing_slash = True 
     337    is_index = None 
    361338     
    362339    hookpoints = ['on_start_resource', 'before_request_body', 
  • trunk/cherrypy/_cptools.py

    r1352 r1369  
    319319default_toolbox.basicauth = Tool('on_start_resource', auth.basic_auth) 
    320320default_toolbox.digestauth = Tool('on_start_resource', auth.digest_auth) 
    321  
     321default_toolbox.trailing_slash = Tool('before_handler', cptools.trailing_slash) 
    322322 
    323323del cptools, encoding, auth, static, tidy 
  • trunk/cherrypy/lib/cptools.py

    r1350 r1369  
    308308    else: 
    309309        raise cherrypy.HTTPRedirect(url) 
     310 
     311def trailing_slash(missing=True, extra=False): 
     312    """Redirect if path_info has (missing|extra) trailing slash.""" 
     313    request = cherrypy.request 
     314    pi = request.path_info 
     315     
     316    if request.is_index is True: 
     317        if missing: 
     318            if pi[-1:] != '/': 
     319                new_url = cherrypy.url(pi + '/', request.query_string) 
     320                raise cherrypy.HTTPRedirect(new_url) 
     321    elif request.is_index is False: 
     322        if extra: 
     323            # If pi == '/', don't redirect to ''! 
     324            if pi[-1:] == '/' and pi != '/': 
     325                new_url = cherrypy.url(pi[:-1], request.query_string) 
     326                raise cherrypy.HTTPRedirect(new_url) 
     327 
  • trunk/cherrypy/test/test_core.py

    r1368 r1369  
    7070    class URL(Test): 
    7171         
     72        _cp_config = {'tools.trailing_slash.on': False} 
     73         
    7274        def index(self, path_info, relative=None): 
    7375            return cherrypy.url(path_info, relative=bool(relative)) 
     
    134136        def by_code(self, code): 
    135137            raise cherrypy.HTTPRedirect("somewhere else", code) 
     138        by_code._cp_config = {'tools.trailing_slash.extra': True} 
    136139         
    137140        def nomodify(self): 
     
    512515            ignore.pop() 
    513516     
    514     def testRedirect(self): 
    515         self.getPage("/redirect/") 
    516         self.assertBody('child') 
    517         self.assertStatus(200) 
    518          
     517    def testSlashes(self): 
    519518        # Test that requests for index methods without a trailing slash 
    520519        # get redirected to the same URI path with a trailing slash. 
     
    532531            self.assertInBody("<a href='%s/'>%s/</a>" % 
    533532                              (self.base(), self.base())) 
     533         
     534        # Test that requests for NON-index methods WITH a trailing slash 
     535        # get redirected to the same URI path WITHOUT a trailing slash. 
     536        # Make sure GET params are preserved. 
     537        self.getPage("/redirect/by_code/?code=307") 
     538        self.assertStatus(('302 Found', '303 See Other')) 
     539        self.assertInBody("<a href='%s/redirect/by_code?code=307'>" 
     540                          "%s/redirect/by_code?code=307</a>" 
     541                          % (self.base(), self.base())) 
     542         
     543        # If the trailing_slash tool is off, CP should just continue 
     544        # as if the slashes were correct. But it needs some help 
     545        # inside cherrypy.url to form correct output. 
     546        self.getPage('/url?path_info=page1') 
     547        self.assertBody('%s/url/page1' % self.base()) 
     548        self.getPage('/url/leaf/?path_info=page1') 
     549        self.assertBody('%s/url/page1' % self.base()) 
     550     
     551    def testRedirect(self): 
     552        self.getPage("/redirect/") 
     553        self.assertBody('child') 
     554        self.assertStatus(200) 
    534555         
    535556        self.getPage("/redirect/by_code?code=300") 
  • trunk/cherrypy/test/test_objectmapping.py

    r1359 r1369  
    6565            return "myMethod from dir1, path_info is:" + repr(cherrypy.request.path_info) 
    6666        myMethod.exposed = True 
    67         myMethod._cp_config = {'request.redirect_on_extra_slash': True} 
     67        myMethod._cp_config = {'tools.trailing_slash.extra': True} 
    6868         
    6969        def default(self, *params): 
  • trunk/cherrypy/test/test_proxy.py

    r1359 r1369  
    1919            raise cherrypy.HTTPRedirect('blah') 
    2020        xhost.exposed = True 
    21         xhost._cp_config = {'tools.proxy.local': 'X-Host'} 
     21        xhost._cp_config = {'tools.proxy.local': 'X-Host', 
     22                            'tools.trailing_slash.extra': True, 
     23                            } 
    2224         
    2325        def base(self): 
     
    9294                             "%s://%s%s%s/this/new/page" 
    9395                             % (self.scheme, self.HOST, port, sn)) 
     96         
     97        # Test trailing slash (see http://www.cherrypy.org/ticket/562). 
     98        self.getPage("/xhost/", headers=[('X-Host', 'www.yetanother.com')]) 
     99        self.assertHeader('Location', "%s://www.yetanother.com/xhost" 
     100                          % self.scheme) 
    94101 
    95102 

Hosted by WebFaction

Log in as guest/cpguest to create tickets