Thu May 31 2007 09:22:
I've finally got the green-light for my Frank Zappa/Samuel L. Jackson crossover vehicle, Baby Snakes on a Plane.
Thu May 31 2007 09:22:
I've finally got the green-light for my Frank Zappa/Samuel L. Jackson crossover vehicle, Baby Snakes on a Plane.
When a client requests one of those URIs they can leave out one or both of the Accept- headers and still get what they want. The Content-Location response header is set to /releases/104 so that you have a URI to use when talking about the press release in general, rather than a specific version of it.
The question in the weblog entry I can't find is more or less this: what about the other two Accept- request headers, Accept-Charset and Accept-Encoding? Why don't I recommend exposing URIs like /releases/104.es.txt.gzip.UTF8?
The reason I put any special levers in the URI is because we pass around URIs, not URIs plus headers. Lots of programs and services take a URI, perform a GET on it, and expect that they got what you told them to get. One example I give in the book is the W3C HTML validator. If the only URI I exposed was /releases/104, there'd be no way to validate the Spanish version separate from the English version. If the default representation format for /releases/104 was plain text (unlikely, but this is just a thought experiment), there'd be no way to validate the HTML formats at all.
To the extent that this reason applies to some piece of information, I argue for putting a lever for it in the URI. Obviously it applies to things like which press release you want. I think it also clearly applies to the language and the data format. I think it doesn't apply to compression or character encodings. Here's a quote from page 243, in the section "Compression" where I talk about Accept-Encoding:
We can argue over what counts as a different representation (as you can see I take a fairly high-level view), but even if you think the compressed and uncompressed data are different representations, this isn't a difference that needs to go into the URI. A client can be automatically programmed to detect a compressed representation and uncompress it. The key is this ability. If it were possible to algorithmically translate any human language into another, or any data format into another, there'd be a much weaker case for extending the URI with levers for language and data format.
The same logic holds for character encodings, because a client can be automatically programmed to convert any character encoding into Unicode. The case is weaker because 1) the programming is difficult unless there happens to be a library for your language, and 2) you only get compression if you ask for it, but you get a character encoding whether you like it or not.
If you're exposing a resource in multiple encodings, and you have reason to believe that a URI-driven client might choke on your default encoding, then sure, put an encoding selection lever in the URI. But at the risk of sounding provincial (if being too cosmopolitan can be a kind of provinciality), your default encoding ought to be UTF-8 or UTF-16.
(2) Thu May 31 2007 09:35 Acceptance:
I can't find the link [UPDATE: it was Paul Sandoz], but someone posted a weblog entry that mentioned something I say in RWS about choosing different URIs for different representations. The example I (and the unknown weblog entry writer) used was a press release which is available in two languages (English and Spanish) and two data formats (HTML and plain text). The URI to this resource is /releases/104, and you can choose a representation format by setting the Accept and Accept-Language headers. But I also recommend exposing a URI for each language and format:
You probably remember that I think different representations of a resource should have distinct URIs. Why do I recommend using HTTP headers to distinguish between compressed and uncompressed versions of a representation? Because I don't think the compressed and uncompressed versions are different representations. Compression, like encryption, is something that happens to a representation in transit, and must be undone before the client can use the representation. In an ideal world, HTTP clients and servers would compress and decompress representations automatically, and programmers should not have to even think about it.
The short answer is that if I'd presented it that way, the
"REST-haters" would have an even better reason to roll their eyes: it
would look like I couldn't think of a resource-oriented way to do
transactions and I'd had to fall back to the RPC style.
Let me explain. When I read this question my immediate vision was
of a request that looked like this:
I don't know if this is what Scott had in mind, but let's
run with it. This actually won't work as is: PUT only works when the
client knows the URI of the new resource, and the URI for a
transaction resource is chosen by the server. That's a minor problem
we can fix by sending POST to a "transaction factory" resource:
My first suggestion about transactions (page 231) was: "You can
expose simple transactions as batch operations..." This is a kind of
batch operation (albeit not quite the kind I had in mind), one that affects two resources identified by URI.
The problem with this representation is that it makes the
second HTTP request look a lot like an RPC-style overloaded
POST request. It looks less like an object the client is creating, and
more like a command that /transactions is supposed to
execute.
I wouldn't go so far as to say it is overloaded POST,
because its result is a new addressable resource (the transaction
record). There's a fuzzy overlap here between RESTful and RPC-style, just
as there is with a request like "GET
/rest-endpoint?method=photos.search&tag=penguin". But in the book I don't
design URIs that look like method calls, because it sets a bad example, and for the same reason I don't
design representations that look like commands. If you looked at
that second HTTP request in isolation, you'd probably think "okay, there's no
fundamental difference between RESTful and RPC-style
transactions". When in fact there is a more elegant way to do them
that looks nothing like the RPC style.
Why do I think the way I showed in the book is more elegant?
Mainly because requests on transaction views work exactly the same way
as would non-transaction requests on the underlying resources. If you
could change an account balance at will, you'd PUT to
/accounts/savings/55. You can't, so you create a transaction
and PUT to /transactions/11a5/accounts/savings/55.
Two lesser reasons. First, you don't have to do the whole
transaction at once. You can build it up on the web service as
real-world events happen on your end, and commit when you're ready. It
works the same way as a transaction in a programming language. Second,
a transaction is an addressable resource even while in
progress. Multiple authenticated clients can inspect or
collaborate on a transaction, and the rules for avoiding conflicts are
the same as on the rest of the web (eg. If-Unmodified-Since).
That leaves the question of efficiency. You can package multiple
operations into a single HTTP request for efficiency's sake. But if a
single operation is an HTTP method applied to a URI, that's what you
should package. If the uniform interface is good enough for
one-at-a-time operations, it's good enough for descriptions of batch
operations. You don't need an application-specific vocabulary like the
one I came up with reflexively. A simple, uniform vocabulary will
do; something like this:
(You could probably use an XML document that contains a series of
SOAP envelopes!)
I think POSTing that representation to a transaction factory
satisfies Scott's original criteria: "create a transaction resource that
included both checking & savings account as well as the transfer
amount... defining the resource as XML in the request body". And it
would make a good addendum to the "Transactions" section, once the
reader has seen which HTTP requests underly the transaction. But
presenting it instead of the multi-request version would
probably be confusing, and would certainly give the impression that
there was no RESTful way to make those HTTP requests one at a time.
Thu May 31 2007 17:26 Transactions of the Transaction Society:
Sam and I got a question from reader Scott Davidson about the famous RESTful
transaction design (quoted at length by Jon Udell here,
in case you bought so many copies of the book that you're now
deadlocked trying to decide which one to look up page 231 in). I think
it's worth responding to at length:
I'm perplexed why your transaction example in Chap. 8 didn't simply
create a transaction resource that included both checking & savings
account as well as the transfer amount w/ a PUT (defining the resource
as XML in the request body). Then you could simply call
/transaction/11a5/commit or even just assume that this is a request to
commit the transaction by default and avoid the 2nd call altogether.
Is there a specific reason why it was not done this way? I can already
see the "REST-haters" rolling their eyes to this three request/response
transaction pattern.
PUT [some URI] HTTP/1.1
Content-Type: application/xml
<transaction type="transfer" amount="50.00">
<source href="/accounts/checking/11" />
<destination href="/accounts/savings/55" />
</transaction>
POST /transactions HTTP/1.1
Content-Type: application/xml
<transaction type="transfer" amount="50.00">
<source href="/accounts/checking/11" />
<destination href="/accounts/savings/55" />
</transaction>
<transaction>
<request method="PUT" target="/accounts/checking/11">
<representation>balance=150</representation>
</request>
<request method="PUT" target="/accounts/savings/55">
<representation>balance=250</representation>
</request>
</transaction>
(6) Thu May 31 2007 18:52 Category:Fictional Fictions:
I feel a sense of unease whenever I'm revising a story and I change what happens. I feel like there's some residual sense in which A "really" happened and B is a lie to cover it up. But if the story is published, most people will think B "really" happened and A will seem a curiosity if they know about it at all. How do we discuss different kinds of fictional events? Lay some vocabulary on me.
(1) Thu May 31 2007 22:29:
A set of algorithms for experimental travel. "Arrange to spend a weekend away with your partner. Travel to your chosen destination by different means and don't arrange a meeting time or place. Now look for each other..." There's a lot of overlap with the Lonely Planet guide, which I've had my traveling eye on.
![]() | Unless otherwise noted, all content licensed by Leonard Richardson under a Creative Commons License. |