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

Changeset 1368

Show
Ignore:
Timestamp:
09/16/06 12:33:20
Author:
fumanchu
Message:

Improvements to cherrypy.url:

  1. Bugfix for relative input ("/leaf" + "new"}}} was generating "/leaf/new", now generates "/new").
  2. Support for single and double dots.
  3. New 'relative' arg for producing relative output.
Files:

Legend:

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

    r1365 r1368  
    55import os as _os 
    66_localdir = _os.path.dirname(__file__) 
     7from urlparse import urljoin as _urljoin 
    78 
    89from cherrypy._cperror import HTTPError, HTTPRedirect, InternalRedirect, NotFound, CherryPyException 
     
    150151            return expose_ 
    151152 
    152 def url(path="", qs="", script_name=None, base=None): 
     153def url(path="", qs="", script_name=None, base=None, relative=False): 
    153154    """Create an absolute URL for the given path. 
    154155     
     
    161162    to find a script_name, if available. 
    162163     
    163     If base is None, cherrypy.request.base will be used if available
     164    If base is None, cherrypy.request.base will be used (if available)
    164165    Note that you can use cherrypy.tools.proxy to change this. 
    165166     
     
    174175            path = request.path_info 
    175176        if not path.startswith("/"): 
    176             path = request.path_info + "/" + path 
     177            path = _urljoin(request.path_info, path) 
    177178        if script_name is None: 
    178179            script_name = request.app.script_name 
     
    180181            base = request.base 
    181182         
    182         return base + script_name + path + qs 
     183        newurl = base + script_name + path + qs 
    183184    else: 
    184185        # No request.app (we're being called outside a request). 
     
    206207                base = "%s://%s" % (scheme, host) 
    207208        path = (script_name or "") + path 
    208         return base + path + qs 
     209        newurl = base + path + qs 
     210     
     211    if './' in newurl: 
     212        # Normalize the URL by removing ./ and ../ 
     213        atoms = [] 
     214        for atom in newurl.split('/'): 
     215            if atom == '.': 
     216                pass 
     217            elif atom == '..': 
     218                atoms.pop() 
     219            else: 
     220                atoms.append(atom) 
     221        newurl = '/'.join(atoms) 
     222     
     223    if relative: 
     224        old = url().split('/')[:-1] 
     225        new = newurl.split('/') 
     226        while old and new: 
     227            a, b = old[0], new[0] 
     228            if a != b: 
     229                break 
     230            old.pop(0) 
     231            new.pop(0) 
     232        new = (['..'] * len(old)) + new 
     233        newurl = '/'.join(new) 
     234     
     235    return newurl 
     236 
    209237 
    210238# Set up config last so it can wrap other top-level objects 
  • trunk/cherrypy/test/test_core.py

    r1364 r1368  
    5252     
    5353    root = Root() 
    54  
    55  
     54     
     55     
    5656    class TestType(type): 
    5757        """Metaclass which automatically exposes all functions in each subclass, 
     
    6666    class Test(object): 
    6767        __metaclass__ = TestType 
    68  
    69  
     68     
     69     
     70    class URL(Test): 
     71         
     72        def index(self, path_info, relative=None): 
     73            return cherrypy.url(path_info, relative=bool(relative)) 
     74         
     75        def leaf(self, path_info, relative=None): 
     76            return cherrypy.url(path_info, relative=bool(relative)) 
     77     
     78     
    7079    class Params(Test): 
    7180         
     
    941950        self.assertHeader('Content-Type', 'text/plain') 
    942951        self.getPage('/defct/html') 
     952     
     953    def test_cherrypy_url(self): 
     954        # Input relative to current 
     955        self.getPage('/url/leaf?path_info=page1') 
     956        self.assertBody('%s/url/page1' % self.base()) 
     957        self.getPage('/url/?path_info=page1') 
     958        self.assertBody('%s/url/page1' % self.base()) 
     959         
     960        # Input is 'absolute'; that is, relative to script_name 
     961        self.getPage('/url/leaf?path_info=/page1') 
     962        self.assertBody('%s/page1' % self.base()) 
     963        self.getPage('/url/?path_info=/page1') 
     964        self.assertBody('%s/page1' % self.base()) 
     965         
     966        # Single dots 
     967        self.getPage('/url/leaf?path_info=./page1') 
     968        self.assertBody('%s/url/page1' % self.base()) 
     969        self.getPage('/url/leaf?path_info=other/./page1') 
     970        self.assertBody('%s/url/other/page1' % self.base()) 
     971        self.getPage('/url/?path_info=/other/./page1') 
     972        self.assertBody('%s/other/page1' % self.base()) 
     973         
     974        # Double dots 
     975        self.getPage('/url/leaf?path_info=../page1') 
     976        self.assertBody('%s/page1' % self.base()) 
     977        self.getPage('/url/leaf?path_info=other/../page1') 
     978        self.assertBody('%s/url/page1' % self.base()) 
     979        self.getPage('/url/leaf?path_info=/other/../page1') 
     980        self.assertBody('%s/page1' % self.base()) 
     981         
     982        # Output relative to current path or script_name 
     983        self.getPage('/url/?path_info=page1&relative=True') 
     984        self.assertBody('page1') 
     985        self.getPage('/url/leaf?path_info=/page1&relative=True') 
     986        self.assertBody('../page1') 
     987        self.getPage('/url/leaf?path_info=../page1&relative=True') 
     988        self.assertBody('../page1') 
     989        self.getPage('/url/?path_info=other/../page1&relative=True') 
     990        self.assertBody('page1') 
    943991 
    944992 

Hosted by WebFaction

Log in as guest/cpguest to create tickets