This is the Title of the Book, eMatter Edition
Copyright © 2007 O’Reilly & Associates, Inc. All rights reserved.
256
|
Chapter 11: REST: Representational State Transfer
known, no other resource is modified, and operation is on the resource as a whole
(though it is possible and perfectly legal to update only part of the resource using a
Content-Range header).
The dialog between client and server may look like the following. Here’s the request:
PUT /authors/pavelkulchenko/bio
Content-Type: text/xml
Content-Length: NNN
<Bio xmlns="http://schema.oreilly.com/book">....</Bio>
Here’s the response:
201 Created
The client code that posts the bio using LWP::UserAgent module is given in
Example 11-3.
What if the design is extended to accept plain text messages and convert them to
XML? It is easy to change the content type from text/xml to text/plain and submit the
text version of a bio, but can a client still use the
PUT method? For purists, the answer
is probably “no,” because the
PUT method would be used for a transformation of the
representation. If transformations are allowed, it isn’t clear what to do with requests
that modify only part of the resource. For the practical implementation the answer is
probably “yes,” because requiring
POST in this case means that the operation on the
resource depends on the implementation and violates one of the REST principles:
details on how to store information on the server side must be irrelevant to the client.
Implementing a Purchase Order Service
The next example is more complex. It allows customers to submit, update, or cancel
purchase orders. The design uses /books/orders/ as the resource for purchase order
submission. This URL works as a factory of orders, creating URLs for particular
orders. Again, there are a number of choices:
Example 11-3. A REST-style PUT request using LWP::UserAgent
use LWP::UserAgent;
my $url = 'http://not-real-url.oreilly.com/authors/pavelkulchenko/bio';
my $bio = '<Bio xmlns="http://schema.oreilly.com/book">....</Bio>';
my $req = HTTP::Request->new(PUT => $url, HTTP::Headers->new, $bio);
$req->content_type('text/xml');
$req->content_length(length $bio);
my $res = LWP::UserAgent->new->request($req);
print $res->status_line;
This is the Title of the Book, eMatter Edition
Copyright © 2007 O’Reilly & Associates, Inc. All rights reserved.
Programming REST
|
257
POST the purchase order to that resource and get back a URI for the order (when
accepted).
Send a
GET request asking for an order number, then PUT the order there.
Two disadvantages of using the POST method
POST has a reliability problem if a client loses its contact with the server after POSTing
a purchase order. The order might have been accepted, and the reply was lost, but
then again the order might have been lost and should be resent. There’s no way for
the client to know what happened.
POST can also be confusing here; a client could
use POST to submit an initial order, but then PUT to update it.
Two disadvantages of the GET and PUT combination
The first disadvantage of using the GET method is that the /orders/ resource is
already taken. The system may want it to do something different, for instance to
return a list of orders for particular customer. Because of this, a different resource
(for example, /orders/new) is needed that will respond to
GET requests and return a
URL in which the order can be submitted (the only real disadvantage is that two
roundtrips are required). The second disadvantage is that now the server has a
potential race condition to address (if it doesn’t keep the generated order numbers
on the server side, it can generate the same order number for more than one cus-
tomer), and the
PUT request has to be smart enough to deal with that.
Choosing the implementation
Because the reliability problem seems to be the more interesting issue to address, the
example will implement the
GET and PUT combination.
*
For now, the actual XML
documents for purchase orders will be skipped over (you can design these as an exer-
cise), and the text will describe the interactions only to highlight the important
aspects.
First, a client receives the information about the resource where the URL and num-
ber for a new order can be obtained (
/books/progwebsoap/orders/new in this exam-
ple). This information may be included as part of the book list (the /books/
representation), or it may be published somewhere.
Following this, the client sends a
GET request to the URL and receives back a new
URL where the order should be submitted.
Here’s the request:
GET /books/progwebsoap/orders/new
* Though the network may go down during the PUT request, it is safe for a client to resubmit the message when
in doubt, because an order with the same number will be treated as the same order, whereas resending the
order with the POST message may result in duplicate orders.

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

O’Reilly members experience live online training, plus books, videos, and digital content from 200+ publishers.