One Rest Constraint

Angelo Trozzo
6 min readMar 22, 2021

--

Since the World moved to Rest API paradigm, seems things have become easier and more adaptable as a solution. Nevertheless numerous times over the course of my career, I have to deal with projects with some opinionable API, and Rest-Like web services.

Building Rest API requires effort and decisive/purposeful actions.

But let’s start with the basics. We all know or at least we should know who Roy Fielding is and how important he was for the HTTP protocol specification. In his thesis he was the first one to define what REST stands for; Representational State Transfer. Rest is not SOAP, it is not a protocol and does not dictate architectural decisions, but instead suggests best practices. It’s an architectural style and as such, leaves a lot of freedom, however, it does have several constraints;

  1. Uniform Interface
  2. Client Server
  3. Cachable
  4. Layered System
  5. Stateless
  6. Code on demand (optional)

Whilst some of these bullet points can be fairly easy to achieve, most of which are dictated by modern architectural decisions; see client server and layered systems, some others require more thought.

In this article, we will look in more detail at the Uniform Interface:

Once a developer becomes familiar with one of your APIs, he should be able to follow a similar approach for other APIs.”

And Again

“In order to obtain a uniform interface, multiple architectural constraints are needed to guide the behavior of components. REST is defined by four interface constraints: identification of resources; manipulation of resources through representations; self-descriptive messages; and hypermedia as the engine of application state.”

The above are the official definition given at the time by Roy Fielding back in 2000 are still very relevant to this day. The idea of having a clear unique identifiable interface that can provide access to a specific resource and state is the key. This is brings us to the first of four sub constraints:

Identification of Resources

Clients should be able to identify a resource, and just that resource, by means of URI request. The URI is the only way to identify the name and address of a resource. This means that an URI should be predictable.

Let s have look at a possible API to retrieve an artist information:

https://api.my.music.server.com/music/artists/{artist-id}

A most predictable api to access albums should be something predictable like this:

https://api.my.music.server.com/music/albums/{album-id}

or

https://api.my.music.server.com/music/artists/{artist-id}/albums

for all the albums of a related artist.

Nothing new here, we are still referring to something standard, RFC 3986. The representation of the resource itself as well should be separated from the resource itself. Here, content negotiation will help to keep the API decoupled from the client, should the content of the API need to change.This will help to keep our API robust and easy to evolve as described by the Robustness Principle ( Postel’s law).

Manipulation of resources through Representations

When a client retrieves the representation of a resource and the related metadata, that would and should be enough to modify the resource state on the server. It s important to remember that a resource exposes its state through the concept of representation, which typically contains metadata and content.

Self Descriptive Message

The message exchanged between client and server, needs to contain enough information to make the recipient understand it. In our case when we reach our API we might send over something like this:

GET / HTTP/1.1
Host: https://api.my.music.server.com/music/albums/b6d4a3f7...

And receive from the server

HTTP/1.1 200 OK
Content-Type: application/json
...

This message is self-descriptive because it told the client how to interpret the message body, via Content-type.

The representation served to the client via the RESTful API should contain all the expected information and in case more are provided should be in a form of Hypermedia content.

HATEOAS

Hypermedia As The Engine of Application will take us to a Richardson Maturity level 3 for a Rest API and will help us to keep strongly decoupled from the server implementation. Hypermedia in fact will be the engine of the application state, telling us what can be done next and the URI of the resource, rather than expect the client knowing where and how.

Example: Let s imagine we want to reuse our API previously defined and retrieve all the available artists and related information from our music server:

https://api.my.music.server.com/music/artists/

Having albums in a link makes any future changes transparent for the client. Instead of coupling the client to known all about albums at this point in time.

API versioning

Warning! This si a controversial point of view. Why and what has the API version got to do with Uniform Interface? Let’s analyze it and see if we can find some interesting hook for a debate? If we reconsider our example API using a version in the URI:

GET http://api.my.music.server.com/v1/artists/{artist-id}

If we divide the URI based on the RFC-3986 standards the URI will be represented by 3 main parts:

  1. The scheme
  2. The authority
  3. Path

The authority identifies the service and refers to domain and subdomain identifiers. The path on the other hand, relates to identifying the resource model, where every forward slash represents a unique resource in the model’s hierarchy. What actually is v1 representing? Is part of the resource model? Being just a versioning constraint, subject to changes, semantically will definitely identify a different resource and/or a different resource state. How can this be compliant with the Uniform Interface?

The problem with this kind of versioning is that it breaks a very well-renounced concept of API evolvability. The concept of evolution is mostly based on loose coupling client and server and the idea that our API represents a contract that should not disrupt and break the client, every time a resource has some changes. In this case, we are talking of static API. Versioning an API in the path generate few well-known issues related to forward and backward compatibility as described in these 3 scenarios:

  1. The server and client are both built against a matching version of the API
  2. The server is built against a newer version of the API than the client is
  3. The client is built against a newer version of the API than the server is

Generally, API should support a very basic design principle, Open/Closed.

“software entities should be open for extension but closed for modification” (Bertrand Mayer)

If we add or remove information in our resource, the contract between the client and the server should not break. Going back Postel’s law which states that you should be “liberal in what you accept and conservative in what you send.” Translated in Java this would look like this:

A strict approach instead, will break at each small change, making a version, the only way to keep compatibility with clients.

The question persists, is versioning bad? The answer is obviously not. Versioning can be a commercial strategy for your public API or a need, based on resource model design constraints. The decision over an evolvable API and a version one is purely based on subjective perspective and needs. In theory, you can start using a static model and later introduce if really need versioning, possibly not in the URL, but in the headers ( for example), but this a completely different topic (versioning strategy).

--

--

Angelo Trozzo
Angelo Trozzo

Written by Angelo Trozzo

Software craftsman, interested in technology, art, Down hill Bike, nature and obviously my family.

No responses yet