RESTafarians should support the abandon of the original term – REpresentational State Transfer – in favour of some fresh new words.
RESTcalation
REST became popular as an alternative to SOAP in writing webservices, while, in fact, they are different and some kind of complementary in some ways: first of all, SOAP is not an architectural style; this is pretty interesting since lot of people actually think that REST equals some kind of API style.
It was pretty obvious that REST would have gained so much attention:
- sold as SOAP’s nemesis, while developers were starting to feel frustrated with the WS-* stack
- it seemed so simple:
GET
,POST
,404
,200
,Cache-Control
and you’re done - many RAD frameworks were using URI templates, so it seemed that using such this kind of schemes was a really good standardization (while they are coupling-prone1, one of the aspects that REST fights)
REST has – basically – 5 constraints ( the sixth one is Code On Demand, but it’s not that important ):
- client/server communication
- stateleness
- caching
- layering
- uniform interface
and, on the web, mainly with the HTTP protocol, people have been able to build:
- client/server models
- stateless communications
- cacheable resources
- layered systems2
What’s missing? The uniform interface.
What is REST’s uniform interface?
The greatest example of uniform interface is the HTTP protocol: something able to make 2 pieces of software talk an ubiquitous language.
Think about HTTP verbs, status codes and media types which are transported along the network: without HTTP it would be hard to face most of the real-world use-cases we need to model in our software with a universal way to communicate applications’ workflows.
This3 wouldn’t be sensational omitting two things which explain why the web has been able to tremendously benefit from its uniform interface: media types and hyperlinks.
Media types
They are – basically – the contract4 between a client and
a server, which defines how they should communicate and exchange resources: an
example is application/xml
, another one is text/plain
: never forget that
you can have vendor-specific media types (in DNSEE we have
used our own application/vnd.dnsee.ses.+xml;v=1.0
5, an XML –
atom-based – dialect), if you are not ok with re-using existing types from the
IANA registry.
Media types are not only important for understanding HTTP responses’ bodies, since – before even parsing a response’s body – machines can agree on exchanging informations in a specific format:
1
|
|
The Accept
header seen above is an example of how a client tells a server
which media types it understands:
text/*
tells the server that any kind of text-based media type can be succesfully interpreted by the client- being a declination of
text/*
,text/html
should be the preferred response format
Servers can behave in different ways based on the media-type requested or used by
clients: for example, if the client POSTs a new resource with a media type the
server doesn’t get, it will receive back a 406 Not Acceptable
status code.
All these practices have a name, content negotiation, which is applied not only to media types but also to more human concepts, like responses’ language:
1
|
|
Acceptance is not the only criteria used to instantiate a correct communication
at the protocol level: for example, if the server – on a certain resource –
provides an Allow: HEAD, GET
and the client PUTs at that resource it will
receive a 405 Method Not Allowed
back.
Hypermedia
When I say hypertext, I mean the simultaneous presentation of information and
controls such that the information becomes the affordance through which the user
(or automaton) obtains choices and selects actions. Hypermedia is just an
expansion on what text means to include temporal anchors within a media stream;
most researchers have dropped the distinction.
When talking about hypermedia on the web, we usually think about hyperlinks:
1
|
|
without considering that hyperlinks can be really complex data structures:
1 2 3 4 5 6 7 |
|
and that they are not bound to (X)HTML documents:
1
|
|
Cache channels , which let you build more efficient, reliable and scalable services, are a good example of leveraging the power of hyperlinks in a complex scenario:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
|
Hyperlinks are used to connect resources and verify their freshness in a M2M scenario, and not only rendered by a browser “just” to be clicked by a user.
REST in the world
Never talked about media types with your
colleagues?
Ordinary.
Never heard about hreflang
attributes in hyperlinking?
Ordinary.
Don’t you know the difference between text/xml
and application/xml
?
Ordinary.
Never thought that if you consume some data, when their URL changes you can still
fetch them without changing any line of code?
Less ordinary, but I can’t judge you.
REST failed: most of the times we hear people talking about REST they discuss about building *plain-old-XML over HTTP webservices, without even knowing the importance of having an extensible infrastructure supporting updates and not breaking retrocompatibility with your consumers.
Enter hypermedia services
By applying the software engineering principle of generality to the component interface, the overall system architecture is simplified and the visibility of interactions is improved. Implementations are decoupled from the services they provide, which encourages independent evolvability.
The trade-off, though, is that a uniform interface degrades efficiency, since information is transferred in a standardized form rather than one which is specific to an application’s needs.
The REST interface is designed to be efficient for large-grain hypermedia data transfer, optimizing for the common case of the Web, but resulting in an interface that is not optimal for other forms of architectural interaction.
Hypermedia services are the ones that rely on hypermedia controls in order to efficiently implement decoupling and avoid breaking retrocompatibility.
For instance, let’s look at the URI templates coupling problem:
1 2 |
|
1 2 |
|
1 2 3 4 5 |
|
Enter hypermedia-aware clients
When the client decides which URI to call and when, they run the risk of attempting to request state transitions
that are not valid for the current state of the server side resource.
An example from my problem domain … it’s not allowed to “start” a virtual machine (VM) until you have “deployed” it.
The server knows about URIs to initiate each of the state changes (via a POST), but the
representation of the VM lists only the URIs for state transitions that are valid from the current state.
This makes it extremely easy for the client to understand that trying to start a VM that hasn’t been deployed yet is not legal, because there will be no corresponding URI in the VM representation.
Hypermedia-aware clients are those client able to detect, understand, process, ignore hypermedia controls, making no assumption in consuming a resource.
People should really care about implementing HATEOAS6 and HATEOAS-detection, since it has proven to be a winning factor in writing robust, fault-tolerant, balanced and durable systems:
- URI templates would not be a problem - per sè - if developers wouldn't forget about decoupling URIs with the application's flow ↩
- Layered system are now a big part of the web, not only of the enterprise world, thanks to social services and the social web: in order to face webscale problems we now need - more than ever - reverse proxies, gateway caches, the cloud… ↩
- Machine-To-Machine ubiquitous communication ↩
- As stated earlier in some of my posts or at some conferences, REST has contracts (called media types) just like SOAP has WSDLs ↩
- “ses” stands for Service Expression Synthax ↩
- Hypermedia As The Engine Of Application State ↩