| 292 | | # Remove leading and trailing slash |
|---|
| 293 | | tpath = objectpath.strip("/") |
|---|
| 294 | | |
|---|
| 295 | | if not tpath: |
|---|
| 296 | | objectPathList = [] |
|---|
| 297 | | else: |
|---|
| 298 | | objectPathList = tpath.split('/') |
|---|
| 299 | | if objectPathList == ['global']: |
|---|
| 300 | | objectPathList = ['global_'] |
|---|
| 301 | | objectPathList = ['root'] + objectPathList + ['index'] |
|---|
| 302 | | |
|---|
| 303 | | if getattr(cherrypy, "debug", None): |
|---|
| 304 | | cherrypy.log(" Attempting to map path: %s using %s" |
|---|
| 305 | | % (tpath, objectPathList), "DEBUG") |
|---|
| 306 | | |
|---|
| 307 | | # Try successive objects... (and also keep the remaining object list) |
|---|
| 308 | | isFirst = True |
|---|
| 309 | | isSecond = False |
|---|
| 310 | | foundIt = False |
|---|
| 311 | | virtualPathList = [] |
|---|
| 312 | | while objectPathList: |
|---|
| 313 | | if isFirst or isSecond: |
|---|
| 314 | | # Only try this for a.b.index() or a.b() |
|---|
| 315 | | candidate = self.getObjFromPath(objectPathList) |
|---|
| 316 | | if callable(candidate) and getattr(candidate, 'exposed', False): |
|---|
| 317 | | foundIt = True |
|---|
| 318 | | break |
|---|
| 319 | | # Couldn't find the object: pop one from the list and try "default" |
|---|
| 320 | | lastObj = objectPathList.pop() |
|---|
| 321 | | if (not isFirst) or (not tpath): |
|---|
| 322 | | virtualPathList.insert(0, lastObj) |
|---|
| 323 | | objectPathList.append('default') |
|---|
| 324 | | candidate = self.getObjFromPath(objectPathList) |
|---|
| 325 | | if callable(candidate) and getattr(candidate, 'exposed', False): |
|---|
| 326 | | foundIt = True |
|---|
| 327 | | break |
|---|
| 328 | | objectPathList.pop() # Remove "default" |
|---|
| 329 | | if isSecond: |
|---|
| 330 | | isSecond = False |
|---|
| 331 | | if isFirst: |
|---|
| 332 | | isFirst = False |
|---|
| 333 | | isSecond = True |
|---|
| 334 | | |
|---|
| 335 | | # Check results of traversal |
|---|
| 336 | | if not foundIt: |
|---|
| 337 | | if tpath.endswith("favicon.ico"): |
|---|
| 338 | | # Use CherryPy's default favicon.ico. If developers really, |
|---|
| 339 | | # really want no favicon, they can make a dummy method |
|---|
| 340 | | # that raises NotFound. |
|---|
| 341 | | icofile = os.path.join(os.path.dirname(__file__), "favicon.ico") |
|---|
| 342 | | cptools.serveFile(icofile) |
|---|
| 343 | | applyFilters('beforeFinalize') |
|---|
| 344 | | cherrypy.response.finalize() |
|---|
| 345 | | raise cherrypy.RequestHandled() |
|---|
| 346 | | else: |
|---|
| 347 | | # We didn't find anything |
|---|
| 348 | | if getattr(cherrypy, "debug", None): |
|---|
| 349 | | cherrypy.log(" NOT FOUND", "DEBUG") |
|---|
| 350 | | raise cherrypy.NotFound(objectpath) |
|---|
| 351 | | |
|---|
| 352 | | if isFirst: |
|---|
| 353 | | # We found the extra ".index". Check if the original path |
|---|
| 354 | | # had a trailing slash (otherwise, do a redirect). |
|---|
| 355 | | if not objectpath.endswith('/'): |
|---|
| 356 | | atoms = self.browserUrl.split("?", 1) |
|---|
| 357 | | newUrl = atoms.pop(0) + '/' |
|---|
| 358 | | if atoms: |
|---|
| 359 | | newUrl += "?" + atoms[0] |
|---|
| 360 | | if getattr(cherrypy, "debug", None): |
|---|
| 361 | | cherrypy.log(" Found: redirecting to %s" % newUrl, "DEBUG") |
|---|
| 362 | | raise cherrypy.HTTPRedirect(newUrl) |
|---|
| 363 | | |
|---|
| 364 | | if getattr(cherrypy, "debug", None): |
|---|
| 365 | | cherrypy.log(" Found: %s" % candidate, "DEBUG") |
|---|
| 366 | | return candidate, objectPathList, virtualPathList |
|---|
| 367 | | |
|---|
| 368 | | def getObjFromPath(self, objPathList): |
|---|
| 369 | | """For a given objectPathList, return the object (or None). |
|---|
| 370 | | |
|---|
| 371 | | objPathList should be a list of the form: ['root', 'a', 'b', 'index']. |
|---|
| 372 | | """ |
|---|
| 373 | | |
|---|
| 374 | | root = cherrypy |
|---|
| 375 | | for objname in objPathList: |
|---|
| 376 | | # maps virtual filenames to Python identifiers (substitutes '.' for '_') |
|---|
| 377 | | objname = objname.replace('.', '_') |
|---|
| 378 | | if getattr(cherrypy, "debug", None): |
|---|
| 379 | | cherrypy.log(" Trying: %s.%s" % (root, objname), "DEBUG") |
|---|
| 380 | | root = getattr(root, objname, None) |
|---|
| 381 | | if root is None: |
|---|
| 382 | | return None |
|---|
| 383 | | return root |
|---|
| | 291 | objectTrail = _cputil.get_object_trail(objectpath) |
|---|
| | 292 | names = [name for name, candidate in objectTrail] |
|---|
| | 293 | |
|---|
| | 294 | # Try successive objects |
|---|
| | 295 | for i in xrange(len(objectTrail) - 1, -1, -1): |
|---|
| | 296 | |
|---|
| | 297 | name, candidate = objectTrail[i] |
|---|
| | 298 | |
|---|
| | 299 | # Try a "default" method on the current leaf. |
|---|
| | 300 | defhandler = getattr(candidate, "default", None) |
|---|
| | 301 | if callable(defhandler) and getattr(defhandler, 'exposed', False): |
|---|
| | 302 | return defhandler, names[:i+1] + ["default"], names[i+1:-1] |
|---|
| | 303 | |
|---|
| | 304 | # Uncomment the next line to restrict positional params to "default". |
|---|
| | 305 | # if i < len(objectTrail) - 2: continue |
|---|
| | 306 | |
|---|
| | 307 | # Try the current leaf. |
|---|
| | 308 | if callable(candidate) and getattr(candidate, 'exposed', False): |
|---|
| | 309 | if i == len(objectTrail) - 1: |
|---|
| | 310 | # We found the extra ".index". Check if the original path |
|---|
| | 311 | # had a trailing slash (otherwise, do a redirect). |
|---|
| | 312 | if not objectpath.endswith('/'): |
|---|
| | 313 | atoms = self.browserUrl.split("?", 1) |
|---|
| | 314 | newUrl = atoms.pop(0) + '/' |
|---|
| | 315 | if atoms: |
|---|
| | 316 | newUrl += "?" + atoms[0] |
|---|
| | 317 | raise cherrypy.HTTPRedirect(newUrl) |
|---|
| | 318 | return candidate, names[:i+1], names[i+1:-1] |
|---|
| | 319 | |
|---|
| | 320 | # Not found at any node |
|---|
| | 321 | if objectpath.endswith("favicon.ico"): |
|---|
| | 322 | # Use CherryPy's default favicon.ico. If developers really, |
|---|
| | 323 | # really want no favicon, they can make a dummy method |
|---|
| | 324 | # that raises NotFound. |
|---|
| | 325 | icofile = os.path.join(os.path.dirname(__file__), "favicon.ico") |
|---|
| | 326 | cptools.serveFile(icofile) |
|---|
| | 327 | applyFilters('beforeFinalize') |
|---|
| | 328 | cherrypy.response.finalize() |
|---|
| | 329 | raise cherrypy.RequestHandled() |
|---|
| | 330 | else: |
|---|
| | 331 | # We didn't find anything |
|---|
| | 332 | raise cherrypy.NotFound(objectpath) |
|---|