Errata


Print Print Icon

Submit your own errata for this product.


The errata list is a list of errors and their corrections that were found after the product was released.

The following errata were submitted by our customers and have not yet been approved or disproved by the author or editor. They solely represent the opinion of the customer.


Color Key: Serious Technical Mistake Minor Technical Mistake Language or formatting error Typo Question



Version Location Description Submitted By
Printed Page xvii
2nd paragraph, the last sentance

"HTTP's weakness is its strength, its simplicity its power." maybe read "HTTP's weakness is its strength, its simplicity (is) its power."

Anonymous 
Printed Page 1
general note

The note on page 1 states "Every URI on the web is also a URL". This is not true, an URL IS an URI but not all URIs are URLs.

Anonymous 
Printed Page 2
Example 1-2

The example - Searching for books with a Ruby script - does not work with the code as is because the dependent library from http://www.caliban.org/ruby/ruby-amazon.shtml has an updated version. Since the API has changed as well, in this new version (4?), getting the example to work for a new person to Ruby is hard. I made some approximations but I don't have it 100% right. I would appreciate if the updated code is posted here.

Anonymous 
Printed Page 2
Example 1-2

The very first example - Searching for books with a Ruby script - does not work with the code as is because the dependent library from http://www.caliban.org/ruby/ruby-amazon.shtml has an updated version. Since the API has changed as well, in this new version (4?), getting the example to work for a new person to Ruby is hard. I made some approximations but I don't have it 100% right. I would appreciate if the updated code is po(a)sted here.

Anonymous 
Printed Page 2
last code snippet on page

The comment says "amazon-book-search.rb", but the next page executes "ruby amazon-search.rb".

Anonymous 
Printed Page 3
First paragraph

It says "customize the Ruby code with your Access Key ID", however the code actually takes that as a command-line argument.

Anonymous 
Printed Page 5
3rd paragraph, above title "HTTP:Documents in Envelopes"

The last sentence ... with the term "REST."

the right-quotation should be on the left side of the full stop

with the term "REST".

Anonymous 
Printed Page 6
Begining on 6th paragraph... and whole book

The authors use the term headers instead of header fields when refering to HTTP envelopes. I think they should stick to the RFC2616 terminology which is: a header is a block of header fields.

Anonymous 
Printed Page 7
3rd paragraph

"This response has 11 headers"
SHOULD BE "...10 headers"

Anonymous 
Printed Page 7
5/10ths down the page

It says "This response has 11 headers", but I actually count 10 of them.

Anonymous 
Printed Page 11
4/10ths and 6/10ths down the page

It says the method information is "doGoogleSearch" and that that's also found in the SOAPAction HTTP header. However, that header says "urn:GoogleSearchAction".

Anonymous 
Printed Page 16
Example 1-15

The example does not match the text that describes it. (Looks like the wrong HTTP snippet was used for the
example, the example matches the text in the preceding paragraph.) I believe the example should be
something like:

GET photos/tag/penguin HTTP/1.1
Host: www.flickr.com

Anonymous 
Printed Page 16,17
Example 1-15 and subsequent para

In example 1-15, the authors seem to be making an argument that Flickr's API can also be viewed in RESTful fashion despite resembling an RPC service. I believe they intended the URI in the example to read "GET /photos/tags/penguin HTTP/1.1" rather than the one shown (with the method and key/value pairs embedded).

Anonymous 
Printed Page 31
Code

I receive an authentication failure:

Authentication fails.
:/InstantRails/ruby/lib/ruby/1.8/net/http.rb:567: warning: using default DH parameters.
C:/InstantRails/ruby/lib/ruby/1.8/net/http.rb:586:in `connect': certificate verify failed
(OpenSSL::SSL::SSLError)
from C:/InstantRails/ruby/lib/ruby/1.8/net/http.rb:586:in `connect'

(username and password is provided in lowercase without square brackets and with a space in between (no
comma))

Code: See http://ruby.about.com/od/tutorials/ss/delicious_tags_4.htm provides xml output
<?xml version='1.0' standalone='yes'?>
<tags>
<tag count="1" tag="for:adobe" />
<tag count="1" tag="rails" />
<tag count="1" tag="restful" />
<tag count="2" tag="ruby" />
<tag count="1" tag="rubyonrails" />
<tag count="1" tag="system:unfiled" />
</tags>
warning: peer certificate won't be verified in this SSL session

This code also provides post by changing to posts/recent as in the example of page 31.

Anonymous 
Printed Page 31
Example 2-4

Related code:

response = open('https://api.del.icio.us/v1/posts/recent',
:http_basic_authentication => [username, password])

Error shown:

c:/ruby/lib/ruby/1.8/net/http.rb:567: warning: using default DH parameters.
c:/ruby/lib/ruby/1.8/net/http.rb:586:in `connect': certificate verify failed (Op
enSSL::SSL::SSLError)
from c:/ruby/lib/ruby/1.8/net/http.rb:586:in `connect'
from c:/ruby/lib/ruby/1.8/net/http.rb:553:in `do_start'
from c:/ruby/lib/ruby/1.8/net/http.rb:542:in `start'

On Windows XP, the ruby code does not work.

Testing the api on safari browser and the authentication works.

Anonymous 
Printed Page 31
4/10ths down the page

It says, "I've added two keyword arguments to open::method, which lets...". There should be a space between those two colons.

Anonymous 
Printed Page 32
HTTP feature matrix

Your ditto marks are not clear to me. It seems that they must be read horizontally, e.g. Net:HTTP provides Basic support for Auth methods, No support for Caching, and Yes support for Proxies.

I have always only used ditto marks vertically - I've never used them horizontally, so your matrices (not
just the one on page 32) are confusing

Anonymous 
Printed Page 36
C# code example

I've been working in C# lately, so I tried this example first. In a nutshell, https://api.del.icio.us/v1/
posts/recent failed to respond (within 10 seconds), so the example won't work. I would imagine the other
examples (in other languages) won't work either, though I haven't tried them.

Anonymous 
Printed Page 36
C# code

I wrote earlier to point out that the C# examples weren't working. I then went for a jog, and as I did it
sank in with me that the "username" and "password" must be values that I personally have to get from
deli.cio.us. This seems pretty obvious now, but it wasn't when I first tried the examples.

The book doesn't seem to say loud and clear that I need to register first. Also, IMHO the C# code should
have a comment saying that you have to sign up with deli.cio.us before trying to use the examples.

Anonymous 
Printed Page 50
End of page 50 and beginning of page 51

It says "A bucket name can only contain the characters A through Z, a through z, 0 through 9, underscore, period, and dash." However, in the previous paragraph, you suggested using names like "directory/subdirectory/file-object".

Anonymous 
Printed Page 56

You map the Amazon "Access Key ID" to @@public_key and the "Secret Access Key" to @@private key in your Authorized module.

Anonymous 
Printed Page 65
2nd paragraph

The book states that Amazon S3 uses "public-key cryptography" to authenticate requests. This is totally
wrong. S3 uses a message authentication code (MAC), which is symmetric key cryptography. That is, it uses
a secret shared by both parties: the client (S3 user) and server (Amazon).

The clues that S3 is not using public-key crypto are in the text. When mentioning your "private" key is
says "(remember, not truly private: Amazon knows it too)".

This mistake is riddled throughout chapter 3. It repeatedly calls the Access Key ID a "public key". It is
in no way a public key. It is an identifier, equivalent to a user-id or username. For instance, on page 56
in the code for "module Authorized" includes "@@public_key" & "@@private_key".

Change "public key" to "key id".
Change "private key" to "secret key".
Change "public-key cryptography" to "cryptography".

Anonymous 
Printed Page 67
3/10ths down the page

It says "# Add it to the header has." I think it meant to say "hash" ;)

Anonymous 
Printed Page 68
Example 3-20

I *think* there is an error in the signed_uri method.

The "expires" variable is carefully set but never
passed to the "signature" method (as the last argument)
where it can be passed thru to "canonical_string" to set the
Date: header. Yet on the next page (69) the need to override
the Date: header with the "expires" time is emphasized with
a direct reference to the code for "canonical_string"
in Example 3-18.

Either I missed something subtle or there's a mistake.

Mike Lutz 
Printed Page 109
Bottom list

The steps "4.) Expose a Subset of a Uniform Interface" and "5.) Design the Representations Accepted from
the Client" are not supposed to be introduced until Chapter 6 p.148 (and are not discussed in Chapter 5).

As a result later in Chapter 6 p148 the list is identical to p109 even though it is declared that two
steps have been added.

Anonymous 
Printed Page 119
3rd paragraph

This is very picky, but...

after stating in the preceding paragraph that you would use comma to separate latitude and longitude, you
go on to use a semicolon when you say:
/v1/Earth/43.9;-103.46/Mount%20Rushmore would be more precise.

Page 120 and 121 use commas, but page 123 uses a semi-colon (in the bullet points).

Page 127 uses both in the same code sample at the bottom of the page. There are similar confusions up to at least page 139.

Anonymous 
Printed Page 119
2nd paragraph

"I'm going to use a comma to separate latitude and longitude." Then the next paragraph uses semicolon "/v1/Earth/43.9;-103.46..." and semicolon runs rampant throughout chapters 5 and 6.

Shawn Hoover 
Printed Page 125
Example 5-4

The closing tag of the XML example -- "maps" -- doesn't match the opening tag "planets".

Anonymous 
Printed Page 125
Example 5-3

Says:
[{url="http://maps.example.com/Earth,description="Earth"},
{url="http://maps.example.com/Venus,description="Venus"},
...]

The JSON format requires names to be quoted and name/value pairs to be separated by colons (and not by an "equals" sign as in the example). I think the correct example should be:

[{ "url" : "http://maps.example.com/Earth", "description" : "Earth"},
{ "url" : "http://maps.example.com/Venus", "description" : "Venus"},
...]

The JSON specification is at http://json.org and a json validator can be found http://jsonlint.com

Anonymous 
Printed Page 128
First image caption

Given the established convention of including the zoom level on the portion of the URI containing the map
type, the caption for figure 5-1 on page 127 should be

/road.3/Earth/images/37.0,-95.png

instead of what is printed:

/road/Earth.3/images/37.0,-95.png

Anonymous 
Printed Page 128
3rd paragraph

Given the established convention of including the zoom level on the portion of the URI containing the map
type, the URI in paragraph 3 on page 128 should be:

http://maps.example.com/road.8/Earth/images/37.0,-95.png

instead of what is printed:

http://maps.example.com/road/Earth.8/images/37.0,-95.png

Also, the zoom level should be 3 instead of 8 since this URI is meant to be referencing the example on the
previous page.

p.s. - In the body of the last error report I sent, I mentionded page 127 instead of the correct page for
the error 128.

Anonymous 
Printed Page 129
First image caption

The image caption for Figure 5-2 on page 129 has a typo. The URI should be

/road.8/Earth/images/32.37,-86.30.png

instead of

/road.8/Earth/images/37.0,-95.png

since the former is the example it is meant to illustrate as indicated in the text that follows.

Anonymous 
Printed Page 129
First complete paragraph, third line

"32.37" -> "37.0" (twice)
"86.30" -> "95" (twice)

The coordinates given in the text are in Montgomery, AL, while the printed image claims to represent
somewhere on the KS/OK border. (The image is not quite what I see on Google maps when I ask for 37N 95W,
but at least it's plausible.)

Anonymous 
Printed Page 131
example 5-8 xml example

The given xhtml is not well formed. For example the <li> tags are not closed properly.

Anonymous 
Printed Page 131
Example 5-8

To confirm and add to an existing report: the XHTML is poorly formed. For example, the opening <dd> tag is missing for the "maps" unnumbered list.

Anonymous 
Printed Page 131
Example 5-8

To confirm and add to an existing report: the XHTML is poorly formed. For example, the opening <dd> tag is missing for the "maps" unnumbered list.

Anonymous 
Printed Page 133
Example 5-9

The "repeat" attribute on the input element (<input name="show" repeat="template") is astonishing to
people familiar with (X)HTML. It gets explained on page 136 after it's used again, but it should be
explained when first used.

Anonymous 
Printed Page 136
Note at the bottom of the page

The note explains the use of the "repeat" attribute on (X)HTML input elements. While it's true that this
is part of the nascent XHTML 5 specification, the documents in the book claim to be XHTML 1.1. Those that
use features introduced in XHTML 5 are not valid XHTML 1.1. The note makes it clear that this is a
convenient shorthand; it should also point out that the resulting documents are not useful in the real
world. (In fact, they should never be, as written; they'll need to be modified to use the XHTML 5 doc type
once it exists.)

Anonymous 
Printed Page 152
Example 6-2

I think "CGI::escape("password=#{password}") should be whatever the Ruby syntax is for "password="
concatenated with CGI::escape("#{password}"). The note that follows says that the password is form-
encoded, which is the correct behavior. If the equals sign is form-encoded, the server will see a name
that includes an encoded equals sign instead of a name=value pair.

Anonymous 
Printed Page 153
Example 6-3

'<input class="password"' -> '<input type="password"'
'<input class="submit"' -> '<input type="submit"'

Anonymous 
Printed Page 163
Last line

'<input class="submit" />' -> '<input type="submit" />'

script/plugin install acts_as_taggable

may install a version of the acts_as_taggable plugin that is broken. Use

script/plugin install http://svn.rubyonrails.org/rails/plugins/legacy/acts_as_taggable/

instead to obtain a version that works with Rails 1.2.6.
It seems that the acts_as_taggable plugin has been deprecated.

Anonymous 
Printed Page 170
Example 7-1, "create_table" commands for users and bookmarks

The table definitions for "users" and "bookmarks" are incorrect. The column "user_id" should be in the "users" table, not the "bookmarks" table. Also, in order for the join table "user_bookmarks" to work, the "bookmarks" table should have a primary key column called ""bookmark_id".

Anonymous 
Printed Page 172
mid-page

"Finally, the __bundles__ API, which lets the authenticated user group similar tags together."

"bundles/" would be more consistent with the context

Anonymous 
Printed Page 172
__/recent__?Fetch the most recently posted bookmarks, from all users.

This is about text font. It should be in italic to be consistent with the context

Anonymous 
Printed Page 174
The User Controller

It seems that the last sentence below "The User Controller" did not finish yet, as it was ended with a colon.

This should be "a path of least resistance that makes a certain kind of design very easy."

Anonymous 
Printed Page 179
under "The Leftovers"

"There's already a solution for this built into HTTP: conditional GET. I cover it briefly in __"Conditional HTTP GET"__ later in this chapter and I'll cover it in more detail in __"Conditional GET,"__ but in this chapter you'll see it implemented. By implementing conditional GET, I can give the time- and bandwidth-saving benefits of posts/update to most of of the resources I'm exposing, not just the single most expensive one."

For the first, it should be "Conditional GET" actually. For the second, it should be "Conditional GET in Chapter 8"

Anonymous 
Printed Page 182
3rd Paragraph; Example 7-3

ruby/ch7/service/config/routes.rb is missing in source archive RESTful_Web_Services_sample_code.zip

Anonymous 
Printed Page 184
1st paragraph

The book states of page 183, there would be a form encoded request parameter such as:

user[name]=leonardr&user[full-name]=Leonard%20Richardson

it then states this would end up being parsed into:

{ "user[name]" => "leonardr",
"user[full_name]" => "Leonard Richardson" }

when in fact.. it would be parsed as:

{ "user" => {"name" => "leonardr", "full_name" => "Leonard Richardson"}

Thus.. the syntax params[:user][:name] (shown in the code for the users controller on page 196) makes
sense.

The print listing, would not actually "work" if that was the actual data structure

Anonymous 
Printed Page 192
Example 7-10. application.rb continued: if_found.

The "user_id_from_username" filter was not mentioned anywhere in the book.

This should be "must_specify_user".

Anonymous 
Printed Page 196
Third line of Example 7-13

The "<screen>" element appears to be a mistake. It's never closed, and I couldn't find any such element in
the Atom spec.

Anonymous 
Printed Page 196
Example 7-13

The title tag is not closed properly.

Anonymous 
Printed Page 197
Middle of the second paragraph

"(defined in the User) model)" -> "(defined in the User model)"

Anonymous 
Printed Page 198
Example 7-15

# There was a problem saving the __bookmark__ to the database.
# Send the validation error messages along with a response
# code of 400.

should be user account actually.

Anonymous 
Printed Page 198
Second paragraph

"data validation errors fail" -> "data validation fails"

Anonymous 
Printed Page 199
End of the last paragraph of text

"index and show simply delegate to the show_bookmarks action" does not agree with the code. While index
calls show_bookmarks, show actually (and somewhat perversely) calls render_bookmarks.

Anonymous 
Printed Page 199
First paragraph

"if_found method sends a response code of 404...if the user tries to GET or DELETE a nonexistent user."

I thought DELETE was supposed to be idempotent. Hence, if you try to delete a user who no longer exists, you should get a 200. Heh, heh, bet you thought I wasn't paying attention! ;)

Anonymous 
Printed Page 202
Line 10

This appears to be a gaping security hole, allowing SQL injection if the user enters carefully crafted values instead of a valid bookmarks.user_id value. But I don't know Ruby or Rails, so perhaps I'm seeing a security issue where none actually exists. Is the "?" in the code really a placeholder for the raw user input, or does Rails automatically sanitize the input that would get spliced into this SQL query? In any event, I would suggest commenting this code to tell the reader either (a) "not to worry, this is not a SQL injection vulnerability," or (b) "we suggest you sanitize user input before inserting it into this SQL query."

Anonymous 
Printed Page 206
2nd Paragraph; Example 7-24. app/models/user.rb

Digest::SHA1.new(password).to_s

is no longer supported under Ruby 1.8.6. To work, app/models/user.rb would have to be updated to:

# Performs a one-way hash of some data.
def self.hashed(password)
Digest::SHA1.digest("string").to_s
end

Alternately some additional code in the config/environment.rb as shown in
http://coderrr.wordpress.com/2007/09/14/incompatibility-between-rails-116-and-ruby-186/
may resolve the problem.

Code in
ruby/ch3/S3lib.rb
ruby/ch8/calculate-wsse-digest.rb
may be similarly affected

Anonymous 
Printed Page 207
middle

Digest::MD5.new(new_uri).to_s doesn't work with the current version of Ruby

The correct code is:

Digest::MD5.hexdigest(new_uri)

to_s is unnecessary

Anonymous 
Printed Page 211
Top of the page

It says:

response_code = e.io.status[0].to_i
if response_code == "409" # Conflict

I'm guessing you should compare ints to ints and strings to strings.

Anonymous 
Printed Page 217
the first sentence of the 4th paragraph

"In the bookmarking service from Chapter 7, I exposed two representations of a set of bookmarks: a generic XML representation at /v1/users/leonardr/bookmarks.xml, and an __Atome__ representation at /v1/users/leonardr/bookmarks.atom.

should be "Atom" instead of "Atome"

Anonymous 
Printed Page 217
3rd paragraph

HTTP/1.1:
<http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.14>

"A server SHOULD provide a Content-Location for the variant corresponding to the response entity; especially in the case where a resource has multiple entities associated with it, and those entities actually have separate locations by which they might be individually accessed, the server SHOULD provide a Content-Location for the particular variant which is returned."

From the book:
"When a client requests one of the representation-specific URIs, you should set the Content-Location response header to /releases/104".

So, if I understand correctly, the spec says to use Content-Location to specify the "permanent" URL of the returned response entity when a canonical URL is accessed. You seem to suggest the other way around. Witch one is the right use for the header? Both?

Aki Björklund 
Printed Page 225
middle of page

"the link text indicate"
should be
"the link text indicates"

Anonymous 
Printed Page 233
3rd paragraph under URI Design

"Use semicolons when the order doesn't matter: /color-blends/red;blue."

The use of semicolons to separate unordered parameters in a URI causes IE to strip the parameters off
ServletRequestImpl.pathInfo starting at first semicolon. The remainder of the string is moved to the
ServletRequestImpl.pathParameter field, so semicolons should either be avoided or used with a caveat.

Anonymous 
Printed Page 241
the 3rd paragraph

qop-auth --> qop=auth

Anonymous 
Printed Page 245
"Printed" output for two requests, near the middle of the page

The response to the second request has a different Etag than the first. Since the second response
indicates that the entity was not modified, shouldn't the tags be the same? In a testing with a few Web
sites, I found that the Etag in a 304 response always matched the Etag in the request.

Anonymous 
Printed Page 256
the last sentence of the 5th paragraph

his --> her

Anonymous 
Printed Page 257
3rd sentence of the 2nd paragraph

authorization --> authentication

Anonymous 
Printed Page 260
fifth paragraph, sixth sentence

Lists one of the 15 possible resource relationships as "stylesteet" when it should read "stylesheet"

Anonymous 
Printed Page 279
3rd last line

The URL in the "Location" header should presumably match the URL in the text on the following page.

WRONG: Location: http://www.example.com/leonardr/photos/my-guinea-pig.atom
RIGHT: Location: http://www.example.com/leonardr/photos/20070124-1.atom

The right URL is mentioned in the middle paragraph on page 280 as the URI to which the document can be PUT
if modified. There seems to be no where else the .../20070124-1.atom URL could have come from.

Anonymous 
Printed Page 280
1st line

Delete the initial "<![CDATA[ " before the XML prolog.

I guess this is a hint that the authors wrote the book in XML, but didn't quite get the escaping right
when incuding an XML fragment in an XML document.

Anonymous 
Printed Page 287
5th "paragraph"

The "name" of the <input> element does not match the name in the resulting search URLs.

WRONG: <input name="query" type="text" />
RIGHT: <input name="q" type="text" />

as the next paragraph mentions generated URLs:
http://search.example.com/search?q=jellyfish and
http://search.example.com/search?q=chocolate
which include "q=", not "query=".

Anonymous 
Printed Page 292-4
Example 9-10, 9-12

The example wadl file for del.icio.us uses a mix of two different wadl specifications: 20061109 (https://
wadl.dev.java.net/wadl20061109.pdf) and 20060802 (https://wadl.dev.java.net/wadl20060802.pdf). The example
does not validate with either schema.

The application has the namespace for the earlier version, but the "header" value for param node's "style"
attribute is not defined in this version. It is used in example 9-10.

For the later revision, "header" is defined, but the "style" attribute is required for all params. The
param in example 9-12 would need a "style" attribute.

Anonymous 
Printed Page 292
2nd paragraph

It says "v1 inside posts inside recent", however that doesn't match the actual nesting of the tags in the XML.

Anonymous 
Printed Page 305
First complete paragraph (after Example 10-4), penultimate sentence

"SOAP messages, send over HTTP" -> "SOAP messages, sent over HTTP."

Anonymous 
Printed Page 310
Last paragraph

"It's possible to prove the originator of a given message was long after it sent, and that the message was
not modified after it was received" -> "It's possible to prove who the originator of a given message was
long after it was sent, and that the message was not modified after it was sent." (Of course, if it hasn't
been modified since it was received, it hasn't been modified since it was sent, but the recipient
generally wants to be sure that the message hasn't been tampered with before receipt.)

Anonymous 
Printed Page 311
First paragraph without a bullet

"one-off solutions are possible" -> "one-off solutions are not possible".

Anonymous 
Printed Page 333
First sentence

The text refers to "the Ajax application delicious-ajax.html," but I don't think the name is used
elsewhere. This seems to be referring to the Ajax client listed in Examples 11-1 through 11-5.

Anonymous 
Printed Page 337
Code example at the top of the page

img.setAttribute("title", image["Height"]);

Oops, that's a copy-and-paste bug ;)

Anonymous 
Printed Page 341
Second bulleted item

"app/view/welogs/new.rhtml" -> "app/view/weblogs.rhtml"

Anonymous 
Printed Page 341
Last bullet point

"PUT /weblogs/{id}: Delete a weblog."

PUT != DELETE

Anonymous 
Printed Page 351
Figure 12-2

Application box in Fig 12-2 should contain three different resources to match the subsequent code snippet: UserResource, BookmarksResource, and BookmarkResource. The (plural) BookmarksResource is missing from Figure 12-2.

Bob 
Printed Page 353
Example 12-9, near the top of the page

The indenting of the code in the if statement is inconsistent.

Anonymous 
Printed Page 357
Two thirds of the way down the page, in the paragraph following Example 12-11

"users/jacobian/tags/python" should be "users/jacob/tags/python" to match the prose that follows, or the prose should change from "jacob" to "jacobian."

Anonymous 
Printed Page 384
Last line

'414 ("Request Entity Too Large")' -> '413 ("Request Entity Too Large")'

Anonymous 
Printed Page 391
Accept-Language, 3rd paragraph

"The client sends an Accept-Charset header" should be "The client sends an Accept-Language header".

(May 2007: First Edition)

Bruce Sinclair 
Printed Page 393
First two "code" sections

It says "Content-Type: text/plain" and then "Content-Type: text/html" when really they're supposed to be the same.

Anonymous 


"Every IT generation has its seminal tome that transcends time and connects the dots in a way that no book had before it...RESTful Web Services will be, in my opinion, that book for the 2000s Web services generation."
--Thomas Beck, Beckshome.com: Thomas Beck's Blog