1

The question : _cp_dispatch not getting called in cherrypy clarifies that _cp_dispatch only gets called when no property/method matches the request.

However, in my code:

import cherrypy

class A(object):
    def _cp_dispatch(self, vpath):
        raise Exception(str(vpath))

    @cherrypy.expose
    def index(self):
        return "start"

    @cherrypy.expose
    def method_1(self):
        return "method_1"

cherrypy.quickstart(A())

_cp_dispatch is called for http://127.0.0.1:8080/garbage but not for http://127.0.0.1:8080/method_1/garbage or http://127.0.0.1:8080/index/garbage

I need it to be called for these also. I can see that method_1 and index are exposed as endpoints but there isn't any endpoint for method_1/garbage. So why isn't _cp_dispatch being called?

sir_osthara
  • 154
  • 2
  • 9

1 Answers1

3

_cp_dispatched is called when no attribute matches the first segment of the url. The path method_1/garbage is parsed like:

  1. Look for an attribute named method_1
  2. If method_1 has an attribute named garbage and is exposed and callable, call it.
  3. Otherwise method_1 is expected to receive one positional argument, if not, raise an exception stating that is not found.

BTW better define a method named default instead of _cp_dispatch, that method is meant to be used to create new custom handlers to to handle the undefined path for the segment. e.g.:

@cherrypy.expose
def default(self, *args, **kwargs):
    """Catch all method"""
    return "Catch all method. {}, {}".format(args, kwargs)

And to clarify: method_1/garbage equals def method_1(self, arg_1). Remember, the default dispatcher in cherrypy behaves like a tree. If one attribute (branch) exists, that attribute has the control of the interpretation the rest of the path, you can always compose clases instead of defining single methods, as an alternative use the Routes or Method dispatchers.

cyraxjoe
  • 5,661
  • 3
  • 28
  • 42
  • Thanks for your answer, Can you please elaborate the 3rd point. Specifically what you meant by 'expecting a positional arguement'? Do you mean it expects something like method1(garbage=something)? – sir_osthara Jul 11 '17 at 19:24
  • Yeah, the name of the argument is only relevant when is passed via the "query string". For example if you have a function defined as `method1(garbage=None)`, that function could be called with this three urls: `/method`, `/method1/foo`, `/method1?garbage=bar`. In the first case, `garbage==None` , second, `garbage==foo` and third `garbage==bar`, and if you use `POST` you can sent the `garbage` field in the body and that would also be matched by the same method. Everything becomes a "parameter" from cherrypy's points of view, query string, url segments and url-encoded forms. – cyraxjoe Jul 11 '17 at 21:09
  • @cyraxjoe Is `default` a standard cherrypy method or any name will do as long as it captures all arguments? – user2297550 Oct 27 '18 at 16:33
  • Is an standard CherryPy method, take a look at this tutorial: https://github.com/cherrypy/cherrypy/blob/master/cherrypy/tutorial/tut06_default_method.py – cyraxjoe Oct 27 '18 at 20:51