[mod_python] providing REST style interfaces

Deron Meranda deron.meranda at gmail.com
Fri Jan 4 04:32:14 EST 2008


On Jan 3, 2008 10:56 PM, Rajarshi Guha <rguha at indiana.edu> wrote:
> Hi, I'm trying to wrap my head around a REST style interface using
> mod_python.

REST and mod_python are for the most part unrelated.  But you can
certainly use mod_python in a REST style (meaning that mod_python
doesn't get in your way of doing REST).


> My understanding of REST so far is that URI's should not
> specify specific actions (as in /service.py?action=delete).

Correct.

The main point of REST is that your URLs identify resources (think
nouns).  You'll typically have lots and lots of URLs; a different URL
for each possible different thing or item.

An opposite style is SOA (which is basically a more complex
evolution of CGI), in which the URLs name services or functions
instead (think verbs).  SOAs usually have very few URLs, but
perhaps with lots and lots of "arguments".

REST exposes things but hides the actors.
SOA exposes the actors but hides the things.

With REST, what you want to do to the resource (the verb) is
specified by the HTTP method which is part of the request protocol...
it is never encoded into the URL.  The methods can be things like
GET, PUT, DELETE, etc.  The POST method is generally
frowned upon in a REST usage, but it can be valid in certain
cases.  The same URL is used regardless of method as long as
whatever you're doing is being done to the same resource.

The whole REST style can be more involved, but it generally is
much closer to the original web/HTTP architecture.  Things like
ETags and content negotiation can be big deals in REST; while they
are blissfully ignored in most SOA approaches.

Perhaps one of the most widely used non-trivial REST applications
on Apache is Subversion (via mod_dav_svn since it's written in C and
not python).


> Thus I'd like to be able to handle a URL like
> http://www.somehost.com/service.py/descriptor/CCCC
> where CCCC is an argument to the service.

No, don't think argument to a *service*....that's an SOA mindset.
Also you most certainly don't want something like "service.py"
being visible in the URL.  A better URL would just be
http://www.somehost.com/descriptor/CCCC

Think of /descriptor/CCCC instead as being a unique *name* for some
resource or object.  Remember, with REST there is no action or verb
implied by the URL; everything is just a name for things/nouns.


> Is something like this possible in mod_python?

Yes, REST is very doable.  Since mod_python is so low-level (as
contrasted with many web "frameworks"), it doesn't force you to use
any one particular style or architecture for your applications.


> If anybody could point
> me to some examples of REST interfaces built using mod_python, it
> would be much appreciated.

If you're just trying to understand REST concepts, start with

http://en.wikipedia.org/wiki/Representational_State_Transfer

but do be aware that more and more misinformation about REST
is starting to show up as the marketing types are grabbing on the
the term as a buzzword.  Sometimes SOA-style architectures are
being described as REST even when they are technically not so.
(the latest such mislabeled example being Amazon's SimpleDB)


A very simple "hello world" like REST-style handler could be structured
similar to the following (note this is not complete code and is not tested):
The important thing to notice is that when doing REST you are usually
going to be doing some sort of switch on the req.method value.

def handler( req ):
    # Extract the resource name (the CCCC portion of the URL):
    uripath = [p for p in req.uri.split('/') if p]
    if len(uripath) != 2 or uripath[0] != 'descriptor':
        raise apache.SERVER_RETURN, apache.HTTP_NOT_FOUND
    resource_name = uripath[-1]

    # Now figure out what we want to do to the resource
    if req.method == 'GET':
        try:
            content = resource_database[resource_name]
        except KeyError:
            raise apache.SERVER_RETURN, apache.HTTP_NOT_FOUND
        req.content_type = 'application/octet-stream'
        req.write( content )
    elif req.method == 'PUT':
         content = req.read()
         resource_database[resource_name] = content
    elif req.method == 'DELETE':
         del resource_database[resource_name]
    else:
        raise apache.SERVER_RETURN, apache.HTTP_METHOD_NOT_ALLOWED

    return apache.OK

-- 
Deron Meranda


More information about the Mod_python mailing list