It’s been over a decade since Roy Fielding wrote his seminal dissertation on Representation State Transfer (REST). Over this period we’ve seen SOAP/WSDL fall out of favor as the cool kids transition their services over to the REST paradigm. Or so it seems on the surface.
In reality, we’ve spent the last 10 years building various ad-hoc services over HTTP that borrow bits and pieces from the grand vision that Roy outlined. We’ve settled into a rhythm that, depending on your outlook, is either a naive implementation or an enlightened massaging of the initial approach. Is the glass half empty, or half full?
A Religious Debate
Your answer depends on your faith. I say faith because a group of RESTafarians defend Roy’s initial vision with near spiritual fervor. Yet, those with such devotion must accept that they’re on the fringe. Why? Virtually no popular APIs that claim to be RESTful today actually honor the complete tenets of the faith. The market has spoken and chosen to be pragmatic. We, the wild unruly developers, have chosen to do our own thing. Check out Facebook, Twitter, and Twilio. All have APIs that claim to be RESTful but have various unique properties that go against REST tenets.
Pragmatism has a variety of benefits which I’ll get to in a moment, but many APIs that claim to be RESTful vary greatly in their implementation. Thus, REST has lost any concrete meaning since the canonical reference is rarely honored in the real world. Fact is, there’s no jargon to describe the architecture of the vast majority of “REST” APIs in use today1.
This inconsistency complicates the entire ecosystem around HTTP based APIs. Consider the following aspects:
- Learning – Learning REST is difficult with such an amorphous definition. There’s no canonical reference and those who subscribe with devotion to Fielding’s work must accept a striking disconnect between his vision and a large body of popular “frauds” in the wild.
- Development – Developers often rely upon benchmark implementations, but today’s “RESTful” APIs provide wildly inconsistent conventions. Even after ten years, the tooling is weak and much of the work remains ad-hoc.
- Consumption – Since every “REST” API is a unique flower, consumers must carefully read documentation to assure they understand the unique approaches of each provider. Lack of convention slows both understanding and consumption.
So Is Anyone Doing it “Right”?
Well, this isn’t about right and wrong, but here are a select few APIs that fully honor REST:
John Moore presented an excellent example of a truly RESTful API at Oradev. Wow, that’s a short list. There’s a sea of “REST” APIs by major players that just don’t fit this bill.
REST Cheat Sheet
So let’s get down to brass tacks. Outside of the rare exceptions above, today if you see an API that claims to be RESTful, it’s basically saying
“To work with our data, send the proper HTTP verb to the URIs in our online docs and specify whether ya want JSON or XML”.
Yep, it’s that simple, and about that casual too. We API developers are doing the simplest thing that could possibly work. No shame in that.
Here’s a number of common ways today’s RESTful APIs deviate from Fielding’s REST, along with an explanation of why the deviation may be useful.
|REST Principle||Why Deviate?|
|Honor HTTP Verb Semantics||Although REST prescribes using HTTP GET, PUT, POST, and DELETE verbs for CRUD operations, some clients can’t generate the less common PUT and DELETE requests. In addition, some overzealous firewalls block PUT and POST. Thus, some RESTful APIs accept all requests via HTTP POST or GET and place the HTTP verb in the querystring. For example, to delete user 124, the POST request would be for the following URI:
|Utilize HTTP Status Codes||HTTP offers a rich set of 71 separate status codes which should be used to describe response status. Some “RESTful” APIs always return an HTTP 200, even when errors occur. This can be necessary when the client won’t allow the developer to elegantly handle any HTTP responses other than HTTP 200, such as when working with Flash. Twitter provides the best of both worlds by allowing the caller to request supression of HTTP status codes and always return a 200. Most RESTful APIs utilize a small subset of the potential status codes.|
|Self Descriptive Messages||REST specifies that the HTTP accept header should declare a custom and specific format. However, very few real world APIs do so. Instead, two popular compromises exist:
|Discovery via Linking and Hypermedia (HATEOAS)||Here’s the unicorn. Virtually none of today’s APIs honor this. To prevent tight coupling between the client and the service, truly RESTful APIs provide a discovery based API. Each call provides a reference to related calls. This allows the API to be highly evolvable because it avoids creating a coupling between the client and the server. This aspect is nearly universally ignored by today’s popular APIs, as made evident by the common pattern of publishing a list of URIs.|
|Hypermedia Aware Media Type||Examples of hypermedia aware media types include HTML, XHTML, Atom, SVG. Notice what this doesn’t include? XML and JSON. Neither offers a native way to convey a hyperlink. This constraint is necessary to support discovery. So, if you’re not interested in the benefits of discovery (and based on real-world uptake, few are), feel free to return XML or JSON.|
|No Version Number||Since fully RESTful APIs are discovery based, the API is expected to change at any moment. Thus, no version number is required. However, as we’ve discussed, the majority of today’s popular “REST” APIs document a static list of URIs that they support. Once you’ve accepted discovery is off the table, version numbers are beneficial to assure all clients aren’t required to simultaneously upgrade whenever the API changes. Version should either be the first segment
|No static URIs||A discoverable API can change regularly and thus should be interacted with solely through the links provided through API calls. However, the vast majority of today’s “REST” APIs document precise URIs and their corresponding return types. The benefit is efficiency since you can directly make the desired call, but at the expense of flexibility due to the tight coupling it creates between the consumer and producer. With “hard coded” documented URIs, if you change the API you need to support concurrent versions as described above, otherwise both consumer and producer have to change simultaneously.|
For more insight on Pragmatic REST, check out this excellent video by Brian Malloy at Apigee.
So Is Microsoft Pragmatic?
In the .Net space, we have two common options for creating RESTful APIs: WCF’s REST Template and the new kid on the block, Web API. The former was recently deprecated in favor of Web API. Although both technologies are completely capable of supporting a fully RESTful API, out of the box neither does so. Both direct developers down the path of creating a pragmatic RESTful API in today’s most popular style. In short, this means neither directs the developer to utilize either discovery or leverage the power of native HTTP response codes.
So what’s the big deal?
Okay, full disclosure, I believe in pragmatic REST. Hey, I strive to be a pragmatic programmer. Although I have no qualms with the deviation, the fragmentation and inconsistency need to be addressed with a canonical reference or convention that shines light on the deviations. In the meantime, developers must strive to make conscious and rational decisions when designing RESTful APIs. REST is an overloaded term, so it’s important that we’re clear and deliberate about the tradeoffs we accept when deviating from the initial spec.
Edit: This post hit the front page of Hacker News! There is plenty of great conversation over there in addition to the comments below.
1 The same issue has occurred today with AJAX. We’ve long since moved on to JSON from XML but AJAX remains in the vernacular. It’s understood that returning JSON over XmlHttpRequest can still be referred to as an AJAX call. (Yes, some pushed for using the term AJAJ but it didn’t catch on).