MiseroMCS
MiseroMCS

Reputation: 39

How can I show arbitrary pages based oy the URL requested in CherryPy?

For example, if the user were to go to localhost:8080/foobar228, I wouldn't need to hardcode in the request for foobar228 page by defining a function. I want to simply have a function that gives you the requested URL ("foobar228") and other information like GET and POST requests, and returns the HTML to be served. Any way to do this?

Upvotes: 0

Views: 393

Answers (2)

cyraxjoe
cyraxjoe

Reputation: 5741

Use the default method. Here is an example.

import cherrypy


class Root:

    @cherrypy.expose
    def default(self, *url_parts, **params):
        req = cherrypy.request
        print(url_parts)
        body = [
            'Page served with method: %s' % req.method,
            'Query string from req: %s' % req.query_string,
            'Path info from req: %s' % req.path_info,
            'Params (query string + body for POST): %s' % params,
            'Body params (only for POST ): %s' % req.body.params
        ]
        if url_parts: # url_parts is path_info but divided by "/" as a tuple
            if url_parts[0] == 'foobar228':
                body.append( 'Special foobar page')
            else:
                body.append('Page for %s' % '/'.join(url_parts))
        else:
            body.append("No path, regular page")
        return '<br>\n'.join(body)

cherrypy.quickstart(Root())

The url segments becomes the positional arguments and any query string (?foo=bar) are part of the keyword arguments of the method, also the body parameters for the POST method are included in the keyword arguments (in this case under the name params in the method definition.

Upvotes: 4

Nikos Vita Topiko
Nikos Vita Topiko

Reputation: 551

The special _cp_dispatch method

_cp_dispatch is a special method you declare in any of your controller to massage the remaining segments before CherryPy gets to process them. This offers you the capacity to remove, add or otherwise handle any segment you wish and, even, entirely change the remaining parts.

import cherrypy

class Band(object):
    def __init__(self):
        self.albums = Album()

    def _cp_dispatch(self, vpath):
        if len(vpath) == 1:
            cherrypy.request.params['name'] = vpath.pop()
            return self

        if len(vpath) == 3:
            cherrypy.request.params['artist'] = vpath.pop(0)  # /band name/
            vpath.pop(0) # /albums/
            cherrypy.request.params['title'] = vpath.pop(0) # /album title/
            return self.albums

        return vpath

    @cherrypy.expose
    def index(self, name):
        return 'About %s...' % name

class Album(object):
    @cherrypy.expose
    def index(self, artist, title):
        return 'About %s by %s...' % (title, artist)

if __name__ == '__main__':
    cherrypy.quickstart(Band())

Notice how the controller defines _cp_dispatch, it takes a single argument, the URL path info broken into its segments.

The method can inspect and manipulate the list of segments, removing any or adding new segments at any position. The new list of segments is then sent to the dispatcher which will use it to locate the appropriate resource.

In the above example, you should be able to go to the following URLs:

http://localhost:8080/nirvana/

http://localhost:8080/nirvana/albums/nevermind/

The /nirvana/ segment is associated to the band and the /nevermind/ segment relates to the album.

To achieve this, our _cp_dispatch method works on the idea that the default dispatcher matches URLs against page handler signatures and their position in the tree of handlers.

taken from docs

Upvotes: 1

Related Questions