Print

Using REST with Ajax

by Nic Ferrier
02/23/2006

This article shows how to use Ajax techniques to make web apps with REST APIs.

Everyone's talking about REST these days. Lots of people are still struggling with it, and there's good reason for that--REST is actually quite difficult to fit into the browser-based HTML Web, for two reasons:

  1. Current HTML forms support only GET and POST, not PUT or DELETE
  2. HTML forms always involve a page change

As far as I'm concerned, this is fair enough; REST is primarily a web services platform, an alternative to CORBA, SOAP, and XMLRPC, not a user interface. Still, at least some of the time, it's nice to use a REST API as the foundation for a web app. On the other hand, Ajax can be really complicated, and it always seems to involve lots of different bits of code.

That is the point of this article. REST's clean definition of an application's architecture solves at least some of the problems with Ajax; and using Ajax to a REST web app leaves the REST API uncomplicated and pure.

REST API

The best way for me to explain this is to refer to a real REST API. I recently built a multiuser ATOM/RSS aggregator. Each user can have a list of feeds (URLs, basically) and manipulate those list items. I built a simple REST API for managing the lists.

The feed aggregator needs to:

  • add a feed to the user's list
  • list the current feeds
  • remove a feed from the user's list

Clearly I could model the list of a user's feeds as a resource:

/feed

... and each feed as a subresource of that:

/feed/106

That is the great thing about REST: it's easy to work out the details of a pure REST implementation:

  • A POST to /feed will add a feed to the user's list. The POST will have to include a parameter specifying the feed URL.
  • A GET to /feed will list the feeds. A nice HTML display of the feeds might be appropriate.
  • A DELETE to /feed/67 will remove the feed with that ID.

This is all very simple, and simplicity is of course why REST is so powerful.

This code is pretty easy to do with just about any web server and language combination. I used mod_python.

Here's the main handler and GET method implementation:

import os
import re
import urllib
 
from mod_python import apache
from mod_python import util
 
def handler(http):
    if http.method == "GET":
        return get(http)
    elif http.method == "POST":
        return post(http)
    elif http.method == "DELETE":
        return delete(http)
    return apache.HTTP_NOT_ACCEPTABLE
 
def get(http):
    """Display a list of feeds."""
    username = http.user
    form = util.FieldStorage(http)
 
    def feeds():
        try:
            dbcon = PgSQL.connect(http.get_options()["DBURL-" + http.hostname])
            curs = dbcon.cursor()
            curs.execute("select id, url from get_feeds('%s')" % (username))
            result = curs.fetchone()
            while result != None:
                yield result
                result = curs.fetchone()
            dbcon.close()
        except:
            pass
        return

    http.content_type = "text/html"
    xmlout(feeds, http)
    return apache.OK

def xmlout(generator, out):
    """Use 'generator' to get the data and send it to 'out'"""
    print >>out, "<?xml version="1.0"?>"
    print >>out, "<?xsl-stylesheet href='/display-feed.xslt' version="1.0"?>"
    print >>out, "<feeds>"
    for id,url in generator():
      print >>out,
      "<feed><id>%s</id><url>%s</url></feed>" % (id, re.sub("&", "&amp;", url))
    print >>out, "</feeds>"

The GET returns an HTML page of the user's feeds. Notice that there is an XML representation in the code, so I could add content negotiation to the mix to support both XML and HTML output.

Pages: 1, 2, 3

Next Pagearrow