TL;DR
Representational state transfer
or simply REST is a term for exchanging data in well-defined formats in order to increase interoperability. Through application of certain constraints decoupling from clients to servers should be achived which make the former one more robust and the latter one more flexible to changes.
A resource representation is the outcome of applying a mapping from the resources current state to a media types well-defined syntax and structure. It is therfore highly coupled with content-negotiation which defines the process of agreeing on a media type to transform the resources state into a requested representation (= syntax & structure).
REST can be seen as a technique to decouple clients from servers/APIs in a distributed system which gives the server-side freedom to evolve and change its structure to its needs without breaking client implementations.
In order to gain such a strong benefit a couple of preconditions need to be in place as almost nothing comes for free. Fielding here defined a couple of constraints which he further clarified (and explained) in his well known blog-post. Servers won't be able to achieve such freedom if clients don't follow the REST approach as well as clients won't be able to dynamically explore further possibilities if the server does not support clients in such. In short, both sides need to follow the same principles. If the approach is not followed stringent a direct coupling between server and clients will remain which will lead to failures if the server is ever going to change.
But how is the decoupling actually achieved?
First, a server should support a client on following its task by including URIs clients are able to use. Having a server provide all the URIs a client can invoke from the current state the client is in removes the need of the client to have a-priori knowledge of the API and how the URIs are structured.
Second, instead of letting clients interpret URIs, servers should return URIs in combination with link relation names. I.e.instead of a client using (and interpreting) a URI like http://server.org/api/orders
it should use a link relation like new-order
. If the server changes the URI above to i.e. http://server.org/api/new-orders
for whatever reason clients using link relation names will still be able to follow their task while those using the URI directly will need an update before they are able to continue.
To my knowledge there are no standards yet where such link relation names should be defined and documented. For collection links the semantics of relation names like self
, prev
, next
, first
and last
seem to be meaningful enough though something more domain specific like order
or product-xyz
may not. Such semantics may be described either in special media types or new standards.
Up to now these points tackle the HATEOAS constraint but unfortunately that's not all yet. According to Fieldings blog post:
A REST API should spend almost all of its descriptive effort in defining the media type(s) used for representing resources and driving application state, or in defining extended relation names and/or hypertext-enabled mark-up for existing standard media types.
Fielding further commentet that:
A REST API should never have “typed” resources that are significant to the client. Specification authors may use resource types for describing server implementation behind the interface, but those types must be irrelevant and invisible to the client. The only types that are significant to a client are the current representation’s media type and standardized relation names.
A typed resource is a resource where a client has a preassumption of the content. I.e. a client who received a URI http://server.org/api/user/sam+sample
with a link relation name user
determines that data belonging to that resource describe a person and therefore may attempt to marshal a application/json
representation of the resource data to a Person
object.
The problem with typed resources is, that clients have certain pre-assigned assumptions or knowledge on the data contained in such resources, i.e. a user resource which may vary from server to server though. While one server may expose a user name as name
property an other server may use firstName
and lastName
and a client that wants to server each possibility is almost unmaintainable. Further, if the server ever changes its logic clients may break witha certain likelihood. To counter this coupling media types should be used instead.
Media types, which are human readable textual description of a representation format, defines the syntax used as well as the structure and semantics of available elements contained in documents exchanged in that format. Applications following the REST architectur model should therefore use established or custom media types to increase interoperability. Instead of directly coupling client and server, both couple to the media types actually. Support for such media types can be provided either through loading existing libraries or by implementing the specification from scratch. Even loading such media types dynamically through plugins is possible, if supported.
Clients and servers should use content negotiation to agree on a common media type format understood by both parties to exchange the current state of a resource. Content negotiation is achieved by providing a HTTP Accept
header (and/or one of its siblings), which lists the MIME types a client is able or willing to process, within the request and by the server responding either in one of the requested formats including a Content-Type
HTTP response header to inform the client which media type representation was used actually or returning a 406
failure response.
For the person example from above clients could send an HTTP Accept
header with the following content: application/vcard+json, application/hal+json;q=0.6, application/json;q=0.1
to the server, wich asks the server to return the state of the resource in a syntax and structure defined by one of the listed media types. It further specifies that the client prefers receiving the state formatted according to the specification of the application/vcard+json
media type description and if the server is not able to it should prefer hal+json over the traditional json syntax. The server now either maps the current resource's state to one of the requested formats or respond with an appropriate 406
failure message if either all of the requested media types are unknown or the state could not get converted to such a structure or default representation supported by the client.
To summarize, REST is a technique used to achieve high interoperability by relying on well-defined media types and to decouple clients from servers by using features like content negotiaion and HATEOAS. As reward clients will get robust to changes and thus need less maintaining in generall while server gain the benefit of being able to evolve and change without having to fear that clients wont be able to interact with it once the changes have gone live.
Certain things like standardized meaningful link relation names, custom domain-dependant media types and mapping processes to transform state into media type applicable representations need to be set up first, which is a non trivial task TBH, though once available they provide above mentioned benefits.