REST Architectural Constraints

1. Overview

REST Architectural Constraints are design rules that are applied to establish the distinct characteristics of the REST architectural style. 
If you follow all constraints designed by the REST architectural style your systems is considered RESTful.

2. REST Architectural Constraints

These constraints don't dictate what kind of technology to use; they only define how data is transferred between components and what benefits we get following the guidelines. Therefore, a RESTful system can be implemented in any networking architecture available.
  • Client-Server
  • Stateless
  • Cacheable
  • Uniform Interface
  • Layered System
  • Code On Demand (Optional) 

2.1 Client-Server

This is a major constraint and it simply requires the existence of a client component that sends requests and a server component that receives requests. After receiving a request the server may also issue a response to the client. This constraint is based on the principle of Separation of concerns.
Figure: Client-Server
Applying separation of concerns: 
  • Separates user interface concerns from data storage concerns.
  • Improves portability of interface across multiple platforms.
  • Improves scalability by simplifying server components.
  • Allows the components to evolve independently.

2.2 Stateless

The notion of statelessness is defined from the perspective of the server. The constraint says that the server should not remember the state of the application. As a consequence, the client should send all information necessary for execution along with each request, because the server cannot reuse information from previous requests as it didn’t memorize them. All info needed is in the message.
 Figure: Stateless
By applying statelessness constraint:
  • Session state is kept entirely on the client.
  • Visibility is improved since a monitoring system does not have to look beyond a single request.
  • Reliability is improved due to easier recoverability from partial failures.
  • Scalability is improved due to not having to allocate resources for storing state
  • The server does not have to manage resource usage across requests. 

2.3 Cacheable

REST includes cache constraints so that the "second fetch" doesn't have to be made at all if the data is already sitting in your local cache (or can be a request that only uses partial network resources if the cache is an intermediary or server-side).
                   If your data can be designed in such a way to take advantage of this, you can reduce total network traffic by orders of magnitude. 
 Figure: Cacheable
By adding optional non-shared caching:
  • Data within a response to a request is implicitly or explicitly labeled as cacheable or non-cacheable.
  • If a response is cacheable, then a client cache is given the right to reuse that response data for later, equivalent requests.
  • Improves efficiency, scalability and user-perceived performance.
  • Tradeoff: cacheable constraint reduces Reliability.

2.4 Uniform Interface

The uniform interface constraint at a high level means the interface for a component needs to be as generic as possible. It simplifies and decouples the architecture, which enables each part of the architecture to evolve independently. 
Figure: Uniform Interface
By applying uniform interface constraint:
The overall system architecture is simplified and the visibility of interactions is improved. Implementations are decoupled from the services they provide and encourage independent evolvability. 

Trade-off: Degrades efficiency since information is transferred in a standardized form rather than one which is specific to application's needs. Further, a uniform interface has four sub-constraints
  • Identification of resources
  • Manipulation of resources through representations
  • Self-descriptive messages
  • Hypermedia as the engine of application state (HATEOAS)
Identification of resources
Each resource must have a specific and cohesive URI to be made available. REST APIs are designed around resources, which are any kind of object, data, or service that can be accessed by the client.
A resource has an identifier, which is a URI that uniquely identifies that resource. For example, the URI for a particular customer order might be:
http://adventure-works.com/orders/1
Resource representation – Is how the resource will return to the client. This representation can be in HTML, XML, JSON, TXT, and more. Clients interact with a service by exchanging representations of resources. Many web APIs use JSON as the exchange format. For example, a GET request to the URI listed above might return this response body:
{"orderId":1,"orderValue":99.90,"productId":1,"quantity":1}
Self-descriptive Messages
Each message includes enough information to describe how to process the message. Beyond what we have seen so far, the passage of meta information is needed (metadata) in the request and response. Some of this information are: HTTP response code, Host, Content-Type etc. Taking as an example the same URI as we have just seen:
GET /#!/user/ramesh HTTP/1.1
User-Agent: Chrome/37.0.2062.94
Accept: application/json
Host: exampledomain.com
Hypermedia as the Engine of Application State (HATEOAS)
REST APIs are driven by hypermedia links that are contained in the representation. For example, the following shows a JSON representation of an order. It contains links to get or update the customer associated with the order.
Just one example:
{
    "orderID":3,
    "productID":2,
    "quantity":4,
    "orderValue":16.60,
    "links": [
        {"rel":"product","href":"http://adventure-works.com/customers/3", "action":"GET" },
        {"rel":"product","href":"http://adventure-works.com/customers/3", "action":"PUT" } 
    ]
} 

2.5 Layered System

There are many layers between the client and the server. These are called intermediaries and can be added at various points in the request-response path without changing the interfaces between components, where they do things to passing messages such as translation or improving performance with caching. Intermediaries include proxies and gateways.
Proxies are chosen by the client, while gateways are chosen by the origin server or are imposed by the network. 
Figure: Layered System
By applying a layered system constraint:
  • Similar to client-server constraint this constraint improves simplicity by separating concerns.
  • Can be used to encapsulate legacy services or protect new services from legacy clients.
  • Intermediaries can be used to improve system scalability by enabling load balancing
  • Placing shared caches at boundaries of the organizational domain can result in significant benefits. Can also enforce security policies e.g. firewall.
  • Intermediaries can actively transform message content since messages are self-descriptive and their semantics are visible to the intermediaries Tradeoff: Adds overhead and latency and reduce user-perceived performance.

2.6 Code on Demand

The code on demand is an optional constraint. It allows a client to download and execute code from a server. 
Figure: Code on demand

By applying Code on demand constraint:
  • Simplifies clients, hence promote the reduced coupling of features.
  • Improves scalability by virtue of the server off-loading work onto the clients.
  • Trade-off: Reduces visibility generated by the code itself, which is hard for an intermediary to interpret.

3. Conclusion

In this post, we have seen the 6 important REST Architectural Constraints.
Now we understand that these 6 architectural constraints which make any web service – a truly RESTful API.
These constraints of the REST architectural style affect the following REST architectural properties.

Comments