a fitful REST

Yesterday I found out about the Amazon Web Services Simple Queue Service (beta), which is an Amazon-provided generic web service, available with both SOAP and “REST” interfaces. Unfortunately, the nature of the “REST” interface is along the lines:

GET http://webservices.amazon.com/some/cgi?operation=[procedure-name]&subscriberId=[foo]&[other args]

(Note that I’m actually guessing on the ‘GET’ part, since the docs don’t specify an HTTP operation.)

I’m really happy that Amazon has opened up this service, and has provided a … more direct … interface than SOAP for interacting with it. My only gripe is that they labeled that interface “REST”. There’re at least two forms of REST that I’m aware of, and this fits neither.

I brought this up on the rest-discuss mailing list, and Jan Algermissen pointed out … basically … “talk is cheap, grousing is free; implementations will help change minds.” [my paraphrasing :)]. So, I have.

queue.py is a simple Python + Twisted web service implementing a /queue[/{name}[/{key}]] as you would expect give the HTTP operations GET, POST and DELETE.

desktop webapps

The appearance of Google’s desktop footprint is significant for two reasons. The minor reason is that it’ll be useful. The major reason is that it validates the local-web-server + browser-UI approach to applications.

bloglines API

Yesterday Bloglines announced their API, which is a RPC/REST interface to their core functionality: unread message count, subscribed feeds / items and blogrolling. While the service URL is http://rpc.bloglines.com/<whatever>, they’re also using HTTP rather directly, specifically in terms of authentication and response codes … mostly correctly even (the 403 in response to listitems should really be a 404, no?)

Open service APIs are awesome; bloglines continues to r0x0r.

I can’t help but wonder why the API isn’t:

GET /user//unread

same plaintext as currently

GET /user//subs

returns the same OPML, with full URLs for the bloglines subscription id of the form…

GET /user//subs/12345 GET /user//subs/12345?since=

returns RSS of feed, with optional date.

POST /user//subs/12345 [simple form indicating that items should be marked read]

I guess you could use GET to modify state, but why? The POST is better-suited.

GET /user//

provides a listing of all of the above, plus more?

Advantages: 1. consistency — both getitems and listsubs? Why am I calling the update RPC to get an unread item list? 2. extension — there’s now a natural resource-space for extension and growth. 3. simplicity — this seems simpler.

Also, a note to API authors: hey, buddy, it’s 2004. You really don’t need to condense sinceLastReadDate to d, or complexActionCode to n … especially when you’re about to give me back super-verbose XML. kthxbye.

In fact, I started to write a aggregation web service not too long ago with a very similar API. Frankly, I love the concept of an aggregation service, but hate web based UIs; luckily the Moz* browers have created a nice, extendable web-browsing platform, which could be an excellent interface to such a service — or really any other.

The UI of a desktop aggregator; the advantages of a web-service approach.

Maybe someday I’ll pick up the thread.

Levels of REST HTTP

Update, 2005.07.07 … I’ve neglected to mention that a long time ago, Roy Fielding corrected me about this. These are really levels of HTTP, not REST.

REST has two very different meanings, at least to me. I’ve never really seen them identified as such; Sean has hinted at it in the past, but not as clearly. Taking a cue from the various levels of Inversion of Control, I propose the following Levels of REST:

REST Type 0

GET = data-retreival; POST = everything else / arbritrary-method-invocation

Note that this is the web as experienced through most browsers [*], which only really support GET and POST. This style is characterized by “http://host.whatever.tld/path?do=save” or “?action=buyNow” or “?bite=me”. Okay, sure, both of those are GET-style URIs, but imagine them as POSTs. Now, imagine them as GETs which they usually are…

MarkB notes that the server provides the “save” of “do=save”, which is important. However … in either case, POST doesn’t mean new subordinate resource so much as “do this!”, which sucks.

REST Type 1

GET, PUT, POST, DELETE are defined as per RFC 2616, and used accordingly.

Note that the more general form of this includes WebDAV and other constrained-interface … uh … interfaces. Moreover, GET and POST have meanings beyond, simply, ways to enforce cache-control.

[*]: Thanks, Jon

graphing

The following is a response mailed to a friend of mine about Jim Webber’s post.

I generally agree with the graph, but… imagine that that graph doesn’t have time as it’s x-axis, but instead has “inverse [user] expressibility” as it’s x-axis. The y-axis then needs to become…”constraint”.

I think there’s a negative-slope graph of some other quantity — maybe “understandability” or “optimizability” or “infrastructure utility” or something that crosses the above one just /at/ REST … and maybe even just to the left of it.

The line itself is … something … maybe … “goodness” or “Quality”, and it is actually the lower bound of the two lines posited above. Thus, it peaks [just to the left of] REST…

WebDAV is just to the left of REST.

And there’s something else, with a very small number of additional verbs, just to the left of that.

But, I believe, that’s where it peaks.

To the right is the semantic fog of “do” [or "processMessage" or whatever...].

To the left is a whole layer devoted to the transfer of arbritrary verbs, which is, effectively, also a semantic fog of “do”.

Right at the peak is an area where the infrastructure is actually something the application can leverage, since the operational semantics are well defined. I think. I’m not quite sure, how, yet, but I’m trying to figure that out… :) At least, developers/intermediaries/&c. benefit from the consistency and clarity.But I do think there are definitely things that a real container can provide, there.

[For instance, one desire would be to have a first-order b[atch]GET operation, allowing the server to optimize the multiple safe/idempotent read operation.]


In the mean time, Mark Baker has posted his take , which — as usual — better expresses what I was trying to get across.