Monday, December 15, 2008

Resource design with twisted.web

The twisted.web Python package offers several resource abstractions that make for a quality RESTful design in my opinion. Putting aside the the Python web framework requirement of "does it do everything I could possibly need ever need?" and focusing on designing an API that cohesive and easily understandable, the twisted.web package is very useful indeed.

The package offers a Resource class that serves as the base class for all resources in your application. As a developer, you will extend (and redefine if needed) this class to provide the behavior of your resources. To create a uniform API, from the RESTful perspective, we implement render_GET(), render_POST(), etc. These the value returned from these methods is the response given to the client.

Here is a trivial example of using the Resource class to implement a blogging system.
#Resource design with twisted.web

from twisted.web import server, resource, util
from twisted.internet import reactor

blog_data=[{'title':'First Entry', 'body':'First Entry Body...'},\
{'title':'Second Entry', 'body':'Second Entry Body...'}]

class Blog(resource.Resource):
def getChild(self, path, request):
return util.Redirect('index')

class BlogIndex(resource.Resource):
isLeaf=True
def render_GET(self, request):
content=''
template='<a href="/entry/%s/">%s</a><br/>'
cnt=0
for i in blog_data:
content+=template%(cnt, i['title'])
cnt+=1
return '<html>%s</html>'%(content)

class BlogEntry(resource.Resource):
isLeaf=True
def render_GET(self, request):
template='<html><h1>%s</h1><p>%s</p></html>'
blog_id=int(request.postpath[0])
blog_entry=blog_data[blog_id]
return template%(blog_entry['title'], blog_entry['body'])

blog_obj=Blog()
blog_obj.putChild('index', BlogIndex())
blog_obj.putChild('entry', BlogEntry())
reactor.listenTCP(8080, server.Site(blog_obj))
reactor.run()
Some things to note in this example:
  • The Blog resource is the root resource. It redefines the getChild() method in order to return the Redirect resource which will take us to the BlogIndex resource.
  • The BlogIndex resource simply displays a list of sample blog entries.
  • The BlogEntry resource represents a specific blog entry. This resource requires a blog id (list index). It will then display the blog entry.
  • The main program first creates the Blog resource and adds the child resources. The server is then started using the Blog resource as the root resource.