Using REST with Ajax
Pages: 1, 2, 3
Here's the POST implementation. This has to add a new feed to the user's list of feeds:
def post(http):
"""Update a user's list of feeds with a new feed."""
username = http.user
form = util.FieldStorage(http)
suggested_feed = form["suggested_feed"]
def add_feeds():
try:
dbcon = PgSQL.connect(http.get_options()["DBURL-" + http.hostname])
curs = dbcon.cursor()
curs.execute("select add_feed('%s', '%s')" % (username, suggested_feed))
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"
http.status = HTTP_CREATED
xmlout(add_feeds, http)
return apache.OK
Here's what the HTTP spec says about POST:
The POST method is used to request that the web server accept the entity enclosed in the request as a new subordinate of the resource identified by the Request-URI.
The spec goes on to say that one specific reason for POST is to allow append operations on databases. That is exactly what this part of the feeds application does; it appends a new feed to a user's list.
I am cheating a bit here. The return from the POST is not exactly REST compliant. A 201 response indicates that the server has created a new resource, but this response is supposed to include a resource indicating a reference to the new resource (including a Location header, as in a redirect response).
However, the example simply returns the same list of feeds as returned from the GET method. In my defense, this isn't too big a heresy, and it simplifies these examples a bit. Again, it's possible to support XML output by adding content negotiation.
The last method to implement is the DELETE method. This must remove a feed specified by its ID from the user's feed list:
def delete(http):
"""Remove a feed from the user's list"""
username = http.user
todelete_match = re.match("/([0-9]+)", http.path_info)
todelete = todelete_match.groups()[0]
try:
dbcon = PgSQL.connect(http.get_options()["DBURL-" + http.hostname])
curs = dbcon.cursor()
curs.execute("select delete_user_feed('%s', %d)" % (username, int(todelete)))
except Exception, e:
# Possibly just from the proc, whatever - it failed.
http.status = apache.HTTP_NOT_FOUND
dbcon.close()
else:
dbcon.commit()
dbcon.close()
http.status = apache.HTTP_OK
return apache.OK
This is pretty obvious. It simply makes another database call to remove the specified feed.