Section 9.1. RESTful Service


9.1. RESTful Service

API, HTTP, REST, Standard, Universal, Web

Figure 9-1. RESTful Service


9.1.1. Developer Story

Devi's producing a public web site explaining pharmaceuticals to the public. The browser applications will pull down drug data from the server, and authorized userssuch as drug manufacturerswill be allowed to upload new information. It's envisioned that third-party applications will also connect to the web server and provide their own user interfaces. For example, pharmacies will be able to use the information via their point-of-sale systems, and doctors will have access from their specialized consulting software. Devi opts to follow a RESTful architecture for all of the services exposed on the server. This makes it easy for the browser side of her own web app to access the data and exposes services in a standardized manner.

9.1.2. Problem

How do you expose services on the Web?

9.1.3. Forces

  • The browser side of an Ajax App needs to call server-side services.

  • There might be more than one browser-side application sharing the same server-side service.

  • As well, it's often desirable for third-party applications to invoke the server-side service too.

  • With numerous different applicationsand a variety of developersaccessing the service, it ought to be easy to use.

  • Taken as a whole, the server-based services in a single "application" form an Application Programming Interface (API). It's important that services work consistently within the API.

  • The basic architecture of the Web does not force any type of service architectureany given functionality could be exposed in a wide variety of styles.

9.1.4. Solution

Expose web services according to RESTful principles. Representational State Transfer (REST) is an architectural styleor "pattern"guiding the architecture of web services. Like "Ajax" itself, "REST" is a broad term and can be broken down into many smaller patterns and idioms (enough to fill up an entire book!). The explanation here can't possibly do justice to the entire concept, but it's worthwhile being familiar with the general principles of REST. Because REST is such a large topic, be prepared for the reality that most real-world systems you'll encounter are only somewhat RESTful; they'll follow some principles and break others. Some people are now making the distinction between "High REST"sticking closely to RESTand "Low REST"following just a couple of core REST guidelines (http://lesscode.org/2006/03/19/high-low-rest/).

9.1.4.1. Motivating REST: many ways to skin a call

To motivate REST, let's consider a football service. Sufficiently authorized clients can read game records, upload new games, correct existing games, or delete games. We'll assume your backend's already written, but how would you offer it as a web service? How will client developers call it, and how will they learn about its interface?

To wit, following are a few random ways you might expose a game servicenote that these aren't necessarily RESTful!

  • GET call to a special newGame service, http://example.com/newGame?id=995&blue-baggers=150&redlegs=60

  • http://example.com/newGame, with an XML body like <game ><score team="bluebaggers">150</score><score team="redlegs">60</score></game>

  • POST or PUT call to a special newGame service, http://example.com/newGame, with a CGI-style body: id=995&bluebaggers=150&redlegs=60

  • GET call to a multipurpose gameMaintenance service, http://example.com/gameMaintenance/command=newGame&id=995&bluebaggers=150&redlegs=60

  • POST call to a multipurpose gameMaintenance service with a command-qualified URL, http://example.com/gameMaintenance/command=newGame, with an XML body like <game ><score team="bluebaggers">150</score><score team="redlegs">60</score></game>

And we could go on. And then we could look at the other functions here. The point is this: as a service designer, you have many options for representing a single function. Is that, in itself, a problem? You might argue it's not a problem at alljust choose any old option, using some darts and a blindfold if need be. Then just create the service and document its usageany competent developer will then be able to deal with it, right? That argument, however, is flawed on several counts:

  • You might assume that the browser script for your web app, and perhaps some known external clients, are the only users of your service, making it relatively easy to create and document any service. In fact, your application resides within a larger Internet ecosystem. Among the entities involved: the web browser (e.g., Firefox), which impacts issues like back-button handling and bookmarking; the web server (e.g., Apache), which impacts issues like caching and compilation; network routers and caches all along the way; robot applications such as those crawling the Web on behalf of search engines; and personal web agents that trawl through the Web on behalf of individuals. Your application will perform faster and more reliably if you follow certain conventions that are common among these entities.

  • Ideally, a service should be intuitive and self-documenting: if a service is based on familiar conventions, you have only to specify the bare minimum for a developer to be able to use it. That's simply not possible if everyone chooses alternatives according to their own personal taste. The standards-based interface usually trumps the optimized interface that's technically superior but based on unfamiliar conventions. There are thousands of web services available on the Internet; developers should be able to assess them and put them into action with as little effort as possible.

  • In the absence of any guiding principles, there's a disturbingly high likelihood you'll end up in tedious debates with colleagues over the most trivial issues, trying to arrive at an optimal API. (The blindfold and dartsor an impatient managerwould alleviate this kind of paralysis, but the other issues would still remain.)

So we've seen the argument for a convention-based approach to web services, but what's the convention? REST is one such convention, consisting of many different guidelines, that has broad industry support. Just about any functionality can be presented as a RESTful API, and by doing so, it gains the advantage of a familiar, intuitive style. Many services on the Net already follow RESTful principles, to differing degrees. Also, many real-world entities such as browsers and caches tend to assume REST. These entities work better if REST is in placea browser, for instance, might give better feedback; a cache will retain all the data that the programmer expected it to retain. And what will happen if REST is not in place? It's probably not the end of the world, but you'll find little things will go wrong and work in unexpected ways. For instance, hitting the browser's Reload button might cause a purchase order to be resubmitted. Or a cache might end up caching data it shouldn't, or it might not cache any data at all. Why these unfortunate events might occur will become clear as we learn about the RESTful principles.

9.1.4.2. Introduction to RESTful principles

So much for abstract motivation: what exactly are the RESTful principles (http://www.xfront.com/REST-Web-Services.html) all about? REST ultimately presents the server as a big blob of "resources" such as people, cars, or football games. Clients interact by inspecting and changing that state. Putting a purchase order on the server, for example, will trigger the server to affect the purchase described in the order. This contrasts with the Remote Procedural Call (RPC) approach, where the client would call a remote purchase( ) procedure. REST is based on data manipulation, RPC is based on procedural calls.

REST sees the universe as consisting of resources and operations performed on, and with, those resources. The resources and the operations can be represented as the HTTP concepts of URLs and call methods.


Resources as URLs

A resource is something like a "business entity" in modelling lingo. It's an entity you wish to expose as part of an API. Almost always, it's a noun; e.g., a person, a car, or a football game. Each resource is represented with a unique URL. So when you say a RESTful URL, it will be a thing rather than an action.


Operations as HTTP methods

REST leverages the existing HTTP methods, particularly GET, POST, PUT, and DELETE. Note that the XMLHttpRequest object, and some wrapper libraries such as ajaxCaller (http://ajaxify.com/run/testAjaxCaller/), support all these methods. If they're unfamiliar to you, consult the W3C HTTP 1.1 Specification (http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html).

URLs or URIs?

In strict HTTP parlance, there's a distinction to be made between Universal Resource Locators (URLs) and Universal Resource Identifier (URIs). URI is the more general term, as it describes a general resource. A URL is a particular type of URI that, in a somewhat vague sense, identifies a network location. You could define a protocol to represent books with URIs (e.g., isbn://12345), and those URIs wouldn't be URLs since they have no relationship with any network location; they are just a scheme for uniquely identifying objects. A string such as http://ajaxpatterns.org/RESTful_Service not only identifies an object (making it a URI), but also refers to a network location (making it a URL), one which will be used by various software to locate the resource.

Having done the Right Thing by pointing out the distinction, let me state why this pattern refers only to URLs. Most importantly, URLs are the language most developers are familiar with, even in contexts where URI is technically the appropriate term (which is arguably most of the time). Furthermore, there is confusion (http://kyseo.blogspot.com/2005/12/uri-url-urns.html) even among the RFCs that define these terms and the definitions have also shifted over time. The W3C states:

People who are well-versed in URI matters tend to use "URL" and "URI" in ways that seem to be interchangable. Among these experts, this isn't a problem. But among the Internet community at large, it is. People are not convinced that URI and URL mean the same thing, in documents where they (apparently) do. When one sees an RFC that talks about URI schemes (e.g., [RFC 2396]), another that talks about URL schemes (e.g., [RFC 2717]), and yet another that talks of URN schemes ([RFC 2276]) it is natural to wonder what's the difference, and how they relate to one another. While RFC 2396 1.2 attempts to address the distinction between URIs, URLs and URNs, it has not been successful in clearing up the confusion.

Given the potential for confusion, and the fact that most developers exclusively use the term "URL," I've opted for the pragmatic approach: you'll only see "URL" used throughout this pattern, and indeed, throughout all others.


Another way to say it is in HTTP, any request a client can make involves a URL and an HTTP method. With REST, the URL is designed to represent a noun and the HTTP method always maps to one of several standard verbs, which will be performed against that noun.

How is the URL combined with the HTTP methods in practice? Returning to the example, a game is clearly an entity in this API. So REST says we create a scheme to expose each particular game as a unique URLfor example, http://example.com/games/995.

So far, this is all pretty unequivocal. Anyone familiar with REST will always be driven to create a unique URL for each game. There might be differences of opinion about the precise naming, but the basic concept will always be the same if you follow REST. Now that we have this unique URL, we can implement many functions around it, by leveraging the standard HTTP methods (http://rest.blueoxen.net/cgi-bin/wiki.pl?RestFaq#nid1UP).

  • To get game results, the client simply issues a GET call on the URL. GET is the standard way to perform queries on the resource indicated by the URL. The response format is not dictated by REST, but XML is common due to it's self-describing and self-validating nature.

  • To delete the game, the client issues a DELETE call on the URL. DELETE is the standard way to delete a resource.

  • To update a game, the client builds a fresh game message and uploads it as the body of a PUT command. PUT is the standard way to update a resource's value.

  • To create a new game, the correct action will depend on whether the client can guess what the game's URL will be. If the service just allocates the URL arbitrarily, perhaps based on an auto-incrementing counter, then the client won't be able to guess it. When that happens, the new game is POSTed to a URL like http://example.com/games, and the server responds with the new game's URL (http://example.com/games/995). On the other hand, the client might be able to guess the URL, based on a naming convention. If the client guesses that the new game would have URL http://example.com/games/2000/9/25, then it can simply PUT the new game to that URL.

  • To perform an arbitrary transaction, you'll also use one or more of these standard methods. So maybe the client wants a way to double the winner's score. In this case, there's probably no special servicethe client just reads the old match, updates it, and PUTs it back to the server. For more complicated transactions, you might design a new resource specifically to encapsulate the request (e.g., a "purchase order" resource), and the client will then be able to POST resources like this to the server. Many businesses work the same waycontracts/orders are passed around in order to request that things are done and to verify that they've been done. See the section "Handling arbitrary transactions" later in this chapter for more details.

In summary, each HTTP method will cause a well-defined action on the resource represented by the URL it operates on. The methods can be compared to SQL commands: GET is like "SELECT," DELETE is like "DELETE," POST is like "INSERT" with an auto-generated ID, and PUT is like "INSERT OR UPDATE IF EXISTS" with an ID specified.

Again, notice how most of this is unequivocal. True, you still have to decide on a precise URL convention and message formats, but that's fairly minimal. Just by declaring "this is a REST interface," you're conveying many implicit rules to a REST-savvy developer. Inform that developer of the URL and message conventions, and they'll be able to intuit most of the API. Compare that to an ad hoc, roll-your-own API, where each detail must be explained piecemeal. Considering that there are thousands of web services out there, it soon becomes clear why REST is an attractive option.

9.1.5. RESTful principles

Let's now look at the main REST principles in more detail.

9.1.5.1. URLs reflect resources

As explained in the previous section, each resource receives a unique URL. URLs generally look like nouns.

REST doesn't tell you what names to call your resourcesthere are infinite possibilities and the choice is up to you. They'll often reflect your conceptual model of the system and look similar to your database table names.

9.1.5.2. HTTP methods reflect actions

With REST, each HTTP method indicates the kind of action to be performed. Moreover, the REST API designer doesn't have to decide what each method means, because there are only a handful of methods, and REST standardizes the meaning of eachGETs for queries, POSTs for inserts, and so on, as explained above. Notice how resource names are not standardized in the same way. Businesses have different models, so you can't standardize on those things. But REST is saying that you can indeed model the resources so that the set of required actions is standard, thus ensuring APIs are consistent with one another.

Fortunately, the standard HTTP methodswhen combined with a well-designed URL and resource schemeare enough to let a client express just about anything it needs to. It's true that in an ideal world, there would be a few extra actions to make life a bit easier. For example, it would be convenient if there was a standard LOCK action to let a client deal exclusively with a particular resource.[*] However, you can still work around this by introducing a lock resource and letting clients lock things by manipulating those resources with the standard HTTP methods.

[*] The WebDav protocol does just that. It adds several methods to HTTP, to support locking, property inspection, and moving resources around. These make REST easier to implement, but unfortunately, most Internet entities won't understand them, so it defeats one of the main purposes of REST on the open Internet.

9.1.5.3. GET for queries, and only for queries

Refining the previous point, GET calls must be read-only. When you perform a read-only query of any kind, always use GET. Conversely, when your call will affect any data on the server, use one of the other methods: PUT, POST, and DELETE all change state. There are some caveats herefor example, if issuing a query ends up leaving a log message somewhere, does that constitute a change? Technically, yes; but common sense says no, it's not a significant change to the underlying resource, so it's acceptable to log the message in response to a GET request. Just be aware that the log might not read as intended; for instance, some clients will get the content from a cache, which means no log message will occur.

The reverse problem can happen too. GET requests are often cached, but the other types of requests are not. When you perform a query with POST, you deny the possibility of caching in the browser, within the client's network, or on your own server.

If you learn nothing else about REST, be sure to learn this guideline; of all the REST conventions, this is the best known and widely applied across the net (see the sidebar "The Backpack-Accelerator Incident" in this chapter).

The Backpack-Accelerator Incident

An incident in mid-2005 highlights the importance of following "GET for queries, and only for queries" (http://radar.oreilly.com/archives/2005/05/google_web_acce_1.html). It involved the newly released Google Accelerator interacting with non-RESTful services. The accelerator is a proxy that jumps ahead of the user and prefetches each link in case the user should click on it (a non-Ajax example of Predictive Fetch [Chapter 13]). As with many other entities on the Net, it assumes services follow "GET for queries, and only for queries." The practical implication is that it indiscriminately clicks on any links.

The problem came when users logged into non-RESTful applications like Backpack (http://backpackit.com/). Because Backpack deletes items using GET calls, the acceleratorin its eagerness to run each GET queryended up deleting personal data. This could happen with regular search engine crawlers too, though the issue doesn't tend to come up because they don't usually have access to personal accounts.

Some people argued Google went too far with the REST assumption (http://www.loudthinking.com/arc/000454.html); it's one thing to assume REST for caching a prior response, but another to proactively visit links that otherwise wouldn't have not been touched, especially when those are only visible to a logged-in user. The argument has some merit, but either way, many components will continue to make the same assumption as the Google Accelerator did, making it prudent to practice "GET for queries, and only for queries."


9.1.5.4. Services should be stateless

In stateful interaction, the server remembers stuff from the past. For example, you could do this:

Greg's Browser: Give me the next game to work on.

Server: Work on game 995.

...

Greg's Browser: Here's the result: bluebaggers 150, redlegs 60.

Server: Thanks.

(Server stores "bluebaggers 150, redlegs 60" for game 995.)

The server here has an implicit conversational state; it remembers the game Greg's working on. That makes testing harder, because you have to set the whole history up to test any particular interaction. Another problem is the fragile nature of the transaction; what if Greg's browser fails and ends up requesting two different games? When Greg uploads the score, the server could easily misinterpret which game he's talking about. Also, you can't cache effectively because a query result might depend on something that happened earlier.

Furthermore, an objective of REST is to be able to switch clients at any time and receive the same result. If you switch "Greg's Browser" to "Marcia's Browser," the server will respond differently to the game result above, because it will assume Marcia's Browser is working on a different game number. While users are unlikely to switch browsers mid-conversation, other clients like caches and robots may well switch. Substitutability makes networks more scalable.

The upshot is that everything should be passed in at once. It's okay for the client to remember details about the conversationREST says nothing about the client's activitybut the server must not. The server responses should be based on the server's global state and not on the state of the conversation; i.e.:

Greg's Browser: Give me the next game to work on.

Server: Work on game 995.

...

Greg's Browser: Here's the result for Game 995: bluebaggers 150, redlegs 60.

Server: Thanks, I'll store "bluebaggers 150, redlegs 60" for Game 995.

So are cookies used at all? Yes, cookies can be used, but mainly for authentication. They should only determine whether or not the server will accept a call, by not in any way how the server will respond. If authentication fails, an appropriate response, such as a 401 (Forbidden) header, will result. If authentication succeeds, the same call will always have the same effect, independent of the client who made the call. So if Greg's Browser says "Get All Games," Greg will see exactly the same thing as if the all-powerful administrator asked for the same thing, as long as Greg's allowed to see them. If the security policy forbids Greg from seeing all games, Greg's query will be denied. What won't happen is for Greg to receive just a minimal list of his own gamesif that happened, the server would be using the cookie to determine the browser's response. To get a minimal list, the query must be explicit"Get All of Greg's Games"and of course, it must be Greg or the administrator that issues this request. If Marcia made that request, she'd get an authentication error.

An alternative to cookies is to use HTTP Basic Authentication, but this doesn't work too well in an Ajax context, because you don't have any control over the UI. The browser will typically pop up a dialog box, whereas you probably want to integrate any authentication directly into the interface, especially if using a pattern like Lazy Registration. HTTP Digest Authentication does allow more flexibility, but browser and server support is limited. Thus, while HTTP authentication is seen as "more pure," cookies are a reasonable workaround, provided you use them only for authentication.

9.1.5.5. Services should be idempotent

"Idempotent" means that once you pass a message to service, there's no additional effect of passing the same message again. Consider the deletion message, "Delete Game 995." You can send it once, or you can send it 10 times in succession, and the world will be the same either way. Likewise, a RESTful GET is always idempotent, because it never affects state. The basic conventions on GET/DELETE/PUT/POST, described earlier, are intended to support idempotency.

9.1.5.6. Services use hyperlinks

In resource representations returned by GET queries, use hyperlinks liberally to refer to related resources. With judicious use of hyperlinks, you can and should break information down. Instead of providing one massive response, include a modicum of information and point to further information using resource identifiers.

9.1.5.7. Services documents themselves

RESTful services can and should document themselves. The exact mechanism is not well-defined. But a couple of examples include:

  • Base URLs can explain how the service works. For example, in the earlier example, http://example.com/game/995 represents a particular game, but ttp://example.com/game represents no real entity, so its result could be an instructive document, in human-friendly language, with appropriate hyperlinks.

  • Error responses should also be in human-friendly language and with examples and hyperlinks.

9.1.5.8. Services constrain data formats

As an extension to the previous point, RESTful services rely on standards such as Document Type Definitions (DTDs) and XML Schema to verify data formats as well as to document what's acceptable.

9.1.5.9. Handling arbitrary transactions

The REST definition is especially geared for creatingsuch as Amazonreading, updating, and deleting (CRUD) operations. How about transactions and arbitrary actions, such as "Pause the printer" or "Email the catalogue to this user"? By definition, application-specific actions don't fit neatly with the standard REST actions. There will always be some pragmatic judgment required as to a suitably RESTful interface. A few possibilities have been mooted, with viewpoints varying (http://rest.blueoxen.net/cgi-bin/wiki.pl?VerbsCanAlsoBeNouns):

  • If it makes sense to do so, reformulate the action as a standard persistence operation. For updates that are complex or entail business logic, you can provide a read-only serviceaccessed with GET queriesto help the client compute the new state.

  • You can POST a message to the resource in questionfor example, POST a "pause" message to a URL representing the printer.

  • The server can expose a stateless "processor" resource to perform the actione.g., a printer controllerand have clients POST command-like messages there, with URLs referencing the resources to be acted upon.

9.1.5.10. Weighing Up REST

Being a broad architectural style, REST will always have different interpretations. The ambiguity is exacerbated by the fact that there aren't nearly enough standard HTTP methods to support common operations. The most typical example is the lack of a search method, meaning that different people will design search in different ways. Given that REST aims to unify service architecture, any ambiguity must be seen as weakening the argument for REST.

Another issue is portability while GET and POST are standard, you may encounter browsers and servers that don't deal consistently with DELETE, PUT, and other methods.

The main alternative to REST is RPC (see RPC Service, later). It's equally broad in definition, but the essential idea is that services are exposed at procedures. You end up POSTing into verb-like URLs such as /game/createGame?gameId=995 instead of RESTful, noun-like URLs such as /game/995. In fact, the distinction is significant enough that some service providers, such as Amazon, actually provide separate APIs for each. As a general rule, any set of services could be exposed as either REST or RPC; it's just a question of API clarity and ease of implementation. Note also there is some overlap; as discussed in the RPC Service solution, RPC can still follow certain RESTful principles.

From an implementation perspective, REST and RPC differ in that REST requires some explicit design, whereas RPC tends to follow directly from the backend software model. In the example, it's likely there will be a Game class with a createGame( ) methodthat's just how most server-side software gets done. So it's a no-brainer to tack on a /game/createGame web service that mediates between the client and the backend method. In fact, there are many frameworks that will completely automate the process for you.

With REST, there's no direct mapping between web service and backend implementationan impedance mismatch. You need to take a step back and explicitly design your API to be RESTful. If you're following feature-driven design, the API is the first thing you'll produce anyway, since the design will be "pulled" by the needs of clients, rather than "pushed" from the available technology. Once you've designed the API, the web service implementation will effectively be a kind of middleware Adaptor (see Gamma et al., 1995) to the backend services.

To summarize crudely:

  • Any web service functionality can be exposed as either REST or RPC. There's a good argument that REST APIs are somewhat clearer, though that view is far from universal.

  • REST APIs may be clearer, but they do require more design and maintenance because they tend to diverge from the backend technology. However, adaptor-style implementations of this nature are quite easy, so the overhead is not substantial and often justified in the effort to provide a clean interface, unaffected by the incidentals of the back-end implementation.

9.1.6. Real-World Examples

I'm not aware of any Ajax Apps that access a truly RESTful interface on the server side. Consequently, the example here is a public API that conforms closely to REST. Note that several prominent industry interfaces are not covered here, because though they promote themselves as RESTful, they tend to break quite a few basic principlesfor example, Amazon's REST API (http://rest.blueoxen.net/cgi-bin/wiki.pl?HowAmazonsRESTComparesWithREST). In industry parlance, REST is sometimes synonymous with "not SOAP," and it's incorrectly assumed that an interface is RESTful as long as it uses GET for reads and POST for writes.

9.1.6.1. Blogger API

Atom is a feed protocol built around RESTful principles. Blogger offers a good description on its use of Atom in its public API (http://code.blogger.com/archives/atom-docs.html). The API lets third-party applications read and change Blogger blogs. Blogger themselves could theoretically build an Ajax App that directly calls on the API.

A blog entry is one important resource in Blogger's API. For example, entry ID 1000 for user 555 "lives at" http://blogger.com/atom/555/1000. So to read that entry, just issue a GET on that URL. To change the entry there, just PUT an XML document to the same URL. To add a new entry, you don't yet know its ID, so you POST to a URL containing only the user IDfor example, http://blogger.com/atom/555. Note that each of these operations uses HTTP Basic Authentication and runs over HTTPS.

9.1.7. Code Example: AjaxPatterns RESTful Shop Demo

The Basic Shop Demo (http://ajaxify.com/run/shop/) employs an ad hoc web service to expose and manipulate store items and user shopping carts. In this demo, the cart service is refactored to become more RESTful. You can contrast this to the Refactoring Illustration in RPC Service. Note that some constraints make the RESTful service less than ideal here:

  • URLs would ideally be prefixed with http://ajaxshop.com, but because it's running within the Ajax Demo framework, the prefix is longer: http://ajaxify.com/run/shop/rest.

  • URLs would ideally avoid CGI-style variables and look like "/content/Movies" instead of /content?category=music. That's not possible here because there's no use URL-rewriting (to make the demos easy to install).

There are three resources: categories, items, and carts. GET is used to read each of these. Only carts can be modified, either by adding an item or clearing the cart. Both of these are handled by POST rather than PUT, since they are changes rather than replacements. Let's look at each service in more detail.

9.1.7.1. Reading categories list

An XML list of categories is exposed by GETting http://ajaxify.com/run/shop/categories.phtml. Here, categories is the resource and the HTTP method is GET since we're reading the resource. To avoid listing all category information here, there's a link to each specific category resource:

   <categories>     <category xlink="http://ajaxify.com/run/shop/rest/category.phtml?name=Books"> Books</category>     <category xlink="http://ajaxify.com/run/shop/rest/category.phtml?name=Songs"> Songs</category>     <category xlink="http://ajaxify.com/run/shop/rest/category.phtml?name=Movies"> Movies</category>   </categories> 

9.1.7.2. Reading an individual category

To drill down to an individual category, say "Movies," you GET http://ajaxify.com/run/shop/category.phtml?name=Movies, which provides the name and items. Since an item is defined solely by its name, and we can't perform operations on items themselves, there's no need to give it a URL.

   <category>     <name>Movies</name>     <item>Contact</item>     <item>Gatica</item>     <item>Solaris</item>   </category> 

As the system scales up, the list of all items gets excessive for someone who just wants to know the category name. So the next service provides just the items. If we want, we could then remove the list of items in the category name.

9.1.7.3. Reading cart contents

Being RESTful, we can't just access the shopping cart out using the current sessioneach operation must specify the cart's owner. The session is used here, but only for authentication.

To read the shopping cart of user 5000, we GET http://ajaxify.com/run/shop/rest/cart.phtml?userId=5000:

   <cart user>     <item>       <name>Hackers and Painters</name>       <amount>2</amount>     </item>     <item>       <name>Accidental Empires</name>       <amount>4</amount>     </item>   </cart> 

To test the authentication, visit the web app http://ajaxify.com/run/shop/rest and add a few items. Cut and paste your assigned user ID over the "5000" in the above URL. You'll be able to see your cart. Then try a different user ID, say 6000, and you'll be greeted with the following message along with a 401 (Forbidden) header:

   You don't have access to Cart for user 6000. 

9.1.7.4. Changing cart contents

Being RESTful, the cart URL remains the same whether we're manipulating or reading it. So when we make changes to user 5000's cart, we use the same URL as for reading it, http://ajaxify.com/run/shop/rest/cart.phtml?userId=5000 (which would instead end with the cleaner /cart/5000 if we could use URL-rewriting).

To update the cart, we simply PUT a new cart specification to the cart's URL. If the user's just cleared the cart, the following will be uploaded:

     <cart>     </cart> 

If the user's added an item, the browser still does the same thing: just upload the whole cart; e.g.:

   <cart user>     <item>       <name>Hackers and Painters</name>       <amount>2</amount>     </item>     <item>       <name>Accidental Empires</name>       <amount>5</amount>     </item>   </cart> 

Note that working with PUT is quite similar to working with POST. As explained in XMLHttpRequest Call (Chapter 6), XMLHttpRequest has a requestType parameter. In the example here, the details are in any event abstracted by the AjaxCaller wrapper library:

   ajaxCaller.putBody("cart.phtml?usertext/xml", cartXML); 

How to mail the cart contents is more subjective, as discussed in the "Arbitrary Actions" section in the Solution. The approach here is to post an email address to the cart URL, e.g.:

   <email-address>     ajaxmail@example.com   </email-address> 

Support for PUT and DELETE

Supporting PUT and DELETE in the server depends on the programming environment. In Java, for example, it's trivial because servlets contain the methods doPut( ) and doDelete( ) alongside doPost( ) and doGet( ) methods. PHP, on the other hand, gives special treatment to GET and POST. Not only are variables exposed with the $_GET and $_POST arrays, but the POST body is accessible with $HTTP_RAW_POST_DATA. To read the body of a PUT call, the service here has to read from the input stream, php://input (http://php.net/wrappers.php):

 function readBody( ) {     $body="";     $putdata = fopen("php://input", "r");     while ($block = fread($putdata, 1024)) {       $body = $body.$block;     }     fclose($putdata);     return $body;   } 

It's partly inconveniences like this that drive some developers to compromise and use POST as a substitute for PUT and DELETION.


9.1.8. Alternatives

9.1.8.1. RPC Service

RPC Service (see later in this chapter) is an alternative to RESTful Service, as highlighted earlier in the "Solution."

9.1.9. Related Patterns

9.1.9.1. XML Message

XML Messages (see later in this chapter) are often used as the format of a REST service's response, and sometimes its input as well. XML fits well here because it's standards-based, broadly supported and understood, self-documenting, and capable of self-verifying when used with DTDs and XML Schemas. XML Messages tend to appear as the body of PUT and POST calls as well as in responses.

9.1.9.2. XML Data Island

A RESTful transaction often involves passing a resource back and forth, with each side augmenting its state. For instance, a server can deliver an initially empty shopping cart, the client can add an item to it, the server can set the total price, and so on. Instead of transforming to and from a custom data structure, it sometimes makes sense for the browser to retain the incoming XML Messages in an XML Data Island (Chapter 11) and transform it according to the interaction.

9.1.9.3. Unique URLs

Unique URLs (Chapter 17) also relates to URL design, though they differ in scope. Unique URLs relates to the URLs of the Ajax App itself, while RESTful Service involves the URLs of web services it uses. It's sometimes said that "Ajax breaks REST" because many Ajax Apps have a single URL regardless of state. Ironically, though, Ajax actually facilitates REST by encouraging a clean API to service the browser application. As for the browser application, Unique URLs do help make an Ajax App a bit more RESTful, though that's somewhat beside the point since it's the web services that a client would want to use.

9.1.10. Metaphor

REST is often likened to Unixwith its consistent usage of pipes and filtersand to SQLwith its standard persistence and querying commandsbut can also be compared to Windows-based GUI platforms. There are standard actions like "Cut," "Paste," and "Popup Context Menu." Each object (e.g., documents, icons, and folders) accepts such actions and interprets them in a manner consistent with the action's meaning.

9.1.11. Want To Know More?

  • Roy Fielding's Dissertation that introduced the REST Concept (http://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm)

  • REST Wiki (http://rest.blueoxen.net/cgi-bin/wiki.pl)

  • Jeff Bone's breakdown of REST vs. RPC (http://www.xent.com/pipermail/fork/2001-August/002801.html)

  • Roger Costello's "Building Web Services the REST Way" (http://www.xfront.com/REST-Web-Services.html)

  • PUT versus POST discussion (http://www.megginson.com/blogs/quoderat/archives/2005/04/03/post-in-rest-create-update-or-action/)

9.1.12. Acknowledgments

Thanks to Tony Hill from the Thomson Corporation for reviewing this pattern and providing some great insights into REST.




Ajax Design Patterns
Ajax Design Patterns
ISBN: 0596101805
EAN: 2147483647
Year: 2007
Pages: 169

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net