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

Changeset 760

Show
Ignore:
Timestamp:
10/29/05 16:12:01
Author:
fumanchu
Message:

Fix for #373 (arbitrary mount points, or "virtual roots"). All internal use of request.path has been changed to inspect request.objectPath instead (the "rewritten path"). The request.path should never be rewritten; instead, it should only be used to generate new URL's based on the original path. The request.originalPath attribute can now probably be deprecated.

Files:

Legend:

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

    r758 r760  
    200200             
    201201            # This has to be done very early in the request process, 
    202             # because request.path is used for config lookups right away. 
     202            # because request.objectPath is used for config lookups 
     203            # right away. 
    203204            self.processRequestLine(requestLine) 
    204205             
     
    246247        self.processRequestBody = self.method in ("POST", "PUT") 
    247248         
    248         # separate the queryString, or set it to "" if not found 
    249         if "?" in path: 
    250             path, self.queryString = path.split("?", 1) 
    251         else: 
    252             path, self.queryString = path, "" 
    253          
    254         # Unquote the path (e.g. "/this%20path" -> "this path"). 
    255         # http://www.w3.org/Protocols/rfc2616/rfc2616-sec5.html#sec5.1.2 
    256         # Note that cgi.parse_qs will decode the querystring for us. 
    257         path = urllib.unquote(path) 
    258          
     249        # path may be an abs_path (including "http://host.domain.tld"); 
     250        # Ignore scheme, location, and fragments (so config lookups work). 
     251        # [Therefore, this assumes all hosts are valid for this server.] 
     252        scheme, location, path, params, qs, frag = urlparse(path) 
    259253        if path == "*": 
    260254            # "...the request does not apply to a particular resource, 
     
    262256            # http://www.w3.org/Protocols/rfc2616/rfc2616-sec5.html#sec5.1.2 
    263257            path = "global" 
    264         elif not path.startswith("/"): 
    265             # path is an absolute path (including "http://host.domain.tld"); 
    266             # convert it to a relative path, so configMap lookups work. This 
    267             # default method assumes all hosts are valid for this server. 
    268             scheme, location, p, pm, q, f = urlparse(path) 
    269             path = path[len(scheme + "://" + location):] 
     258        else: 
     259            if params: 
     260                params = ";" + params 
     261            path = path + params 
     262             
     263            # Unquote the path (e.g. "/this%20path" -> "this path"). 
     264            # http://www.w3.org/Protocols/rfc2616/rfc2616-sec5.html#sec5.1.2 
     265            # Note that cgi.parse_qs will decode the querystring for us. 
     266            path = urllib.unquote(path) 
    270267         
    271268        # Save original value (in case it gets modified by filters) 
    272269        self.path = self.originalPath = path 
     270        self.queryString = qs 
    273271         
    274272        # Change objectPath in filters to change 
    275273        # the object that will get rendered 
    276         self.objectPath = None 
     274        self.objectPath = path 
    277275     
    278276    def processHeaders(self): 
     
    347345        self.base = "%s://%s" % (self.scheme, self.headerMap.get('Host', '')) 
    348346        self.browserUrl = self.base + self.path 
    349         if self.queryString:   
     347        if self.queryString: 
    350348            self.browserUrl += '?' + self.queryString 
    351349     
     
    392390        """Obtain and set cherrypy.response.body from a page handler.""" 
    393391        if path is None: 
    394             path = self.objectPath or self.path 
     392            path = self.objectPath 
    395393         
    396394        while True: 
     
    408406                path = x.path 
    409407     
    410     def mapPathToObject(self, path): 
     408    def mapPathToObject(self, objectpath): 
    411409        """For path, return the corresponding exposed callable (or raise NotFound). 
    412410         
     
    427425         
    428426        # Remove leading and trailing slash 
    429         tpath = path.strip("/") 
     427        tpath = objectpath.strip("/") 
    430428         
    431429        if not tpath: 
     
    484482                if getattr(cherrypy, "debug", None): 
    485483                    cherrypy.log("    NOT FOUND", "DEBUG") 
    486                 raise cherrypy.NotFound(path) 
     484                raise cherrypy.NotFound(objectpath) 
    487485         
    488486        if isFirst: 
    489             # We found the extra ".index" 
    490             # Check if the original path had a trailing slash (otherwise, do 
    491             #   a redirect) 
    492             if path[-1] != '/': 
     487            # We found the extra ".index". Check if the original path 
     488            # had a trailing slash (otherwise, do a redirect). 
     489            if not objectpath.endswith('/'): 
    493490                atoms = self.browserUrl.split("?", 1) 
    494491                newUrl = atoms.pop(0) + '/' 
  • trunk/cherrypy/_cputil.py

    r758 r760  
    5252        # Try object path 
    5353        try: 
    54             path = cherrypy.request.objectPath or cherrypy.request.path 
     54            path = cherrypy.request.objectPath 
    5555        except AttributeError: 
    5656            path = '/' 
     
    9797    objectList = getObjectTrail() 
    9898    if objectList: 
    99         pathList = cherrypy.request.objectPath or cherrypy.request.path 
     99        pathList = cherrypy.request.objectPath 
    100100        pathList = pathList.split("/")[1:] 
    101101        for i in xrange(len(objectList) - 1, -1, -1): 
  • trunk/cherrypy/config.py

    r692 r760  
    9595    if path is None: 
    9696        try: 
    97             path = cherrypy.request.path 
     97            path = cherrypy.request.objectPath 
    9898        except AttributeError: 
    99             # There's no request.path yet, so use the global settings. 
     99            # There's no request.objectPath yet, so use the global settings. 
    100100            path = "global" 
    101  
     101     
    102102    while True: 
    103103        if path == "": 
     
    134134     
    135135    try: 
    136         path = cherrypy.request.path 
     136        path = cherrypy.request.objectPath 
    137137    except AttributeError: 
    138138        return results 
  • trunk/cherrypy/lib/cptools.py

    r731 r760  
    260260    strModifTime = HTTPDate(time.gmtime(stat.st_mtime)) 
    261261    if cherrypy.request.headerMap.has_key('If-Modified-Since'): 
    262         # Check if if-modified-since date is the same as strModifTime 
    263262        if cherrypy.request.headerMap['If-Modified-Since'] == strModifTime: 
    264263            response.status = "304 Not Modified" 
  • trunk/cherrypy/lib/filter/staticfilter.py

    r756 r760  
    4242            return 
    4343         
    44         path = request.objectPath or request.path 
     44        path = request.objectPath 
    4545         
    4646        regex = config.get('staticFilter.match', '') 
  • trunk/cherrypy/lib/filter/xmlrpcfilter.py

    r758 r760  
    116116        Unmarshalls the posted data to a methodname and parameters. 
    117117        - These are stored in cherrypy.request.rpcMethod and .rpcParams 
    118         - The method is also stored in cherrypy.request.path, so CP2 will find 
    119           the right method to call for you, based on the root's position. 
     118        - The method is also stored in cherrypy.request.objectPath, 
     119          so CP2 will find the right method to call for you, 
     120          based on the root's position. 
    120121    beforeFinalize: 
    121122        Marshalls cherrypy.response.body to xmlrpc. 
     
    149150    def beforeRequestBody(self): 
    150151        """ Called after the request header has been read/parsed""" 
    151         cherrypy.request.xmlRpcFilterOn = cherrypy.config.get('xmlRpcFilter.on', False) 
    152         if not cherrypy.request.xmlRpcFilterOn: 
     152        request = cherrypy.request 
     153         
     154        request.xmlRpcFilterOn = cherrypy.config.get('xmlRpcFilter.on', False) 
     155        if not request.xmlRpcFilterOn: 
    153156            return True 
    154157         
    155         cherrypy.request.isRPC = self.testValidityOfRequest() 
    156         if not cherrypy.request.isRPC:  
     158        request.isRPC = self.testValidityOfRequest() 
     159        if not request.isRPC:  
    157160            # used for debugging or more info 
    158161            # print 'not a valid xmlrpc call' 
    159162            return # break this if it's not for this filter!! 
    160         # used for debugging, or more info: 
    161         # print "xmlrpcmethod...", 
    162         cherrypy.request.processRequestBody = False 
    163         dataLength = int(cherrypy.request.headerMap.get('Content-Length', 0)) 
    164         data = cherrypy.request.rfile.read(dataLength) 
     163         
     164        request.processRequestBody = False 
     165        dataLength = int(request.headerMap.get('Content-Length', 0)) 
     166        data = request.rfile.read(dataLength) 
    165167        try: 
    166168            params, method = xmlrpclib.loads(data) 
    167169        except Exception: 
    168170            params, method = ('ERROR PARAMS', ), 'ERRORMETHOD' 
    169         cherrypy.request.rpcMethod, cherrypy.request.rpcParams = method, params 
     171        request.rpcMethod, request.rpcParams = method, params 
     172         
    170173        # patch the path. there are only a few options: 
    171174        # - 'RPC2' + method >> method 
    172175        # - 'someurl' + method >> someurl.method 
    173176        # - 'someurl/someother' + method >> someurl.someother.method 
    174         if not cherrypy.request.path.endswith('/'): 
    175             cherrypy.request.path += '/' 
    176         if cherrypy.request.path.startswith('/RPC2/'): 
    177             cherrypy.request.path=cherrypy.request.path[5:] ## strip the first /rpc2 
    178         cherrypy.request.path += str(method).replace('.', '/') 
    179         cherrypy.request.paramList = list(params) 
    180         # used for debugging and more info 
    181         # print "XMLRPC Filter: calling '%s' with args: '%s' " % (cherrypy.request.path,params) 
    182  
     177        if not request.objectPath.endswith('/'): 
     178            request.objectPath += '/' 
     179        if request.objectPath.startswith('/RPC2/'): 
     180            # strip the first /rpc2 
     181            request.objectPath = request.objectPath[5:] 
     182        request.objectPath += str(method).replace('.', '/') 
     183        request.paramList = list(params) 
     184     
    183185    def beforeMain(self): 
    184186        """This is a variation of main() from _cphttptools. 
    185  
     187         
    186188        The reason it is redone here is because we don't want 
    187189        cherrypy.response.body = iterable(body) - we want to use 
     
    192194            return 
    193195         
    194         path = cherrypy.request.objectPath or cherrypy.request.path 
     196        path = cherrypy.request.objectPath 
    195197         
    196198        while True: 
  • trunk/cherrypy/test/helper.py

    r758 r760  
    7777     
    7878    def onStartResource(self): 
    79         path = cherrypy.request.path 
     79        path = cherrypy.request.objectPath 
    8080        if path.startswith(self.prefix): 
    8181            cherrypy.request.objectPath = path[len(self.prefix):] 
    8282vroot = "" 
     83##vroot = "/vpath" 
    8384test_vrf = VirtualRootFilter(vroot) 
    8485 
     
    142143         
    143144        if vroot: 
    144             url = vroot + url 
     145            if url != "*": 
     146                url = vroot + url 
    145147            filters = getattr(cherrypy.root, "_cpFilterList", None) 
    146148            if filters is None: 
  • trunk/cherrypy/test/test_baseurl_filter.py

    r719 r760  
    4949    def testBaseUrlFilter(self): 
    5050        self.getPage("/") 
    51         self.assertHeader('Location', "http://www.mydomain.com/dummy") 
     51        self.assertHeader('Location', 
     52                          "http://www.mydomain.com%s/dummy" % helper.vroot) 
    5253 
    5354 
  • trunk/cherrypy/test/test_core.py

    r758 r760  
    381381            from cherrypy import _cphttptools 
    382382            cherrypy.serving.request = r = _cphttptools.Request("", "", "") 
    383             r.path = path 
     383            r.objectPath = r.path = path 
    384384            result = cherrypy.config.get(key, None) 
    385385            self.assertEqual(result, expected) 
     
    457457                haslength = True 
    458458        if haslength: 
    459             self.assertEqual(data[0][-42:], '] "GET /flatten/as_string HTTP/1.1" 200 7\n') 
     459            self.assert_(data[0].endswith('] "GET %s/flatten/as_string HTTP/1.1" 200 7\n' 
     460                                          % helper.vroot)) 
    460461        else: 
    461             self.assertEqual(data[0][-42:], '] "GET /flatten/as_string HTTP/1.1" 200 -\n') 
     462            self.assert_(data[0].endswith('] "GET %s/flatten/as_string HTTP/1.1" 200 -\n' 
     463                                          % helper.vroot)) 
    462464         
    463465        self.assertEqual(data[1][:15], '127.0.0.1 - - [') 
     
    467469                haslength = True 
    468470        if haslength: 
    469             self.assertEqual(data[1][-41:], '] "GET /flatten/as_yield HTTP/1.1" 200 7\n') 
     471            self.assert_(data[1].endswith('] "GET %s/flatten/as_yield HTTP/1.1" 200 7\n' 
     472                                          % helper.vroot)) 
    470473        else: 
    471             self.assertEqual(data[1][-41:], '] "GET /flatten/as_yield HTTP/1.1" 200 -\n') 
     474            self.assert_(data[1].endswith('] "GET %s/flatten/as_yield HTTP/1.1" 200 -\n' 
     475                                          % helper.vroot)) 
    472476         
    473477        data = open(logFile, "rb").readlines() 
     
    478482        self.assertBody("'a'") 
    479483        data = open(logFile, "rb").readlines() 
    480         self.assertEqual(data[0][-53:], ' HTTP INFO 127.0.0.1 - GET /params/?thing=a HTTP/1.1\n') 
     484        self.assert_(data[0].endswith(' HTTP INFO 127.0.0.1 - GET %s/params/?thing=a HTTP/1.1\n' 
     485                                      % helper.vroot)) 
    481486         
    482487        # Test that tracebacks get written to the error log. 
     
    501506        # Make sure GET params are preserved. 
    502507        self.getPage("/redirect?id=3") 
    503         self.assert_(self.status in ('302 Found', '303 See Other')) 
    504         self.assertInBody("<a href='http://127.0.0.1:%s/redirect/?id=3'>" 
    505                           "http://127.0.0.1:%s/redirect/?id=3</a>" % 
    506                           (self.PORT, self.PORT)) 
     508        self.assertStatus(('302 Found', '303 See Other')) 
     509        self.assertInBody("<a href='http://127.0.0.1:%s%s/redirect/?id=3'>" 
     510                          "http://127.0.0.1:%s%s/redirect/?id=3</a>" % 
     511                          (self.PORT, helper.vroot, self.PORT, helper.vroot)) 
     512         
     513        if helper.vroot: 
     514            # Corner case: the "trailing slash" redirect could be tricky if 
     515            # we're using a virtual root and the URI is "/vroot" (no slash). 
     516            self.getPage("") 
     517            self.assertStatus(('302 Found', '303 See Other')) 
     518            self.assertInBody("<a href='http://127.0.0.1:%s%s/'>" 
     519                              "http://127.0.0.1:%s%s/</a>" % 
     520                              (self.PORT, helper.vroot, self.PORT, helper.vroot)) 
    507521         
    508522        self.getPage("/redirect/by_code?code=300") 
     
    767781        if httpcls and httpcls.__name__ == "WSGIServer": 
    768782            cherrypy.config.update({ 
    769                 '/maxrequestsize': {'server.maxRequestBodySize': 3}}) 
     783                '%s/maxrequestsize' % helper.vroot: {'server.maxRequestBodySize': 3}}) 
    770784            self.getPage('/maxrequestsize/upload', h, "POST", b) 
    771785            self.assertStatus("413 Request Entity Too Large") 
  • trunk/cherrypy/test/test_logdebuginfo_filter.py

    r717 r760  
    7878""" 
    7979            cherrypy.config.update({ 
    80                 '/bug326': {'server.maxRequestBodySize': 3, 
    81                             'server.environment': 'development', 
     80                ('%s/bug326' % helper.vroot): { 
     81                    'server.maxRequestBodySize': 3, 
     82                    'server.environment': 'development', 
    8283                } 
    8384            }) 
  • trunk/cherrypy/test/test_objectmapping.py

    r719 r760  
    148148         
    149149        self.getPage("/dir1/dir2/") 
    150         self.assertBody('index for dir2, path is:/dir1/dir2/'
     150        self.assertBody('index for dir2, path is:%s/dir1/dir2/' % helper.vroot
    151151         
    152152        self.getPage("/dir1/dir2") 
    153153        self.assert_(self.status in ('302 Found', '303 See Other')) 
    154         self.assertHeader('Location', 'http://%s:%s/dir1/dir2/' 
    155                           % (self.HOST, self.PORT)) 
     154        self.assertHeader('Location', 'http://%s:%s%s/dir1/dir2/' 
     155                          % (self.HOST, self.PORT, helper.vroot)) 
    156156         
    157157        self.getPage("/dir1/dir2/dir3/dir4/index") 
     
    160160        self.getPage("/redirect") 
    161161        self.assertStatus('302 Found') 
    162         self.assertHeader('Location', 'http://%s:%s/dir1/' 
    163                           % (self.HOST, self.PORT)) 
     162        self.assertHeader('Location', 'http://%s:%s%s/dir1/' 
     163                          % (self.HOST, self.PORT, helper.vroot)) 
    164164         
    165165        # Test that we can use URL's which aren't all valid Python identifiers 
  • trunk/cherrypy/test/webtest.py

    r697 r760  
    270270    def assertStatus(self, status, msg=None): 
    271271        """Fail if self.status != status.""" 
    272         if not self.status == status: 
    273             if msg is None: 
    274                 msg = 'Status (%s) != %s' % (`self.status`, `status`) 
    275             self._handlewebError(msg) 
     272        if isinstance(status, basestring): 
     273            if not self.status == status: 
     274                if msg is None: 
     275                    msg = 'Status (%s) != %s' % (`self.status`, `status`) 
     276                self._handlewebError(msg) 
     277        else: 
     278            if not self.status in status: 
     279                if msg is None: 
     280                    msg = 'Status (%s) not in %s' % (`self.status`, `status`) 
     281                self._handlewebError(msg) 
    276282     
    277283    def assertHeader(self, key, value=None, msg=None): 

Hosted by WebFaction

Log in as guest/cpguest to create tickets