| 300 | | class Dispatcher(object): |
|---|
| 301 | | |
|---|
| 302 | | def __call__(self, path): |
|---|
| 303 | | """Find the appropriate page handler.""" |
|---|
| 304 | | request = cherrypy.request |
|---|
| 305 | | handler, opath, vpath = self.find(request.browser_url, path) |
|---|
| 306 | | |
|---|
| 307 | | # Remove "root" from opath and join it to get found_object_path |
|---|
| 308 | | request.found_object_path = '/' + '/'.join(opath[1:]) |
|---|
| 309 | | |
|---|
| 310 | | # Decode any leftover %2F in the virtual_path atoms. |
|---|
| 311 | | request.virtual_path = [x.replace("%2F", "/") for x in vpath] |
|---|
| 312 | | |
|---|
| 313 | | return handler |
|---|
| 314 | | |
|---|
| 315 | | def find(self, browser_url, objectpath): |
|---|
| 316 | | objectTrail = _cputil.get_object_trail(objectpath) |
|---|
| 317 | | names = [name for name, candidate in objectTrail] |
|---|
| 318 | | |
|---|
| 319 | | # Try successive objects (reverse order) |
|---|
| 320 | | mounted_app_roots = cherrypy.tree.mount_points.values() |
|---|
| 321 | | for i in xrange(len(objectTrail) - 1, -1, -1): |
|---|
| 322 | | |
|---|
| 323 | | name, candidate = objectTrail[i] |
|---|
| 324 | | |
|---|
| 325 | | # Try a "default" method on the current leaf. |
|---|
| 326 | | defhandler = getattr(candidate, "default", None) |
|---|
| 327 | | if callable(defhandler) and getattr(defhandler, 'exposed', False): |
|---|
| 328 | | return defhandler, names[:i+1] + ["default"], names[i+1:-1] |
|---|
| 329 | | |
|---|
| 330 | | # Uncomment the next line to restrict positional params to "default". |
|---|
| 331 | | # if i < len(objectTrail) - 2: continue |
|---|
| 332 | | |
|---|
| 333 | | # Try the current leaf. |
|---|
| 334 | | if callable(candidate) and getattr(candidate, 'exposed', False): |
|---|
| 335 | | if i == len(objectTrail) - 1: |
|---|
| 336 | | # We found the extra ".index". Check if the original path |
|---|
| 337 | | # had a trailing slash (otherwise, do a redirect). |
|---|
| 338 | | if not objectpath.endswith('/'): |
|---|
| 339 | | atoms = browser_url.split("?", 1) |
|---|
| 340 | | newUrl = atoms.pop(0) + '/' |
|---|
| 341 | | if atoms: |
|---|
| 342 | | newUrl += "?" + atoms[0] |
|---|
| 343 | | raise cherrypy.HTTPRedirect(newUrl) |
|---|
| 344 | | return candidate, names[:i+1], names[i+1:-1] |
|---|
| 345 | | |
|---|
| 346 | | if candidate in mounted_app_roots: |
|---|
| 347 | | break |
|---|
| 348 | | |
|---|
| 349 | | # We didn't find anything |
|---|
| 350 | | raise cherrypy.NotFound(objectpath) |
|---|
| | 300 | def dispatch(path): |
|---|
| | 301 | """Find the appropriate page handler.""" |
|---|
| | 302 | request = cherrypy.request |
|---|
| | 303 | handler, opath, vpath = find(request.browser_url, path) |
|---|
| | 304 | |
|---|
| | 305 | # Remove "root" from opath and join it to get found_object_path |
|---|
| | 306 | request.found_object_path = '/' + '/'.join(opath[1:]) |
|---|
| | 307 | |
|---|
| | 308 | # Decode any leftover %2F in the virtual_path atoms. |
|---|
| | 309 | request.virtual_path = [x.replace("%2F", "/") for x in vpath] |
|---|
| | 310 | |
|---|
| | 311 | return handler |
|---|
| | 312 | |
|---|
| | 313 | def find(browser_url, objectpath): |
|---|
| | 314 | objectTrail = _cputil.get_object_trail(objectpath) |
|---|
| | 315 | names = [name for name, candidate in objectTrail] |
|---|
| | 316 | |
|---|
| | 317 | # Try successive objects (reverse order) |
|---|
| | 318 | mounted_app_roots = cherrypy.tree.mount_points.values() |
|---|
| | 319 | for i in xrange(len(objectTrail) - 1, -1, -1): |
|---|
| | 320 | |
|---|
| | 321 | name, candidate = objectTrail[i] |
|---|
| | 322 | |
|---|
| | 323 | # Try a "default" method on the current leaf. |
|---|
| | 324 | defhandler = getattr(candidate, "default", None) |
|---|
| | 325 | if callable(defhandler) and getattr(defhandler, 'exposed', False): |
|---|
| | 326 | return defhandler, names[:i+1] + ["default"], names[i+1:-1] |
|---|
| | 327 | |
|---|
| | 328 | # Uncomment the next line to restrict positional params to "default". |
|---|
| | 329 | # if i < len(objectTrail) - 2: continue |
|---|
| | 330 | |
|---|
| | 331 | # Try the current leaf. |
|---|
| | 332 | if callable(candidate) and getattr(candidate, 'exposed', False): |
|---|
| | 333 | if i == len(objectTrail) - 1: |
|---|
| | 334 | # We found the extra ".index". Check if the original path |
|---|
| | 335 | # had a trailing slash (otherwise, do a redirect). |
|---|
| | 336 | if not objectpath.endswith('/'): |
|---|
| | 337 | atoms = browser_url.split("?", 1) |
|---|
| | 338 | newUrl = atoms.pop(0) + '/' |
|---|
| | 339 | if atoms: |
|---|
| | 340 | newUrl += "?" + atoms[0] |
|---|
| | 341 | raise cherrypy.HTTPRedirect(newUrl) |
|---|
| | 342 | return candidate, names[:i+1], names[i+1:-1] |
|---|
| | 343 | |
|---|
| | 344 | if candidate in mounted_app_roots: |
|---|
| | 345 | break |
|---|
| | 346 | |
|---|
| | 347 | # We didn't find anything |
|---|
| | 348 | raise cherrypy.NotFound(objectpath) |
|---|