Monday 8 January 2018

How to design a RESTful API architecture from a human-language spec

This is a precise of a separate post: https://www.oreilly.com/learning/how-to-design-a-restful-api-architecture-from-a-human-language-spec?imm_mid=0fa416&cmp=em-prog-na-na-newsltr_20180106


By RESTful API we mean an API that follows Representational State Transfer (REST) architectural style. REST is a very popular approach to building APIs because it emphasizes simplicity, extensibility, reliability, and performance.

Let’s briefly look at each of those concepts to see how using a RESTful architectural approach affects the way your API behaves for its users1 :

  • Simplicity: The way to interact with API resources is well-defined and strict: you have a clear and simple path to follow concerning what you can and cannot do. Interaction is stateless: requests have all data needed to move resources to the next state.
  • Extensibility: Support for representing the same resources with different formats or even versions, ability to add new resources without changing others, etc.
  • Reliability: Clear separation of actions with and without side-effects, the possibility of retrying requests with idempotent actions, etc.
  • Performance: Caching made possible via well-defined semantics, scalability made possible because server resources can be isolated in each request due to stateless interaction, etc.

The process for designing a RESTful HTTP API architecture has two steps:


  1. Identify nouns and verbs from the system spec
  2. Extract URLs and the methods they respond to from those nouns and verbs

With those simple things, we'll have the basis of our API. It will be enhanced with other considerations in the next two articles.

Start with the basics: REST key concepts

Let's review a few key concepts of RESTful APIs as we start reasoning about our own application. First of all, we need to think about the basic elements used in REST:

  • Resources - You can think of those as the "nouns" of your system. For example, in a food-delivery service API, the nouns would be restaurant, menu, menu item, restaurant owner, etc. Those nouns are what hold the State, the "S" in REST.
  • Representations - Representations are the way API clients see the resources. A RESTful API never hands resources directly to a user. Interactions happen only via representations of the real resource. For example, you can store all the menu items for a restaurant in a database table, but the representations of these items in your API might be a list of names and prices, perhaps filtered to reflect restrictions specified by the user. To do this, we use media types such as JSON and XML. That's why REST is "RE"presentational.
  • Actions - Because API clients do not have direct access to resources, they need actions to alter the state of a resource. Those actions are the verbs of our system. They are what "transfer" the state, the "T" of REST.

One of the main authors of HTTP is also the creator of REST. No wonder HTTP has parts that fit very well to these REST basic elements:
  • URLs - Uniform resource locators, as the name states, are what people and programs use to locate resources from servers across the Internet. They locate REST resources.
  • Media Types - These specify how the data in requests and responses look like, i.e., the REST representations. Currently, the most popular media types are JSON, HTML, and XML.
  • Methods - HTTP built-in methods (such as GET, POST, PUT, DELETE) are what we use to implement REST actions. Each HTTP method has characteristics that should be taken into account when implementing the actions. Methods are called over URLs and have data that is represented with media types.

From Spec to RESTful API

We've seen that REST is made of resources, representations, and actions. We've also seen that resources are like nouns and actions are like verbs. So, identifying the nouns and verbs available at a system spec is a good way to start our spec to API process. By reading the spec, we can get the following list of nouns and verbs related to the system use cases. For example an API for a bike rental service, night have these verbs & nouns:

Nouns:

  • City
  • User
  • Station
  • Bike

Verbs:

  • View (user views the list of stations)
  • Rent (user rents a bike)
  • Show (app shows the quantity of available bikes at a station)
  • Release (station releases a bike)
  • Ride (user rides a bike)
  • Return (user returns a bike)
  • View (user views the history of rents)
  • Change (user changes destination station)
  • Cancel (user cancels the active rent)
It's easy to convert nouns into HTTP resources with URLs. For example, the noun “station” can become a resource located by the URL path /stations/ in our API. But there are some gotchas in the conversion of verbs to HTTP methods.

A word on HTTP "verbs"

One limitation we have while mapping a spec to a RESTful API is the restricted set of verbs HTTP provides. We can only use the documented HTTP methods: GET, POST, PUT, PATCH, DELETE, etc. As you can see, we don't have a "RENT" verb, even though at first glance our application requires it.

Instead of custom verbs, we must define custom nouns for our RESTful API. Anything can be a noun. Therefore anything can be a resource that's mapped by a URL. Even if it doesn't look like a noun at first sight. "RENT" fits more into a verb, but you can noun-ify it to make it a resource. Think about the "Rent" noun, not the "RENT" verb. Then you'll see that you can "add a Rent". And HTTP fits here because it has the POST verb for adding things. See? Just by changing the way we think about noun and verbs we can adapt our application to HTTP. 

The correct way to rent something via HTTP is to POST a Rent.

Thus, to properly design our RESTful API we need to know really well the meaning of each HTTP method. What are the semantics behind each method? How should we use them? Let's see:

  • GET - Should be used to retrieve data from the server. Means "give me a representation of this resource identified by this URL". It's worth noting that we must never use GET to change resources. For this, we have the following other methods.
  • POST - Should be used to provide data to the server. Means "process the resource representation as a new subordinate of this URL". In practice, POST is mostly used for creating resources. The client specifies the resource representation in the request body and makes a POST to the URL that holds the collection of resources.
  • PUT - Should be used to update existing server resources by replacing their old state with a new one. Means "use this representation to replace the resource identified by this URL". 
  • DELETE - Should be used to remove server resources. Means "delete the resource identified by this URL".
By following the semantics of each method, we can design a truly RESTful API.

Conclusions

Before starting any work on an API DO NOT start coding, spend time writing the API down and discussing and agreeing it.
Doing so will save days of lost effort.

For a full analysis of how to convert a particular API see the original article as it details the transition of the Bike Rental API into its methods.