5

i'd like to use cherrypy but i don't want to use the normal dispatcher, i'd like to have a function that catch all the requests and then perform my code. I think that i have to implement my own dispatcher but i can't find any valid example. Can you help me by posting some code or link ?

Thanks

wezzy
  • 5,897
  • 3
  • 31
  • 42

3 Answers3

13

make a default function:

import cherrypy

class server(object):
        @cherrypy.expose
        def default(self,*args,**kwargs):
                return "It works!"

cherrypy.quickstart(server())
Jacob Stoner
  • 1,113
  • 9
  • 10
2

What you ask can be done with routes and defining a custom dispatcher

http://tools.cherrypy.org/wiki/RoutesUrlGeneration

Something like the following. Note the class instantiation assigned to a variable that is used as the controller for all routes, otherwise you will get multiple instances of your class. This differs from the example in the link, but I think is more what you want.

class Root:
    def index(self):
        <cherrpy stuff>
        return some_variable

dispatcher = None
root = Root()

def setup_routes():
    d = cherrypy.dispatch.RoutesDispatcher()
    d.connect('blog', 'myblog/:entry_id/:action', controller=root)
    d.connect('main', ':action', controller=root)
    dispatcher = d
    return dispatcher

conf = {'/': {'request.dispatch': setup_routes()}}

Hope that helps : )

fellyn
  • 41
  • 3
  • am i wrong or this solution assume that i already know all the available path when cherrypy start ? this is not my case, i have to query the database every time to find if a particular url is valid and what to display – wezzy Jul 16 '11 at 15:48
  • Yes it does assume that you already know the paths that you are serving from. If you have those paths in a database you could construct the paths at app startup in the dispatch function. Its hard to give you a full solution without knowing more but you should be able to loop through a cursor and point all paths to your instantiated class. Hopefully your paths are not dynamic. This solution would require an app restart for every path change. – fellyn Jul 18 '11 at 18:54
1

Here's a quick example for CherryPy 3.2:

from cherrypy._cpdispatch import LateParamPageHandler

class SingletonDispatcher(object):

    def __init__(self, func):
        self.func = func

    def set_config(self, path_info):
        # Get config for the root object/path.
        request = cherrypy.serving.request
        request.config = base = cherrypy.config.copy()
        curpath = ""

        def merge(nodeconf):
            if 'tools.staticdir.dir' in nodeconf:
                nodeconf['tools.staticdir.section'] = curpath or "/"
            base.update(nodeconf)

        # Mix in values from app.config.
        app = request.app
        if "/" in app.config:
            merge(app.config["/"])

        for segment in path_info.split("/")[:-1]:
            curpath = "/".join((curpath, segment))
            if curpath in app.config:
                merge(app.config[curpath])

    def __call__(self, path_info):
        """Set handler and config for the current request."""
        self.set_config(path_info)

        # Decode any leftover %2F in the virtual_path atoms.
        vpath = [x.replace("%2F", "/") for x in path_info.split("/") if x]
        cherrypy.request.handler = LateParamPageHandler(self.func, *vpath)

Then just set it in config for the paths you intend:

[/single]
request.dispatch = myapp.SingletonDispatcher(myapp.dispatch_func)

...where "dispatch_func" is your "function that catches all the requests". It will be passed any path segments as positional arguments, and any querystring as keyword arguments.

fumanchu
  • 14,419
  • 6
  • 31
  • 36
  • 1
    Hm, but that won't collect config for you from the Application per URI. I'll see if I can improve the above tomorrow. – fumanchu Jul 12 '11 at 06:23
  • uh maybe i'm too newbie but i can't get your example working, see this https://gist.github.com/1086473 if i call 127.0.0.1:8080 i get the "hello world" message but what i want is handle other urls that i can't determine at startup and the test() function never get called. Is it possible to catch 404 exceptions to handle all the paths ? – wezzy Jul 16 '11 at 15:53
  • Sorry about that. I got the vpath messed up. I've fixed the above. – fumanchu Jul 16 '11 at 16:07
  • i've replaced the code in the gist with the new version of your class but it acts exactly like before – wezzy Jul 16 '11 at 16:18