In this chapter I walk through the life cycle of a web service request from the client’s point of view. Though most of this book’s code examples are written in Ruby, in this chapter I show code written in a variety of programming languages. My example throughout this chapter is the web service provided by the social bookmarking web site del.icio.us. You can read a prose description of this web service at http://del.icio.us/help/api/.
If you’re not familiar with del.icio.us, here’s a brief digressionary introduction. del.icio.us is a web site that works like your web browser’s bookmark feature, but it’s public and better-organized (see Figure 2-1). When you save a link to del.icio.us, it’s associated with your account so you can find it later. You can also share your bookmarks with others.
You can associate short strings, called tags, with a URI. Tags are versatile little suckers. They make it easy for you to find a URI later, they make it possible to group URIs together, and when multiple people tag the same URI, they create a machine-readable vocabulary for that URI.
The del.icio.us web service gives you programmatic access to your bookmarks. You can write programs that bookmark URIs, convert your browser bookmarks to del.icio.us bookmarks, or fetch the URIs you’ve bookmarked in the past. The best way to visualize the del.icio.us web service is to use the human-oriented web site for a while. There’s no fundamental difference between the del.icio.us web site and the del.icio.us web service, but there are variations:
The web site and the web service expose different URI
structures. To get your recent bookmarks from the web site, you
To get your recent bookmarks from the web service, you fetch https://api.del.icio.us/v1/posts/recent.
The web site serves HTML documents, and the web service serves XML documents. The formats are different, but they contain the same data.
The web site lets you see a lot of information without logging in or even having an account. The web service makes you authenticate for every request.
Both offer features for personal bookmark management, but the web site also has social features. On the web site, you can see lists of URIs other people have bookmarked, lists of people who have bookmarked a particular URI, lists of URIs tagged with a certain tag, and lists of popular bookmarks. The web service only lets you see your own bookmarks.
These variations are important but they don’t make the web service a different kind of thing from the web site. The web service is a stripped-down web site that uses HTTPS and serves funny-looking documents. (You can flip this around and look at the web site as a more functional web service, though the del.icio.us administrators discourage this viewpoint.) This is a theme I’m coming back to again and again: web services should work under the same rules as web sites.
Aside from its similarity to a web site, the del.icio.us web
service does not have a very RESTful design. The programmers have laid
out the service URIs in a way that suggests an RPC-style rather than a
resource-oriented design. All requests to the del.icio.us web service
use the HTTP GET method: the real method information goes into the URI
and might conflict with “GET”. A couple sample URIs should illustrate
this point: consider https://api.del.icio.us/v1/posts/add and
Though there’s no explicit
methodName variable, the
del.icio.us API is just like the Flickr API I covered in Chapter 1. The method information (“add” and
“rename”) is kept in the URIs, not in the HTTP method.
So why have I chosen del.icio.us for the sample clients in this chapter? Three reasons. First, del.icio.us is an easy application to understand, and its web service is popular and easy to use.
Second, I want to make it clear that what I say in the coming chapters is prescriptive, not descriptive. When you implement a web service, following the constraints of REST will give your clients a nice, usable web service that acts like the web. But when you implement a web service client, you have to work with the service as it is. The only alternatives are to lobby for a change or boycott the service. If a web service designer has never heard of REST, or thinks that hybrid services are “RESTful,” there’s little you can do about it. Most existing services are hybrids or full-blown RPC services. A snooty client that can feed only on the purest of REST services isn’t very useful, and won’t be for the forseeable future. Servers should be idealistic; clients must be pragmatic. This is a variant of Postel’s Law: “Be conservative in what you do; be liberal in which you accept from others.”
Third, in Chapter 7 I present a bookmark-tracking web service that’s similar to del.icio.us but designed on RESTful principles. I want to introduce the social bookmarking domain to you now, so you’ll be thinking about it as I introduce the principles of REST and my Resource-Oriented Architecture. In Chapter 7, when I design and implement a RESTful interface to del.icio.us-like functionality, you’ll see the difference.
In the sections that follow, I show you simple del.icio.us
clients in a variety of programming languages. All of these clients do
exactly the same thing, and it’s worth spelling out what that is.
First, they open up a TCP/IP socket connection to port 443 (the standard
HTTPS port) on the server at
api.del.icio.us. Then they send something
like the HTTP request in Example 2-2.
Like all HTTP responses, this one has three parts: a status code, a
set of headers, and an entity-body. In this case, the
entity-body is an XML document.
Example 2-2. A possible request to the del.icio.us web service
GET /v1/posts/recent HTTP/1.1 Host: api.del.icio.us Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=
The del.icio.us web service sends back something like the HTTP response in Example 2-3, then closes the socket connection.
Example 2-3. A possible response from the del.icio.us web service
200 OK Content-Type: text/xml Date: Sun, 29 Oct 2006 15:09:36 GMT Connection: close <?xml version='1.0' standalone='yes'?> <posts tag="" user="username"> <post href="http://www.foo.com/" description="foo" extended="" hash="14d59bdc067e3c1f8f792f51010ae5ac" tag="foo" time="2006-10-29T02:56:12Z" /> <post href="http://amphibians.com/" description="Amphibian Mania" extended="" hash="688b7b2f2241bc54a0b267b69f438805" tag="frogs toads" time="2006-10-28T02:55:53Z" /> </posts>
The clients I write are only interested in the entity-body part.
Specifically, they’re only interested in the
description attributes of the
post tags. They’ll parse the XML document
into a data structure and use the XPath expression
/posts/post to iterate over the
post tags. They’ll print to standard output
description attribute of every del.icio.us
foo: http://www.foo.com/ Amphibian Mania: http://amphibians.com/
To use any of these clients, you'll need to create a del.icio.us account. Some of the clients hard-code the strings “username” and “password”; you'll need to substitute your del.icio.us username and password.