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

Changeset 1303

Show
Ignore:
Timestamp:
08/30/06 19:02:25
Author:
fumanchu
Message:

Fix for #433 (mapPathToObject should remove a trailing /, not just add it). CP 3 only. Configurable now via request.redirect_on_extra_slash and request.redirect_on_missing_slash. Also broke the slash logic out of find_handler, so it's more reusable.

Files:

Legend:

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

    r1302 r1303  
    186186         
    187187        # Try successive objects (reverse order) 
    188         for i in xrange(len(object_trail) - 1, -1, -1): 
     188        num_candidates = len(object_trail) - 1 
     189        for i in xrange(num_candidates, -1, -1): 
    189190             
    190191            name, candidate, nodeconf, curpath = object_trail[i] 
     
    203204             
    204205            # Uncomment the next line to restrict positional params to "default". 
    205             # if i < len(object_trail) - 2: continue 
     206            # if i < num_candidates - 2: continue 
    206207             
    207208            # Try the current leaf. 
    208209            if getattr(candidate, 'exposed', False): 
    209210                request.config = set_conf() 
    210                 if i == len(object_trail) - 1: 
    211                     # We found the extra ".index". Check if the original path 
    212                     # had a trailing slash (otherwise, do a redirect). 
    213                     if path[-1:] != '/': 
    214                         atoms = request.browser_url.split("?", 1) 
    215                         new_url = atoms.pop(0) + '/' 
    216                         if atoms: 
    217                             new_url += "?" + atoms[0] 
    218                         raise cherrypy.HTTPRedirect(new_url) 
     211                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() 
     215                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() 
    219219                return candidate, names[i:-1] 
    220220         
     
    222222        request.config = set_conf() 
    223223        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 tool_up 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                atoms = request.browser_url.split("?", 1) 
     235                new_url = atoms.pop(0) + '/' 
     236                if atoms: 
     237                    new_url += "?" + atoms[0] 
     238                raise cherrypy.HTTPRedirect(new_url) 
     239     
     240    def check_extra_slash(self): 
     241        """Redirect if path_info has trailing slash (if configured).""" 
     242        request = cherrypy.request 
     243        pi = request.path_info 
     244         
     245        # Must use config here because tool_up hasn't run yet. 
     246        if request.config.get("request.redirect_on_extra_slash", 
     247                              request.redirect_on_extra_slash): 
     248            # If pi == '/', don't redirect to ''! 
     249            if pi[-1:] == '/' and pi != '/': 
     250                atoms = request.browser_url.split("?", 1) 
     251                new_url = atoms.pop(0)[:-1] 
     252                if atoms: 
     253                    new_url += "?" + atoms[0] 
     254                raise cherrypy.HTTPRedirect(new_url) 
    224255 
    225256 
     
    300331    config = None 
    301332    recursive_redirect = False 
     333    redirect_on_extra_slash = False 
     334    redirect_on_missing_slash = True 
    302335     
    303336    hookpoints = ['on_start_resource', 'before_request_body', 
  • trunk/cherrypy/lib/cptools.py

    r1294 r1303  
    220220    request = cherrypy.request 
    221221     
     222    # Guard against running twice. 
    222223    if hasattr(request, "virtual_prefix"): 
    223224        return 
  • trunk/cherrypy/test/test_objectmapping.py

    r1297 r1303  
    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} 
    6768         
    6869        def default(self, *params): 
     
    9293        def default(self): 
    9394            return "default for dir3, not exposed" 
    94      
    9595     
    9696    class Dir4: 
     
    179179            self.assertBody('index for dir2, path is:%s/dir1/dir2/' % prefix) 
    180180             
     181            # Test omitted trailing slash (should be redirected by default). 
    181182            self.getPage("/dir1/dir2") 
    182             self.assert_(self.status in ('302 Found', '303 See Other')) 
     183            self.assertStatus((302, 303)) 
    183184            self.assertHeader('Location', 'http://%s:%s%s/dir1/dir2/' 
    184185                              % (self.HOST, self.PORT, prefix)) 
    185186             
     187            # Test extra trailing slash (should be redirected if configured). 
     188            self.getPage("/dir1/myMethod/") 
     189            self.assertStatus((302, 303)) 
     190            self.assertHeader('Location', 'http://%s:%s%s/dir1/myMethod' 
     191                              % (self.HOST, self.PORT, prefix)) 
     192             
     193            # Test that default method must be exposed in order to match. 
    186194            self.getPage("/dir1/dir2/dir3/dir4/index") 
    187195            self.assertBody("default for dir1, param is:('dir2', 'dir3', 'dir4', 'index')") 

Hosted by WebFaction

Log in as guest/cpguest to create tickets