Changeset 760
- Timestamp:
- 10/29/05 16:12:01
- Files:
-
- trunk/cherrypy/_cphttptools.py (modified) (8 diffs)
- trunk/cherrypy/_cputil.py (modified) (2 diffs)
- trunk/cherrypy/config.py (modified) (2 diffs)
- trunk/cherrypy/lib/cptools.py (modified) (1 diff)
- trunk/cherrypy/lib/filter/staticfilter.py (modified) (1 diff)
- trunk/cherrypy/lib/filter/xmlrpcfilter.py (modified) (3 diffs)
- trunk/cherrypy/test/helper.py (modified) (2 diffs)
- trunk/cherrypy/test/test_baseurl_filter.py (modified) (1 diff)
- trunk/cherrypy/test/test_core.py (modified) (6 diffs)
- trunk/cherrypy/test/test_logdebuginfo_filter.py (modified) (1 diff)
- trunk/cherrypy/test/test_objectmapping.py (modified) (2 diffs)
- trunk/cherrypy/test/webtest.py (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/cherrypy/_cphttptools.py
r758 r760 200 200 201 201 # 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. 203 204 self.processRequestLine(requestLine) 204 205 … … 246 247 self.processRequestBody = self.method in ("POST", "PUT") 247 248 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) 259 253 if path == "*": 260 254 # "...the request does not apply to a particular resource, … … 262 256 # http://www.w3.org/Protocols/rfc2616/rfc2616-sec5.html#sec5.1.2 263 257 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) 270 267 271 268 # Save original value (in case it gets modified by filters) 272 269 self.path = self.originalPath = path 270 self.queryString = qs 273 271 274 272 # Change objectPath in filters to change 275 273 # the object that will get rendered 276 self.objectPath = None274 self.objectPath = path 277 275 278 276 def processHeaders(self): … … 347 345 self.base = "%s://%s" % (self.scheme, self.headerMap.get('Host', '')) 348 346 self.browserUrl = self.base + self.path 349 if self.queryString: 347 if self.queryString: 350 348 self.browserUrl += '?' + self.queryString 351 349 … … 392 390 """Obtain and set cherrypy.response.body from a page handler.""" 393 391 if path is None: 394 path = self.objectPath or self.path392 path = self.objectPath 395 393 396 394 while True: … … 408 406 path = x.path 409 407 410 def mapPathToObject(self, path):408 def mapPathToObject(self, objectpath): 411 409 """For path, return the corresponding exposed callable (or raise NotFound). 412 410 … … 427 425 428 426 # Remove leading and trailing slash 429 tpath = path.strip("/")427 tpath = objectpath.strip("/") 430 428 431 429 if not tpath: … … 484 482 if getattr(cherrypy, "debug", None): 485 483 cherrypy.log(" NOT FOUND", "DEBUG") 486 raise cherrypy.NotFound( path)484 raise cherrypy.NotFound(objectpath) 487 485 488 486 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('/'): 493 490 atoms = self.browserUrl.split("?", 1) 494 491 newUrl = atoms.pop(0) + '/' trunk/cherrypy/_cputil.py
r758 r760 52 52 # Try object path 53 53 try: 54 path = cherrypy.request.objectPath or cherrypy.request.path54 path = cherrypy.request.objectPath 55 55 except AttributeError: 56 56 path = '/' … … 97 97 objectList = getObjectTrail() 98 98 if objectList: 99 pathList = cherrypy.request.objectPath or cherrypy.request.path99 pathList = cherrypy.request.objectPath 100 100 pathList = pathList.split("/")[1:] 101 101 for i in xrange(len(objectList) - 1, -1, -1): trunk/cherrypy/config.py
r692 r760 95 95 if path is None: 96 96 try: 97 path = cherrypy.request. path97 path = cherrypy.request.objectPath 98 98 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. 100 100 path = "global" 101 101 102 102 while True: 103 103 if path == "": … … 134 134 135 135 try: 136 path = cherrypy.request. path136 path = cherrypy.request.objectPath 137 137 except AttributeError: 138 138 return results trunk/cherrypy/lib/cptools.py
r731 r760 260 260 strModifTime = HTTPDate(time.gmtime(stat.st_mtime)) 261 261 if cherrypy.request.headerMap.has_key('If-Modified-Since'): 262 # Check if if-modified-since date is the same as strModifTime263 262 if cherrypy.request.headerMap['If-Modified-Since'] == strModifTime: 264 263 response.status = "304 Not Modified" trunk/cherrypy/lib/filter/staticfilter.py
r756 r760 42 42 return 43 43 44 path = request.objectPath or request.path44 path = request.objectPath 45 45 46 46 regex = config.get('staticFilter.match', '') trunk/cherrypy/lib/filter/xmlrpcfilter.py
r758 r760 116 116 Unmarshalls the posted data to a methodname and parameters. 117 117 - 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. 120 121 beforeFinalize: 121 122 Marshalls cherrypy.response.body to xmlrpc. … … 149 150 def beforeRequestBody(self): 150 151 """ 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: 153 156 return True 154 157 155 cherrypy.request.isRPC = self.testValidityOfRequest()156 if not cherrypy.request.isRPC:158 request.isRPC = self.testValidityOfRequest() 159 if not request.isRPC: 157 160 # used for debugging or more info 158 161 # print 'not a valid xmlrpc call' 159 162 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) 165 167 try: 166 168 params, method = xmlrpclib.loads(data) 167 169 except Exception: 168 170 params, method = ('ERROR PARAMS', ), 'ERRORMETHOD' 169 cherrypy.request.rpcMethod, cherrypy.request.rpcParams = method, params 171 request.rpcMethod, request.rpcParams = method, params 172 170 173 # patch the path. there are only a few options: 171 174 # - 'RPC2' + method >> method 172 175 # - 'someurl' + method >> someurl.method 173 176 # - '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 183 185 def beforeMain(self): 184 186 """This is a variation of main() from _cphttptools. 185 187 186 188 The reason it is redone here is because we don't want 187 189 cherrypy.response.body = iterable(body) - we want to use … … 192 194 return 193 195 194 path = cherrypy.request.objectPath or cherrypy.request.path196 path = cherrypy.request.objectPath 195 197 196 198 while True: trunk/cherrypy/test/helper.py
r758 r760 77 77 78 78 def onStartResource(self): 79 path = cherrypy.request. path79 path = cherrypy.request.objectPath 80 80 if path.startswith(self.prefix): 81 81 cherrypy.request.objectPath = path[len(self.prefix):] 82 82 vroot = "" 83 ##vroot = "/vpath" 83 84 test_vrf = VirtualRootFilter(vroot) 84 85 … … 142 143 143 144 if vroot: 144 url = vroot + url 145 if url != "*": 146 url = vroot + url 145 147 filters = getattr(cherrypy.root, "_cpFilterList", None) 146 148 if filters is None: trunk/cherrypy/test/test_baseurl_filter.py
r719 r760 49 49 def testBaseUrlFilter(self): 50 50 self.getPage("/") 51 self.assertHeader('Location', "http://www.mydomain.com/dummy") 51 self.assertHeader('Location', 52 "http://www.mydomain.com%s/dummy" % helper.vroot) 52 53 53 54 trunk/cherrypy/test/test_core.py
r758 r760 381 381 from cherrypy import _cphttptools 382 382 cherrypy.serving.request = r = _cphttptools.Request("", "", "") 383 r. path = path383 r.objectPath = r.path = path 384 384 result = cherrypy.config.get(key, None) 385 385 self.assertEqual(result, expected) … … 457 457 haslength = True 458 458 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)) 460 461 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)) 462 464 463 465 self.assertEqual(data[1][:15], '127.0.0.1 - - [') … … 467 469 haslength = True 468 470 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)) 470 473 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)) 472 476 473 477 data = open(logFile, "rb").readlines() … … 478 482 self.assertBody("'a'") 479 483 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)) 481 486 482 487 # Test that tracebacks get written to the error log. … … 501 506 # Make sure GET params are preserved. 502 507 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)) 507 521 508 522 self.getPage("/redirect/by_code?code=300") … … 767 781 if httpcls and httpcls.__name__ == "WSGIServer": 768 782 cherrypy.config.update({ 769 ' /maxrequestsize': {'server.maxRequestBodySize': 3}})783 '%s/maxrequestsize' % helper.vroot: {'server.maxRequestBodySize': 3}}) 770 784 self.getPage('/maxrequestsize/upload', h, "POST", b) 771 785 self.assertStatus("413 Request Entity Too Large") trunk/cherrypy/test/test_logdebuginfo_filter.py
r717 r760 78 78 """ 79 79 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', 82 83 } 83 84 }) trunk/cherrypy/test/test_objectmapping.py
r719 r760 148 148 149 149 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) 151 151 152 152 self.getPage("/dir1/dir2") 153 153 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)) 156 156 157 157 self.getPage("/dir1/dir2/dir3/dir4/index") … … 160 160 self.getPage("/redirect") 161 161 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)) 164 164 165 165 # Test that we can use URL's which aren't all valid Python identifiers trunk/cherrypy/test/webtest.py
r697 r760 270 270 def assertStatus(self, status, msg=None): 271 271 """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) 276 282 277 283 def assertHeader(self, key, value=None, msg=None):

