9 min read

What is RESTful API?

November 09, 2020

To understand RESTful API or RESTful web services, You first need to understand what an API is. API(Application Programming Interface) is a software/application/library/mechanism that helps one program to communicate with another. The most widely used API types are web-APIs or web-services. In this type, a client sends a HTTP request and the server sends back an HTTP response.

For example, if you are on a banking site, and you want to see the balance, The browser sends a request to the bank servers and gets a response with relevant account details.

REpresentational State Transfer (REST) is a set of software design guidelines to develop applications that interact over HTTP. If a web API follows REST’s architectural constraints, then it can be called a RESTful API.

Architectural Properties

The reason why RESTful APIs exist is because of its promised Architectural Properties. If implemented correctly, a RESTful web service would demonstrate properties such as

  • performance
  • scalability
  • simplicity
  • modifiability
  • visibility
  • portability
  • reliability.

By definition, A Web-Service should comply with the following architectural constraints to become a RESTFul web service or RESTful API. I will go through them one by one and what they mean and how they help in developing applications that couples loosely over HTTP.

Client-Server Model

The main reason behind this constraint is the separation of concerns. For example, in a shopping site, moving account-related components away from inventory and orders is a good thing because we can extend each of these components individually. The Order component can act as a client and perform an API request to Payment and Inventory web services if needed. It also improves scalability as each separate component can evolve independently.

Separation of concern

Stateless systems

Take a look at this sample code.

@GetMapping("/nextPage")
List<Orders> getNextOrders() {
     currentPage = currentPage +1 ;
      return getPage(currentPage);
}

The problem with this code is that the server maintains the state of what the client wants to do. And this state is maintained between requests. This is what we call as stateful systems. These type of implementations my seem comfortable at first. But, Things will become ugly as the client now need to know for sure which page it will get. This is why stateless systems are far efficient.

A system is stateless when the server doesn’t maintain any state between each requests. Take a look at the below code for the same problem we tried to solve before.

@GetMapping("/pages/{pageNumber}")
List<Orders> getNextOrders(@PathVariable Integer pageNum) {
      return getPage(pageNum);
}

With this implementation, the server doesn’t keep the current page number. The client gets to have the control of which page it wants to read.

Cacheability

As REST believes in HTTP concepts of the World Wide Web, clients and intermediaries are allowed to cache responses when possible. The servers and clients must provide enough hints to let the other party know if they support caching. In an ideal REST service, the caching partially or fully eliminates some of the client-server interactions and thus improving scalability and performance.

Layered System

A Client may not have to know what is behind the server it is requesting resources. A client may call order service and order service may internally query stock and price details from another service. This approach further enables the separation of concerns and thus letting each component evolve individually.

Layered systems

Code on demand

This constraint is optional. In a web API request, the request and responses are usually JSON or XML. But when you have to and if the client allows you may serve executable content as responses, for example, JSONP, APPLETS etc.

Uniform interface

For a web service, the client can be of many form. It can be a mobile app, a website, a smart device or even another service. With many type of clients, the code can become clumsy once we start writing platform specific code. REST wants to avoid these type of situations. A RESTful system should always have a single interface for all type of clients. No matter which type of client makes requests, the server should behave the same way, This is what we call as an uniform interface.

Uniform interfaces

Uniform interface is the core constraint for a service to be RESTful. This constraint dictates how each components in a RESTful systems should communicate with each other. The primary goal of this constraint is to provide a set of sub constraints that would streamline how client and servers can agree on 1) Where to look for resources 2) How to look for resources 3) How to agree to a format that client and server understands 4) And Is all of the above implemented throughout the system.

We will see about these sub constraints in details.

Resource identification requests

A resource in REST is a similar Object in Object-Oriented Programming or is like an Entity in a Database. It could be a web page, A single Object or an Entity. It may even represent any arbitrary content. Because of this nature, We need to address these unique resources, REST design principle advice us to use URIs.

By using URLs, we can arrange the resources in a hierarchical order. Let’s take an example. In an order management system, The following list will explain how we can represent the resources as URLs.

  • /orders Would represent all orders.
  • /orders/{orderId} Would represent order with specific order number
  • /orders/{orderId}/items Would represent all items in that order
  • /orders/{orderId}/items/{itemId} Would represent a single item in an order
  • /orders/{orderId}/account Would represent who ordered it.
  • /accounts/ Would represent all accounts in the system
  • /accounts/{accountId} Would represent a specific accounts.

The actual content of these URIs should provide enough information for the client to perform the necessary tasks. For instance, the client gets the data of the account when looking at the order. This way client can go back to the list of accounts and find relevant orders if they want to. Once we embrace this logic, REST APIs become easier to understand.

In some of the cases, You may not be able to give out all the information. In situations where the child objects have too much information, the server may provide URIs to those objects. The client should be able to follow the URIs to get the necessary information. This type of implementation is called HATEOAS(Hypertext As The Engine Of Application State).

Resource manipulation through representations

A client can perform CRUD operations on a resource identified by a URI(if the client has enough access). The good thing here is that URI can be an URL and thus we can map each crud operations into an HTTP verb.

HTTP Method Intended operation on a URI
GET Read a resource pointed by the URI
POST Create a resource at the pointed URI. Ideal implementation should return a URI of the created resource
PUT Replace all the representations of the member resource or create the member resource if it does not exist, with the content in the request body.
PATCH Update all the representations of the member resource, or may create the member resource if it does not exist, using the instructions in the request body.
DELETE Delete all the representations of the member resource

Self-descriptive messages

Each operation we spoke about earlier results is a response from the server. In some cases, the server will send responses. In other cases, there may be status messages. As we use HTTP for communication and HTTP by default comes with a variety of client-server status codes, we don’t have to invent new status messages or codes. For example,

  • HTTP 2xx means success.
  • HTTP 3xx may represent redirects or Cache related indications
  • HTTP 4xx means that the client didn’t send an appropriate request.
  • HTTP 5xx mean the server is either not in an accepting state or could not process the request.

Hypermedia references (HATEOAS)

In a response of one Resource we may not represent all of its child/parent Resources. In these cases, We need some way to point the right resources within out resource response from server. But we solved this problem already, with URIs. Each resource response may contain URIs of their related Resources, Following these Resource URIs will give the client to explore if they want to. These are called Hyper-Media-Driven outputs. And the representation is called HATEOAS (Hypertext As The Engine Of Application State). For example take this output json for Order resource.

{
  "orderId": 1,
  "total": 54.99,
  "_links": {
    "self": {
      "href": "http://localhost:8080/orders/1"
    },
    "account": {
      "href": "http://localhost:8080/accounts/2"
    },
    "items": {
      "href": "http://localhost:8080/orders/1/items"
    }
  }
}

Here the items field of Order is a collection of Item. Thus it would have taken a large number of bytes in the response. If the client wants that information, It can always navigate to http://localhost:8080/orders/1/items. Same for account field which is related to this specific order.

Advantages of restful services.

  1. By the nature of being stateless, The restful services are easier to scale up and down.
  2. The components are split based on logical layers. So upgrading separate components can be easier. This is why most of the micro-services go for a RESTful approach.
  3. Definitive operation instructions. As we seen earlier, each HTTP method is synonymous to a HTTP verb. This way no complex API documentation is needed. For example, A developer would infer that he need to Call HTTP.DELETE method if he needs to erase a resource.
  4. Lets be honest. Naming an API url can be brain numbing. Instead of choosing between, /getOrdersForAccount or /accountOrders, We could simply name using the hierarchical naming convention /account/orders. This is easier and less ambiguous to understand.
  5. With proper caching, The server load is reduced drastically. The benefit of not storing states increases the server’s performance.
  6. Client has most of the control.
About the author
Raja Anbazhagan

I'm a Software Engineer with over 7 years of experience in working with Enterprise Java applications. Lately, I am focused on cloud-based Java applications and serverless technologies. I spend most of my spare time on stackoverflow and this blog.