elarson’s posterous

 
« Back to blog

URL Matching and CherryPy

I don't know what it is about URLs, but I always manage to get somewhat hung up on specific patterns. For example, in Rails, the traditional :controller/:method/:id pattern just gets on my nerves. My (rather silly) issue is that resource is not being described separately from its actions. In my mind, the RESTful way to design the URL is to provide the resource URL and utilize the protocol methods to perform actions. In the case you need a special kind of action that may not easily be supported, then take analyze the idempotency of the requirement and mint yourself a new URL. It all is pretty simple.

Unfortunately, for whatever reason, the default dispatchers that come with CherryPy seem to never really allow me to easily design the URLs like this. I've tried the routes dispatcher and every time I end up getting hung up because of the rather greedy matching. The method dispatcher can be really helpful at times, but lacks the robustness to dynamically call a specific controller or function. I always end up heading back to Sylvains Selector dispatcher for CherryPy. It provides a simple way of attaching a function to a URL pattern and HTTP method. Here is an example:



controller = SomeController()
d = SelectorDispatcher()

d.add('/api/:model/:id', { 
    'GET': controller.read, 
    'PUT': controller.update, 
    'DELETE': contoller.delete 
})


While this may seem pretty verbose, it is easy enough to have controllers return their own dict for mapping the HTTP methods to the controller methods. Likewise, you can just have a controller that uses method names such as "PUT".The Selector docs have more information as well on doing partial matches and declaring optional aspects of the URL.This patterns has made sense to me for a while now and it is definitely my preferred mapping library.

UPDATE:

One thing that might be confusing here is that I'm not bashing CherryPy, Rails, Routes or any other routing tools. I'm merely pointing out how I personally like to think when coding a class that is meant to be an API. There are plenty of ways to design a web app framework to organize code. Personally, I like to have the URL router handle sending things directly to a function and Selector fits my own way of thinking. There are probably countless arguments for organizing handlers as classes, function, or a combination thereof dealing with HTTP methods or completely ignoring them. Likewise, I like a URL routing tool that lets someone take a look and get a good idea what the API is. Other people prefer to use tests with others usign comments. To each his/her own.

Loading mentions Retweet