Having a proper REST

Today’s article is devoted to REST API. I will try to keep it as short as possible and simple as possible targeting people who are new to this concept. So if you have had experience with REST then you are very likely to find here lots of stuff that you already know. The article gives the essential crisps and bits of understanding what a good REST implementation might look like.

REST stands for Representational state transfer and its purpose is to simplify the communication between components of a computer system distributed over a network.

Here are the key aspects of REST:

  1. There is always a server that owns some state and a client that is interested in the state.
  2. Every client message to the server is associated with the following things:
    • A domain model area, called “resource”. Each resource has a unique identifier.
    • An action the message wants the server to carry out in the context of the specified resource.
  3. Most common use of REST is over HTTP protocol, but REST is not limited to HTTP and can be used in other environments, i.e. on top of message queues.

There are for sure more, but I will cover them later implicitly.

Let’s imagine Alice owns the server and Bob owns the client that needs to consume and update the data from the server. In order for the client-server communication to happen Bod needs to know what API Alice exposes on her side. There are two approaches Alice can take to make Bob’s life a whole lot easier:

  1. Alice provides an explorable API. It means that in the beginning Bob knows only about a single entry point from the whole API. When Bob starts to query the known API the responses contain data itself, metadata that helps to digest the data and navigational metadata that hints what other associated resources are available and what actions they allow.
  2. Document the whole thing in advance, so Bob knows the layout of the API and does not rely on any kind of metadata to consume the data.

The first approach fits the public APIs where Alice and Bob do not generally talk to each other and do not exchange any documentation.

The second approach is good for APIs that are used within a single work organization and it allows to save on building and transferring metadata with the messages. By the way, in order keep the API documentation up to date Alice can use libraries like Swagger which take the API and spits out an automatically built documentation for it. Bob can take it even further by consuming the auto-documentation and building REST clients to the API for his tech of choice.

At some point Bob and Alice agree to use REST via HTTP as the API access protocol. To be honest REST implementations that imply anything other than HTTP are so rare to find, that it does not take them too long to agree. Anyway using HTTP brings certain specific flavors into the REST API implementation:

  1. Resource identifiers are expressed as URLs.
  2. The actions the resources support are expressed as HTTP verbs (GET, POST, DELETE, etc.)
  3. Some others of lesser importance.

Besides the HTTP specific things REST some conventions that need to be followed if Alice wants Bob to consume the API hassle free. One of them is the way the resource identifiers are built.

http://my.api.provider.net/api/v1/resources/resourceId?query

The example resembles an ordinary URL but it actually follows stricter conventions rather than those apply to all URLs. It begins like all other URLs with the protocol and the domain. Then follows the part of the path that indicate the API is being used and API version. The latter two are optional, but having them is considered good manners to say the least. The part of the URL of the greatest interest if this:

/resources/resourceId?query

Alice is a good engineer and she knows that only nouns and IDs can go into into the REST resource identifier. The nouns stand for the collections of domain entities and IDs are used to specify which entity from the associated collection is being operated on. The query part usually contains clauses that help to work with collections, i.e. filtering, sorting, paging.

From Bob’s side this API is super easy to consume. After all prerequisites for the web call are met (the authorization is passed, the network path is available, etc.) Bob needs to make an HTTP request to the URL of the resource he wants to act upon and supply the HTTP verb supported by the API.

Theory needs some practice to let it settle, but first…

Let’s have our imaginary friends Alice and Bob magically appear in the business simulation game.

Bob joins the game and wants to know what businesses he owns at the moment. He issues an API call which uses the GET HTTP verb and the relevant resource locator (the boring part in the beginning of the URL is omitted).

GET /subjects/my

GET stands for a request to make a transfer of the representation of the server state from the server to the client. The resource locator specifies what data the client is interested in. In Bob’s case the mentioned resource locator points to a collection of subjects (this is an alias to the business which can grow from a small family store to a huge corporation in our simulation) and it has an additional segment after the collection name “my” that servers to tell the API the the collection needs the filter to be applied to return only Bob’s subjects.

Snap! The request did not return anything for Bob and he decides to kick off a new business and creates a subject. To do so he issues the POST into the appropriate collection.

POST /subjects
{
  name:"Good guy Bob & Co."
}

At this point the API needs some input from Bob which he successfully provides by including the state representation using JSON payload in the HTTP request’s body. REST does not restrict the data type to JSON only, but instead Bob can enjoy sending and receiving any kind of data as long as Alice and Bob have an agreement on the supported data types. Since Bob knows in advance that this resource’s action supports JSON he sets the HTTP content type header for Alice to rely on and to process the incoming data model successfully.

After the the POST request is processed it might or might not return a reply. But Alice follows best practices and sends the ID of a newly created subject back to Bob in the response. So now Bob is able to get the newly created entity by its ID without making another call to list the resource collection:

GET /subjects/1

This call is supposed to return a single entry from the collection of the specified resources and Bob sees the newly created item in the response.

{
 name:"Good guy Bob & Co.",
 created: "2077-06-11T00:01:20"
}

Bob notices that the data schema returned to him is different from the one he has used to submit a creation request, but Bob knows that this is just a representation of the state and different API calls can return different projections of the same data by design and it is quite common to do so.

Now Bob wants to add new departments to the subject he has just created and doing so is very easy via REST:

POST /subjects/1/departments/administration

which might return the ID of a newly created administration department to be used in a query like

GET /subjects/1/departments/administration/15

This request literally means “get the administration department with ID equal to 15 from the subject with ID equal to 1” and it will return the state for the department in question.

Then suddenly Bob decides that he wants to get rid of the business he ran for some time and issues a DELETE HTTP request. But Bob is tired by now and he forgets to specify the identifier of the subject he wants to drop and makes the following call:

DELETE /subjects

instead of

DELETE /subjects/1

Since Alice has implemented her API according to the pattern this call is interpreted as “delete all the subjects” and Bob gets an error, because the code attempts to delete all of it and fails as Bob is not allowed to delete other players’ stuff. The HTTP status of the response will indicate a server error (403 forbidden sounds just about right) and Bob will revisit his request and narrow its scope down to a single subject.

Conclusion

Alice and Bob were kind enough to demonstrate the elegance and huge potential of REST today. While mostly being used in conjunction with HTTP but not limited to it REST uses a lot of HTTP protocol features, like verbs, URLs, headers and status codes and empowers developers to build amazing things on top of it, see OData for example.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s