REST APIs: DEMYSTIFYING THE BUZZWORD
Web development has many buzzwords like “REST”, “API”, and “ARCHITECTURE” or to make matters worse, a combination of these terms gets even more confusing terms like “REST ARCHITECTURE” or “REST APIs. While these terms represent many important concepts in web development, their meanings are often lost on us.
But I got you covered. In this article, we will delve into the subtleties of these terms, you will gain not only a practical understanding of the study but also practical tips on how to effectively implement it in your projects.
It all started in 2000 when Roy Fielding in his dissertation introduced Representational State Transfer (REST) as an architectural style. The objective was to draft engineering principles and interaction constraints essential for building distributed information systems. What a great guy!
Fielding in his work stated that there are two common perspectives on the process of architectural design. Firstly, the designer may choose to start from nothing and build up an architecture from familiar components until it satisfies the needs of the intended system. Secondly, the designer may choose to start with the system’s needs as a whole, without constraints, and then incrementally identify and apply constraints to the elements of the system to allow the forces that influence system behavior to flow naturally, in harmony with the system.
The first approach emphasizes creativity and unbounded vision, while the second approach emphasizes restraint and understanding of the system context. REST was developed using the second approach. The REST architectural style was designed mostly for network-based applications, which are usually very dynamic (features of a network-based application may vary depending on the use case, number of users, resources being shared, technology being used, and some other factors).
Fielding in his dissertation listed the constraints as follows:
The null style: This is the starting point for our description of REST architecture. This is simply an empty set of constraints. From an architectural perspective, the null system describes a system in which there are no distinguished boundaries between components.
Client-Server Architecture: The first constraint added is the “client-server” architectural style. By separating the user interface implementation from the data storage implementation, we improve the portability of the user interface across multiple platforms.
For the Web, the client and server are separate entities that communicate over a network. The client is responsible for the user interface and user experience, while the server is responsible for processing requests and managing resources.
Statelessness: Each request from the client to the server must contain all the information necessary to understand the request, and cannot take advantage of any stored context on the server. This constraint induces the property of visibility, reliability, and scalability. Visibility is improved because a monitoring system (eg. server) does not have to look beyond a single request datum to determine the full nature of the request. Reliability is improved because it makes it easier for the system to recover from partial failures ( due to statelessness, the system can recover without dependence on any third party). Scalability is improved because not having to store state mid-requests allows the server to quickly free up resources.
Caching: Cache constraints mandate that the information in a response to a request must be marked as cacheable or noncacheable, either implicitly or explicitly. When a response is deemed cacheable, it permits a client to reuse that response data for subsequent, equivalent requests.
The advantage of adding cache constraints is that they have the potential to partially or eliminate some interactions, improving efficiency, scalability, and user-perceived performance by reducing the average latency of a series of interactions. The trade-off, however, is that a cache can decrease reliability if stale data within the cache differs significantly from the data that would have been obtained had the request been sent directly to the server.
Uniform Interface: A server must not require a different way of accessing data despite the nature of the device requesting the data. The same format used by a Windows device, should also hitchlessly run on a Mac device, or even an Android device, you get the gist, right?
The way a client interacts with the server is completely independent of the device or application. An application that is built using the REST constraints uses HTTP verbs like GET, POST, UPDATE, PUT, and DELETE to act on resources, as well as a standard format for data representation (eg. JSON).
Uniform Interfacing has four sub-principles:
Self-descriptive messages: Each message exchanged between a client and server should contain all the information necessary for its interpretation, without requiring any external context or prior knowledge. A self-descriptive message usually contains a header(comprising of the status code, content-type — {JSON, XML}, a body (the data contained in the body comprises standard data types), metadata(additional information about the message), and HATEOAS. Yes, it's another buzzword, but stay tuned.
Hypermedia as the engine of application state (HATEOAS): they are links within responses and guide clients to further actions and resources.
Resource identification: In REST architecture, every resource (eg users, images, products) are uniquely identified by a URI. URIs often follow a hierarchical pattern, reflecting relationships between resources. For example,
/users/123
might represent a specific user, while/users
might list all users.Manipulability of resources through representations: This tries to align client expectations with server actions, reducing misunderstandings.
for example, in creating a user:
the client sends a POST request to /users with a JSON representation of the new user’s name, email, and password (required user data).
the server responds with a 201 (CREATED) status code and JSON representation of the newly created user.
Layered System: A layered system means that a client can access endpoints that rely on other endpoints without understanding all of the underlying implementations.
The design of a RESTful API with consideration of the layered system constraint implies that interactions between the client and server can go through different layers or intermediaries without the client noticing.
As the name suggests, there may be several layers that are on top of each other. for instance, we may have a user interface, a security layer( for user authorization and authentication), a database, business logic, etc. The way the layered system works is that the layers can only directly communicate with the adjacent layers, and never jump above or below. The request must move in sequential order from top to bottom.
In a layered system, it is easy to insert a new layer without having to change the entire system. Decentralization is easy, and replacing and updating things in the layered system becomes easier.
By adhering to the layered systems constraint, RESTful architectures gain several advantages, including improved maintainability, extensibility, and the ability to accommodate system structure changes over time. This constraint aligns with the overarching goal of creating scalable and adaptable distributed information systems.
Code on Demand: This is the optional constraint. It is open to the possibility of the server generating and sending code that is to be executed on the client side.
REST is more of a guideline than a protocol itself because, in its implementation on the HTTP protocol, we attempt to apply a few constraints to clarify communication and resource management. Generally speaking, REST API is an API that follows the REST architecture, applying the constraints wherever possible.
REST architectural style was incorporated as a web development pattern during the infant stages of the World Wide Web, to standardize Web design patterns and reduce complexities.