This is the Title of the Book, eMatter Edition
Copyright © 2007 O’Reilly & Associates, Inc. All rights reserved.
Programming REST
|
251
Now it is easy to model other URLs, shown in Table 11-5.
The /authors/ resource represents the list of all O’Reilly authors, while the resource
/authors/pavelkulchenko/ represents information about a particular author (which is
the same as /books/progwebsoap/authors/pavelkulchenko/). The resource repre-
sented by the sequence,
/authors/pavelkulchenko/books/, represents the list of books
written by a particular author and in this case, /authors/pavelkulchenko/books/prog-
websoap/ links to the same resource as /books/progwebsoap/.
Note that structure of the URI is irrelevant to client software: it always operates on a
URI as a whole. Even when relative URIs are used, they are processed according to
the algorithm described in the URI specification, without an application knowing
anything about their internal structure.
Creating Multiple Representations
Only one representation has been dealt with for now (XML), but in a real world envi-
ronment, it will definitely be a good idea to provide a broad range of representations
to satisfy the needs of different clients. Imagine that the service makes the /books/
resource available in RSS format; a user can then subscribe (using one of the many
available RSS readers) to that feed and see when new books come out. In a similar
fashion, a RSS representation for the /books/progwebsoap/ resource may return news
about a book, and for /authors/, may return information about new authors. Follow-
ing that line of reasoning, a representation for /authors/pavelkulchenko/ may return a
news feed about the particular author (books, articles and everything related). Some
of these resources may even be requested in PDF format.
Table 11-4. The resources and services thus far
Resource Service
/books/ A list of books
/books/progwebsoap/ Information about a particular book
/books/progwebsoap/authors/ A list of authors for a particular book
/books/progwebsoap/authors/pavelkulchenko/ Information about a particular author
Table 11-5. Other resources using the model
Resource Service
/authors/ List of authors
/authors/pavelkulchenko/ Information about a particular author
/authors/pavelkulchenko/books/ Books by a particular author
/authors/pavelkulchenko/articles/ Articles by a particular author
/authors/pavelkulchenko/bio The authors bio
This is the Title of the Book, eMatter Edition
Copyright © 2007 O’Reilly & Associates, Inc. All rights reserved.
252
|
Chapter 11: REST: Representational State Transfer
All this variety of formats and representations brings up an interesting question: how
does the server know what format to return for a particular request?
It was easier in the good old days. Most available resources were documents, so there
was no need for a server to choose what format to use (most resources had only one
representation). Even in the case of Common Gateway Interface (CGI) scripts, it was
the rare situation when one resource had multiple formats, and yet it was mostly the
client’s responsibility to figure out what to do with the response based on the
Content-Type or other representation metadata. As a result, browsers (which repre-
sented the vast majority of client software) became greedy: “give me everything; I am
smart enough to figure out how to deal with it.” In many cases that was true, but
now servers want to accommodate nonbrowser clients and keep the compatibility
with browser-based clients when possible.
There are three primary ways to convey desired format information:
File extensions (
"GET /image.gif")
Query string (
"GET /image?type=gif")
“Accept” header (
"GET /image" with "Accept: image/gif")
File extensions are bad for several reasons: they circumvent the content negotiation,
they trick client software into thinking that a file extension has something to do with
the content type, and they don’t work with resources that are collections of other
resources (A /books.rss/ resource would be clumsy at best). Imagine a server using the
URL /images/camel.gif and needing to upgrade it to /images/camel.png for some rea-
son. This is a problem, because of the need to update all links that point to that
resource (note that only the representation of the resource has changed; the meaning
of it stays the same). Using /images/camel as a link, the client and server can do a
content negotiation based on values of
Accept, Accept-Encoding, Accept-Language,
and
UserAgent headers, customer preferences, or even legal obligations, without
affecting other resources or client software. For example, a PDF version of a pur-
chase order can be returned in different languages based on client preferences. How-
ever, file extensions aren’t easy to avoid: many resources mirror local filesystems,
and extensions are used on the server side to provide a hint to the web server about
the content type it should return.
Query strings are only slightly better and still share the main weakness: a server
always returns the format a client asks for without leaving a room for negotiation.
A more appropriate role for the query string is to carry additional information that
may change the representation of a resource or collection of resources without
changing semantics. For instance, it can filter or sort entities in a collection:
.../books/?number=10;orderby=date
.../books/?status=outofprint

Get Programming Web Services with Perl now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.