Let me preface this rant with a declaration:
Web services are great.
... but, I won’t beat around the bush. I hate REST. REST is the most asinine attempt to ignorantly hand-jam arrogant assumptions about my desires as a programmer into the most unsuited mechanism possible: a transport protocol.
Let’s start with HTTP. No matter what the authors’ intent, today HTTP is simply not much more than a high level transport protocol (I use “authors’ intent” because no matter what anyone tells you, HTTP as we know it today wasn’t conceived and formulated into specification by Tim Berners-Lee. His team’s initial specification was sane and only included one verb: GET). HTTP effectively is a client/server request/response mechanism perfectly suited for a browser to request a resource from a server. PERIOD. And to all those who would say, “but no, it’s so much more.” I would say, you’re full of crap. It’s not. Stop. No, really... Stop. 99.9999% of all HTTP traffic (I’d tack 10 more ‘9’s to the end of that number to be more accurate, but you get my point) is simply browser requests for a resource / server responses with the resource. And that’s OK. So just stop. HTTP does a good job assuring a persistent URI reference to, and means to retrieve, a web resource; it allows me to assume a resource will remain at a specific location such that I can reference that resource from another resource, and now we have... The World Wide Web! I love HTTP. I would even say I love both GET and POST. What I don’t love is REST trying to cram my entire programming model into 9 verbs. Now don’t get me wrong, I think adding other verbs (besides GET) to maintain resources on the web is fine-- static HTML pages, images, XSD specs, even iCal through WebDAV is almost coherent. But trying to expose a public RPC interface for an entire complex software system architecture via 9 verbs is the closest thing to insane I can imagine. It’s like trying to hack a programming paradigm out of the TCP packet header control bits! If URG is high then my calendar appointment is very important. If ACK is low, then I’m denying your friend request. It’s INSANE!
Here’s the deal. We’re all complex programmers. We dream up a lot of crazy crap. Don’t try to shove our creativity into your world of CRUD (Create, Read, Update, Delete). We’re not simply storing stuff on the web; no, we are doing stuff.
I mentioned before that GET and POST have their merits. GET provides me with a nice, human-readable URL which can be used to repeat a simple request:
Great. I know I’m referencing arbitrarySubcontext on server someserver.com and sending 2 parameters. Wonderful.
What if the information in the parameters is big, and useless for human viewing-- like a uuencoded image, or the entire body of an email message. Would I want that as part of the address in human sight? Would I likely want to repeat that exact same request and receive the exact same response? No, probably not; hence, POST.
But what about the other 7 HTTP verbs?
HEAD, PUT, DELETE, TRACE, OPTIONS, CONNECT, PATCH
If you can accurately describe more than 2 of the above HTTP verbs, then you probably endorse REST. Enough said.
Sure, we all get DELETE. Some of us get PUT, but I’d bet hard cash you won’t get 2 identical answers when you ask us the difference between PUT and POST. HEAD, TRACE, OPTIONS, CONNECT? Transport verbs for special cases or querying metadata! PATCH is a nice nerdy Computer Science addition to U in CRUD.
So, basically we’re left with GET, PUT, POST, and DELETE to map my entire complex system software architecture into. Back to my earlier rant: we don’t simply STORE THINGS... we DO THINGS! My nouns don’t just exist! They breath and join and search and jump and fart! They DO THINGS!
The world of Computer Science has seen many leaps in design. We went from Procedural Programming, to Object Oriented Programming, to Functional Programming (we kindof skipped Aspect Oriented Programming) and I’m sure in between I’m missing some favorites which you’ll all tell me about. But hear me clearly. RPC has been around and seen umpteen iterations, and with the exception of SOAP, REST is the absolute worst incarnation! Summarily, REST is:
RPC + Object Oriented Programming stripped down to only allow classes 4 methods (GET, PUT, POST, DELETE).
Imagine if I asked you to design a complex system using an Object Oriented design pattern restricting your objects to 4 methods.
Now, here’s the sad thing. REST advocates think REST is cool!
They think they’ve discovered some hidden knowledge the rest of us (no pun intended) haven’t figured out! And they go around jacking with apache config files and playing in their little console windows running curl, hand crafting HTTP headers and they think it’s cool! I hear things like: The Web was originally built to handle all of this, but no one ever uses it! No frickin’ duh. No one ever uses it because it sucks!
Look, web services in moderation (that’s another rant for a later time) are cool. Noun/Verb URL semantics are a useful convention. But please, please, just please stop trying to derive some closest-to-CRUD meaning from each method in my complex software system and pigeon hole that into the closest representation of GET, PUT, POST, or DELETE! It adds nothing to the usefulness of the implementation and only takes away functionality.
“How does it take away functionality?” you might ask. Well, let me tell ya 2 ways. Just about all dynamic web content programming systems easily support POST and GET and most support retrieving provided parameters in the same way for either:
PHP - $_REQUEST['param1']
JSP - request.getParameter("param1");
ASP - OK, so ASP is stupid:
.Form for POST? Really? What if my <form method="get">?
All browsers support GET. duh.
What does this mean? Well, it means that I can easily program all my web services to accept both GET and POST (normally without changing any of my server side code, to seamlessly accept either), and can test it simply with my browser… if I use a sane noun/verb URL convention like:
I can easily handle these without any web server tweaks, and using my server side environment de jour easily with, e.g.,
I can add any number of verbs (methods) to my nouns (classes) because they are simply the last segment of my URL path, by convention-- the penultimate segment being the noun-- all providing a relatively straightforward class/method approach to exposing as web services most software system. It's easy to understand. Easy to discover and browse and poke around by a potential user by simply turning on folder listings. Adding "usage" output for endpoints when no parameters are passed can self document the API. I can test these all out with my web browser. I can demo these to would-be users of my API in a browser and give them examples for a method call simply by giving them example URLs. Easy peasy-- except I hate peas. Mushy peas are the worst. They remind me of baby food. Silly Brits. You know they try to eat non-mushy peas balanced on the backs of their forks! That’s almost as insane as REST! Almost.
Now, imagine the above example as a REST implementation:
HTTP Type: GET;
Header: Accept: application/json
HTTP Type: GET;
Header: Accept: text/xml;
HTTP Type: DELETE
The first URL is not obviously a search call and probably ambiguous if I wanted to simply list all widgets-- hack. Clients wishing to designate the response format must construct an HTTP Header. Delete requires the complexity of handling an HTTP type other than the commonly supported GET or POST. The recall and sendpromotion methods do something other than simple CRUD on my object and since REST is built around the assumption that I wish to merely perform persistence (Create, Read, Update, Delete) and that actions on my nouns will do nothing more, then if I do have special server-side code to do something more, the client certainly wouldn’t expect it! Every one of these methods requires jacking around with my web server to handle URL rewriting, so I can basically convert the url-part ‘widget/1’ into (what it should be) a parameter, ‘widgetID=1’, and then choosing a different service handler based on the HTTP method. None of this can be tested or demoed from a browser and all require you to drop to a shell and construct by hand HTTP Headers and Bodies and to become intimate with cryptic curl arguments.
Why? Well because the Web was made to handle all this! What a bunch of hog crap.
Look, it takes a sane, unenlightened human being about 2 minutes to come up with a useful OO-to-web-services mapping:
Sure, it doesn’t handle stateful objects, but neither does REST “because the web should be stateless”-- yeah, go tell that to jsessionid, aspsessionid, and phpsessid... and I bet a few bright minds and a few more minutes could come up with some sort of UUID-per-object-instance-reference-stored-in-a-session-map convention to handle stateful in-session objects. It’s not rocket science. Stop trying to make it rocket science!
Web services are great, but please, let REST RIP.