Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Combining REST dispatcher with the default one in a single CherryPy app

I'm trying to make CherryPy to handle request to /api via cherrypy.dispatch.MethodDispatcher() and all other request (like /) to some default dispatcher.

After reading CherryPy's doc I have no idea how to do this. They use both routing methods only separately but this is such a basic thing that I believe it has to work together.

#!/usr/local/bin/python2.7
import cherrypy


class Root(object):
    @cherrypy.expose
    def index(self):
        return 'Hello world'

class RestAPI(object):
    @cherrypy.expose
    def POST(self, blah):
        return 'ok'

cherrypy.config.update({
    'global': {
        'environment': 'production',
        'server.socket_host': '127.0.0.1',
        'server.socket_port': 8080,
    }
})


root = Root()
root.api = RestAPI()

conf = {
    '/api': {
        'request.dispatch': cherrypy.dispatch.MethodDispatcher()
    }
}

cherrypy.quickstart(root, '', config=conf)

By calling curl 'http://localhost:8080/' it gives me Hello world which is correct.
But calling curl -X POST 'http://localhost:8080/api' returns just 404.

By the way, the're eaxctly the same question without any answer CherryPy MethodDispatcher with multiple url paths.

like image 221
martin Avatar asked Jan 29 '26 08:01

martin


2 Answers

Finally I solved it. The weird thing was that I had to expose index method (and all other methods in Root class) using annotation @cherrypy.expose and not just by setting exposed = True like in RestAPI class. I don't know why.

To properly test POST handler I didn't have to pass any variables but still I had to set Content-length: 0 header.

class Root(object):

    @cherrypy.expose
    def index(self):
        return 'Hello world'


class RestAPI(object):

    exposed = True

    def POST(self):
        return 'post'

    def GET(self):
        return 'get'


cherrypy.config.update({
    'global': {
        'environment': 'test_suite',
        'server.socket_host': '127.0.0.1',
        'server.socket_port': 8080,
    }
})

cherrypy.tree.mount(Root())

cherrypy.tree.mount(RestAPI(), '/api',
    {'/':
        {'request.dispatch': cherrypy.dispatch.MethodDispatcher()}
    }
)

cherrypy.engine.start()
cherrypy.engine.block()

Proper way to test POST using cURL:

curl -X POST --header "Content-length: 0" http://localhost:8080/api

like image 97
martin Avatar answered Jan 31 '26 07:01

martin


I'm late, perhaps you already found the error. Your class RestApi must be exposed. That decorator doesn't work with MethodDispatcher.

like image 42
snahor Avatar answered Jan 31 '26 08:01

snahor



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!