MMMeeja

blog :: web development :: rest :: rest api examples

Examples Of REST Interfaces

Posted on 19 Nov 2008 by Andy - Permanent link Trackback this post Subscribe to this post Comment on this post -   

Continuing our look at Representational State Transfer interfaces, part three lets us get our hands dirty with some real-life RESTful interfaces from BrightKite and del.icio.us.

But first...

What Is A RESTful Interface?

Three articles into the series and I finally get to explain this, thanks for sticking around!

Knitted body to laptop interface

REST stands for Representational State Transfer, a term first coined in Roy Fielding’s PHd Thesis. It involves using HTTP to manipulate resources identified by URLs via a completely stateless protocol.

The URLs used are generally quite pretty. For example, an e-commerce store might sell a product identified by this URL:

http://mystore.com/products/1234

The store might have an API that supplied users with a list of products by performing a HTTP GET request on this URL:

http://mystore.com/products

The response might be supplied in an XML document, like this:

 <?xml version="1.0"?>
<products>
    <product id="1">
         <url>http://mystore.com/products/1<url>
         <name>Red widget<name>
         <description>A large, left-handed widget<description>
         <stock-level>406<stock-level>
    <product>
    <product id="2">
         <url>http://mystore.com/products/2<url>
         <name>Blue widget<name>
         <description>A small, left-handed widget<description>
         <stock-level>12<stock-level>
    <product>
<products>

Stateless Protocol

I mentioned that REST is a stateless protocol, so how can that work in an e-commerce context? People need to browse around the site and fill up their shopping basket!

Simple, a shopping basket is a resource too. Create a basket with a POST request to this URL:

http://mystore.com/baskets

And add items with POSTs like this:

http://mystore.com/baskets/1/products/2

You can use HTTP authentication to ensure that only the basket owner can view or manipulate the contents of the basket.

Enough of fabricated example shops, let’s look at some RESTful APIs that are being used on the internet today...

Delicious

One of the first mainstream web applications to offer a RESTful interface was del.cio.us with its version 2 API. We’ll be using the del.icio.us API for this example, so if you’re following along be sure to get a del.icio.us account and download CURL, the tool that we’ll be using.

Delicious Logo

We’ll begin by using the API to get a list of tags that we’ve applied to our bookmarks. Open a command line terminal and type the following (changing username & password to your values):

curl --user username:password https://api.del.icio.us/v1/tags/get

This executes an authenticated GET request for your set of tags and the output will look something like this:


<?xml version="1.0" encoding="UTF-8"?>
<tags>
  <tag count="1" tag="Action"/>
  <tag count="1" tag="Bookmarklet"/>
  <tag count="1" tag="Day"/>
  <tag count="8" tag="EC2"/>
  <tag count="1" tag="GTD"/>
  <tag count="14" tag="IE"/>
  <tag count="14" tag="Maps"/>
  <tag count="1" tag="On"/>
  <tag count="3" tag="yahoo"/>
  <tag count="1" tag="youtube"/>
<tags>

Pretty cool, no?

Now, let’s examine the REST API to add a new bookmark:

curl --user username:password -d "?url=http%3A%2F%2Fwww.mmmeeja.com%2Fblog%2F&tags=webdev%20web%20design" https://api.del.icio.us/v1/tags/add

The command above will perform a HTTP POST to add this blog :) to your del.icio.us account. Note that the url parameter is URL encoded and the tag parameter has spaces replaced by %20.

The observant reader will note that there’s something fishy about the two del.icio.us URLs we just used. The first ended in /get and the second in /add - this goes against the whole idea of using HTTP methods for REST! Yes, delicious have compromised by allowing people to use HTTP GET to create resources and the only way to do that is to break the HTTP model.

This is very common and I understand why they did it, but it’s a shame, especially when I’m using their API to teach about RESTful interfaces. Roy Fielding successfully argues that a resource should only ever have one URL no matter whether the API changes.

So, how about another API that’s a bit more compliant?

BrightKite

I had to search for a long time to find a well-known service that implemented to truly RESTful API, so hats off to BrightKite.

BrightKite Logo

If you’ve not got a BrightKite account already, you might be out of luck because its invite only at the moment, but there are plenty of invites around if you know where to look.

The BrightKite API documentation explains that people, places, notes, photos etc are all resources available via their API. Placenames are rarely unique and unambiguous so places are assigned UUIDs, so the URL for City Square, in Leeds is:

http://brightkite.com/places/b1adc0a0b65e11dd8a90003048c0801e

That URL takes you to the web page, but you can get the information in XML format by performing a HTTP GET of the URL with “.xml” on the end:

curl http://brightkite.com/places/b1adc0a0b65e11dd8a90003048c0801e.xml

You should be able to access that part of the BrightKite API without an account, so try it and check out the results. You can also get the results in JSON format by substituting “.json” for “.xml”.

Posting Notes

Places can have notes associated with them, get a list of notes attached to City Square like this:

curl http://brightkite.com/places/b1adc0a0b65e11dd8a90003048c0801e/notes.xml

In correct RESTful fashion, we can create a note with an HTTP POST. We must be an authenticated user to be allowed to do this, so replace the username and password fields in the command below:

curl -u username:password -X POST http://brightkite.com/places/b1adc0a0b65e11dd8a90003048c0801e/notes -dnote[body]=My%20lovely%20note

Finally, We Get Some REST!

That was part three of the series, only two more to go. I hope that it’s been worth getting up to speed on URLs and HTTP before we got into the REST examples.

In the next installment, I’ll cover using RESTful interfaces from software. Both client-side javascript and server-side scripts will be featured, so don’t forget to subscribe.


Creative Commons licensed photo by Bekathwia.

0 Trackbacks

9 Comments

 Brian Hendrickson said at 2008-11-19 21:08

cool articles, looking forward to the next..

I'm really enjoying this series of articles on REST APIs, although I wonder if Roy Fielding would insist that you not call it an API but an architectural style. Not really important I don't think, just noting that there is a distinction. rather than http://mystore.com/baskets/1/products/2 you would probably POST to http://mystore.com/baskets/1/products ?? thanks, looking forward to the next installment -- Brian
 MMMeeja said at 2008-11-19 21:26

Thanks Brian

Thanks for your kind comments, Brian.

As for the URL used to add items into the basket, my thinking was that basket 1 would have product 2 added to it.

As you say, it's just as valid to POST to a basket URL that doesn't contain the product ID, like you say. In that case the product ID would be supplied as a parameter (along with the item count etc).

Next installment coming soon, I promise.

 Brian Hendrickson said at 2008-11-20 06:07

Resources and URLs

Right, that makes sense because you're not CREATING new products, you're adding existing products to a basket resource.
But if you're modifying the basket resource then I think you should POST there.
That's part of the problem with REST, it's ill-defined, but that's where conversations like this help ;) Also the RESTful Web Services book by Richardson/Ruby is helpful, I was glad to be pulling it out today for the first time in a long while.
(I added some BR to this because your comment form ignores my Mac line-breaks)
 MMMeeja said at 2008-11-20 09:39

Re: Resources and URLs

Whilst you're not creating products by adding them to the basket, you are creating order items (which can subsequently be updated or deleted) so maybe a better URL for the POST would be:

http://mystore.com/baskets/1/items

As for REST being ill-defined, I agree. As always, interfaces need to be carefully designed and defined. REST helps by specifying common terms but it's not a silver bullet.

 Brian Hendrickson said at 2008-11-20 09:52

attributes of a resource

It seems like items are not real resources, but are just attributes of a basket

So I would continue to debate with you ;)

And suggest that baskets is the resource to POST to:

http://mystore.com/baskets

What do you think?
 MMMeeja said at 2008-11-20 10:18

Re: attributes of a resource

Well, I think that the store can have more than one basket but the user should only have one, so either we identify the user or the basket in the URL when modifying it. Using HTTP authentication to identify the user would break the rule of one resource per URL.

The question of whether an order item is an attribute or a nested resource of the basket is less clear cut. I would opt for the latter, because I do think that order items are real resources. They can be edited and deleted and they enter the physical realm once the order is shipped.

On top of that, treating order items as nested resources will save a load of headaches when defining an XML schema.

 

 Brian Hendrickson said at 2008-11-20 10:22

amending that..

OK, we are not _creating_ a basket so we can't POST to /baskets, I what I'm suggesting is that to add items to a basket you would PUT (or pseudo-PUT via POST aka low-rest) to http://mystore.com/baskets

Now I think i'm at least making a little bit of sense.
 Brian Hendrickson said at 2008-11-20 10:33

to nest, or not to nest?

That sounds good, so items is a nested resource of baskets, and once basket 1 has been created you can POST to

http://mystore.com/baskets/1/items

and your controller will know that the item being created is a child of basket 1

my only concern is the semantics of POSTing to an existing basket I guess, but mostly this sounds pretty nice
 MMMeeja said at 2008-11-20 10:52

Re: to nest, or not to nest?

As you say, we're not POSTing to the basket itself, but to its set of items. So a post to:

http://mystore.com/baskets/1/

would return the HTTP status 409 Conflict, but a POST to:

http://mystore.com/baskets/1/items/

should be OK.

I'll be covering the concept of "a set of X" in more detail in the final part of the series, arguing that /items/ is like an axis on a graph.

This was a great debate, BTW. Thanks.

Comment On This Article

Your Details
Save my name, email and homepage for next time
Your Comment

 

Sitemap

Copyright © 2006-2009 MMMeeja Ltd. All rights reserved.