In 2008, Leonard Richardson published his Maturity Heuristic that classified web services into three levels based on their use of URI, HTTP, and hypermedia.
Back then, most web services were stuck at either level 1 or 2. Unfortunately, not a whole lot has improved since then in that respect: so-called pragmatic REST is still the norm.
BTW, I really dislike the term “pragmatic REST”. It’s a cheap rhetoric trick to put opponents (“dogmatists”) on the defensive.
More importantly, it creates semantic diffusion: pragmatic REST is not actually REST according to the definition, so please don’t call it that way or else we’re going to have a hard time understanding each other. The term REST hardly means anything anymore these days.
Anyway, there is some light at the end of the tunnel: more services are now at level 3, where they serve hypermedia. A good example by a big name is Amazon’s AppStream API.
The difference between plain media types, like
image/jpeg, and hypermedia types, like
text/html, is of course the “hyper” part. Links allow a client to discover functionality without being coupled to the server’s URI structure.
application/json is not a hypermedia type, since JSON doesn’t define links.
We can, of course, use a convention on top of JSON, for instance that there should be a
links property with a certain structure to describes the links, like Spring HATEOAS does.
The problem with conventions is that they are out-of-band communication, and a client has no way of knowing for sure whether that convention is followed when it sees a
application/json. It’s therefore much better to use a media type that turns the convention into a rule, like HAL does.
Speaking of out-of-band communication, the amount of it steadily decreases as we move up the levels. This is a very good thing, as it reduces the amount of coupling between clients and servers.
Level 3 isn’t really the end station, however. Even with a hypermedia format like HAL there is still a lot of out-of-band communication.
HAL doesn’t tell you which HTTP method to use on a particular link, for instance.
The client can only know because a human has programmed it with that knowledge, based on some human-readable description that was published somewhere.
Imagine that the human Web would work this way. We wouldn’t be able to use the same browser to shop at Amazon and read up at Wikipedia and do all those other things we take for granted. Instead, we would need an Amazon Browser, a Wikipedia Browser, etc. This is what we do with APIs today!
Moving further into the direction of less out-of-band communication requires more than just links. Links only specify the URI part and we also need the HTTP and media type parts inside our representations. We might call this level 3b, Full Hypermedia.
These newer hypermedia types allow for the use of a generic client that can handle any REST API that serves that hypermedia type, just like a web browser can be used against anything that serves HTML. An example of such an effort is the HAL browser (even though HAL is stuck at level 3a).
However, even with the inclusion of protocol, media type, and method in the representation, we still need some out-of-band communication.
The HAL browser can navigate any API that serves HAL, but it doesn’t understand the responses it gets. Therefore it can’t navigate links on its own to reach a certain goal. For true machine-to-machine (M2M) communication, we still need more.
If we ever get the whole semantic web sorted out, this might one day be the final answer, but I’m not holding my breath.
In the meantime we’ll have to settle for partial answers.
We’d still need a human to read out-of-band communication and build a special-purpose client for M2M scenarios. But this client could handle all services in the application domain it is programmed to understand, not just one.
Also, the human could be helped a lot by a generic API browser that fetches ALPS profiles to explain the API.
All this is currently far from a reality. But we can all work towards this vision by choosing generic, full-featured hypermedia types like Siren or Uber for our APIs and by documenting our application semantics using profiles in ALPS.