Sometimes representations are little more than serialized data structures. They’re intended to be sucked of their data and discarded. But in the most RESTful services, representations are hypermedia: documents that contain not just data, but links to other resources.
Let’s take the search example again. If you go to Google’s directory of documents about jellyfish, you see some search results, and a set of internal links to other pages of the directory. Figure 4-3 shows a representative sample of the page.
There’s data here, and links. The data says that somewhere on the Web, someone said such-and-such about jellyfish, with emphasis on two species of Hawaiian jellyfish. The links give you access to other resources: some within the Google search “web service,” and some elsewhere on the Web:
The external web page that talks about jellyfish:
The main point of this web service, of course, is to present links
of this sort.
A link to a Google-provided cache of the external page (the
“Cached” link). These links always have long URIs that point to
Google-owned IP addresses, like
A link to a directory of pages Google thinks are related to the external page (http://www.google.com/search?q=related:www.aloha.com/~lifeguards/jelyfish.html, linked as “Similar pages”). This is another case of a web service taking a URI as input.
A set of navigation links that take you to different pages of the “jellyfish” directory: http://www.google.com/search?q=jellyfish&start=10, http://www.google.com/search?q=jellyfish&start=20, and so on.
Earlier in this chapter, I showed what might happen if HTTP was a
stateful protocol like FTP. Figure 4-2 shows the
paths a stateful HTTP client might take during a “session” with
www.google.com. HTTP doesn’t really work that
way, but that figure does a good job of showing how we use the human
web. To use a search engine we start at the home page, fill out a form
to do a search, and then click links to go to subsequent pages of
results. We don’t usually type in one URI after another: we follow links
and fill out forms.
If you’ve read about REST before, you might have encountered an axiom from the Fielding dissertation: “Hypermedia as the engine of application state.” This is what that axiom means: the current state of an HTTP “session” is not stored on the server as a resource state, but tracked by the client as an application state, and created by the path the client takes through the Web. The server guides the client’s path by serving “hypermedia”: links and forms inside hypertext representations.
The server sends the client guidelines about which states are near the current one. The “next” link on http://www.google.com/search?q=jellyfish is a lever of state: it shows you how to get from the current state to a related one. This is very powerful. A document that contains a URI points to another possible state of the application: “page two,” or “related to this URI,” or “a cached version of this URI.” Or it may be pointing to a possible state of a totally different application.
I’m calling the quality of having links connectedness. A web service is connected to the extent that you can put the service in different states just by following links and filling out forms. I’m calling this “connectedness” because “hypermedia as the engine of application state” makes the concept sound more difficult than it is. All I’m saying is that resources should link to each other in their representations.
The human web is easy to use because it’s well connected. Any experienced user knows how to type URIs into the browser’s address bar, and how to jump around a site by modifying the URI, but many users do all their web surfing from a single starting point: the browser home page set by their ISP. This is possible because the Web is well connected. Pages link to each other, even across sites.
But most web services are not internally connected, let alone connected to each other. Amazon S3 is a RESTful web service that’s addressible and stateless, but not connected. S3 representations never include URIs. To GET an S3 bucket, you have to know the rules for constructing the bucket’s URI. You can’t just GET the bucket list and follow a link to the bucket you want.
Example 4-1 shows an S3 bucket list
that I’ve changed (I added a
so that it’s connected. Compare to Example 3-5, which has no
URI tag. This is just one way of introducing
URIs into an XML representation. As resources become better-connected,
the relationships between them becomes more obvious (see Figure 4-4).
Example 4-1. A connected “list of your buckets”
<?xml version='1.0' encoding='UTF-8'?> <ListAllMyBucketsResult xmlns='http://s3.amazonaws.com/doc/2006-03-01/'> <Owner> <ID>c0363f7260f2f5fcf38d48039f4fb5cab21b060577817310be5170e7774aad70</ID> <DisplayName>leonardr28</DisplayName> </Owner> <Buckets> <Bucket> <Name>crummy.com</Name> <URI>https://s3.amazonaws.com/crummy.com</URI> <CreationDate>2006-10-26T18:46:45.000Z</CreationDate> </Bucket> </Buckets> </ListAllMyBucketsResult>