You'd think that a language with a mere handful of verbs, only two of which are widely spoken, would be easy to learn. Not
so in the case of the HTTP, though. After more than a decade, we're still sorting out how and why to use its most common verbs:
GET and POST.
This perennial issue recently flared up again when Microsoft's Dare Obasanjo noted that three popular services had got it wrong. Bloglines, Flickr, and del.icio.us all offer APIs that claim to be RESTful -- that is, to conform to the Representational
State Transfer principles of HTTP -- yet each violates those principles by allowing GET in some cases where only POST should
be allowed.
There are two reasons why a service ought to allow HTTP GET, when it's appropriate to do so. First, the resulting URL remains
visible in the browser's address (location) field. That means you can bookmark a request, post it to the Web, or send it to
someone in an e-mail. If you've ever wanted to save a search but couldn't, the reason is probably that the form unnecessarily
used POST rather than GET.
A second rationale for GET is that various systems along an HTTP pipeline may be able to cache the response.
GET's purpose, however, is only to retrieve information. When you offer a service that updates a resource, you should disallow
GET and require clients to use POST. (There are also rarely used HTTP verbs to PUT or DELETE resources, but that's another
story.) The reasoning here is twofold: You don't want users to invoke resource-altering requests from hyperlinks. And, such
requests aren't cacheable.
Why didn't Bloglines, Flickr, or del.icio.us enforce the POST restriction? I suspect it's because they wanted their APIs to
have the broadest possible reach. And from a programmer's perspective, the simplest and easiest HTTP clients are those that
use GET.
As an experiment, I sent both GET and POST requests to one of the indicted APIs using four different HTTP client technologies.
First up was Curl, the Swiss-army knife of command-line-based URL fetchers. In this case, happily, it was trivial to convert
a GET-style request to one that uses POST. I just took the part of the URL that followed the question mark and stuck it after
a -d flag. I might have had to look that up, but it's only a small step off the path of least resistance.
The same held true for Python's basic one-line URL fetcher, urllib. In this case I took what followed the URL's question mark
and attached it to the optional data argument. Again, just a small extra step.
With Perl, though, I had to take a bigger step. Perl's basic one-line URL fetcher is implemented by the LWP::Simple module.
But to switch from GET to POST, I had to construct an LWP::UserAgent object, call its post method, and encode the arguments
in a data structure.
Likewise with JavaScript. I could issue a GET request by simply assigning a URL to the location.href object. To issue a POST,
though, I had to construct a form or use the nonstandard XMLHttpRequest object.
These aren't huge obstacles. But if all toolkits made POST as accessible as GET -- or as nearly so as possible -- there would
be less incentive to misuse GET.
It should be easy to do the right thing.