I’ve been working on a little project lately using Pyramid and AngularJS, for server and client side respectively. Naturally, this means that my Angular’s Controllers need to make AJAX calls to my server in order to get and send data. So, I have decided to create a little RESTful API to easily do this.

There are many benefits of using a RESTful web service – this IBM article does an excellent job of explaining them – and I wanted to leverage them for my project. What I wanted to do was:

GET    /user        - get a collection of ALL users
POST   /user        - create new user

GET    /user/name   - get the user with that 'name'
PUT    /user/name   - update user with that 'name'
DELETE /user/name   - delete user with that 'name'

Of course, name is a horrible key to use. I’ll probably end up using id instead, but for the purpose of this post, name will suffice.

In Pyramid you have the ability of mapping different request methods to the same route. For example:

from pyramid.response import Response
from pyramid.config import Configurator
from pyramid.view import view_defaults

@view_defaults(route_name='user')
class USERView(object):
    def __init__(self, request):
        self.request = request

     @view_config(request_method='GET')
     def get(self):
        return Response('get')

     @view_config(request_method='POST')
     def post(self):
        return Response('post')

     @view_config(request_method='PUT')
     def put(self):
         return Response('put')

     @view_config(request_method='DELETE')
     def delete(self):
        return Response('delete')

if __name__ == '__main__':
    config = Configurator()
    config.add_route('user', '/user')
    config.scan()
    ...

In this example, whenever the URL /user is visited, Pyramid will render the view that corresponds with the request_method.Such that,

GET  /user  => USERView.get
POST /user  => USERView.post
...

So far so good. This is just how REST works, however there’s a little caveat. If I want to get a specific user I need to do:

myapp.com/user?name=carlos

Uh-oh. This is not how I wanted to access a user. Not only that, but it also breaks one of REST design principles: Expose directory structure-like URIs. This URI, besides not being intuitive, it’s hard to remember – therefore making for a horrible API. Instead, it should look like:

myapp.com/user/carlos

In order to get the routes to look like the above, I could do:

...
@view_defaults(route_name='user')
class USERView(object):
    ...
    @view_config(request_method='GET')
    def getUser(self):
        id = self.request.matchdict['name']
        ...

    @view_config(route_name='users', request_method='GET')
    def getAllUsers(self):
        ...

    ... same methods as before ...

if __name__ == '__main__':
    config = Configurator();
    config.add_route('user', '/user/{name}')
    config.add_route('users', '/user')
    config.scan()
    ...

Notice how I added a new route config.add_route('users', '/user') which will handle getting ALL of the users. I also updated the old one to handle access to a specific user config.add_route('user', '/users/{name}').

I added a new method to the USERView class to handle the new /users route. This works, because arguments passed to @view_config decorator override those passed to @view_defaults. Meaning that getAllUsers overrides its class’ route and specifies its own. For more information about how @view_defaults works, check the Pyramid documentation.

Now, our requests do the following:

GET /user/carlos    => USERView.getUser
GET /user           => USERView.getAllUsers
POST /user          => USERView.post

Using Cornice

The fine folks at Mozilla realized that specifying multiple routes and multiple request methods every time you wanted to create a RESTful API was cumbersome. So they created a simple library to facilitate this. Enter Cornice.

from pyramid.config import Configurator
from cornice.resource import resource, view

@resource(collection_path='/user', path='/user/{name}')
class USERView(object):

    def __init__(self, request):
        self.request = request

    def collection_get(self):
        return {'users': ... }

    @view(renderer='json')
    def get(self):
        name = self.request.matchdict['name']
        ....

if __name__ == '__main__':
    config = Configurator()
    # adds cornice
    config.include("cornice")
    config.scan()
    ...

Our requests now look like:

GET /user/carlos    => USERView.get
GET /user           => USERView.collection_get
POST /user          => USERView.post

Voila! Cornice’s @resource(collection_path='/user', ...) maps to collection_get method, which is used whenever I need to get ALL of the users. While @resource(..., path='/user/{name}) maps to the corresponding get, post, put, delete method.

With Cornice, I obtained the same output with half the amount of work. What kind of sorcery is this? Actually, Cornice’s insides are doing exactly the same thing I did above!

So, guess what ended up using for my web app? Yep, I decided to go with Cornice. Besides being easier to set up and read, it provides some robust validation features – which are out of the scope of this post – which will be useful later on during development.