Search code examples
urlgetcherrypy

Cherrypy respond to unmounted or incorrect url


I have been confused by the following:

I have a class TestLink mounted to the url /testlink

class TestLink(object):
    exposed = True
    @cherrypy.expose
    @cherrypy.tools.accept(media='text/plain')
    def GET(self, var=None, **params):
        return "data:1,2\\nzelta:3,4"

if __name__ == '__main__':
    app = cherrypy.tree.mount(
        TestLink(), '/testlink',
        "test.config"
    )

And I use the Cherrypy rest dispatcher in my "test.config" file:

request.dispatch = cherrypy.dispatch.MethodDispatcher()

And when I hit start the server and hit the url "http://127.0.0.1:8080/testlink", I get the result. However, I also get result if I hit the url http://127.0.0.1:8080/testlink/x or "http://127.0.0.1:8080/testlink/anything_string". Why does this happen, shouldn't only the url "http://127.0.0.1:8080/testlink" return data?


Solution

  • Given your code example, if you try to access http://127.0.0.1:8080/testlink/foo/bar cherrypy will respond with 404 Not Found. This is because MethodDispatcher is interpreting 'foo' as value of the parameter 'var', as you specified in the signature of GET().

    Here's a modified working version of your example:

    import cherrypy
    
    config = {
        '/': {
            'request.dispatch': cherrypy.dispatch.MethodDispatcher(),
            'tools.trailing_slash.on': False,
        }
    }
    
    class TestLink(object):
        exposed = True
    
        ## not necessary, you want to use MethodDispatcher. See docs.
        #@cherrypy.expose
        @cherrypy.tools.accept(media='text/plain')
        def GET(self, var=None, **params):
            print var, params
            return "data:1,2\\nzelta:3,4"
    
    if __name__ == '__main__':
        app = cherrypy.tree.mount(TestLink(), '/testlink', config)
        cherrypy.engine.start()
        cherrypy.engine.block()
    

    Now try http://127.0.0.1:8080/testlink/foo, it will print

    foo {}
    

    whereas hitting http://127.0.0.1:8080/testlink/foo/bar will lead to 404.

    See the docs https://cherrypy.readthedocs.org/en/3.3.0/refman/_cpdispatch.html, or of course you could investigate the code in the module cherrypy/_cpdispatch.py yourself.