In the world of software development, APIs are everywhere, enabling different systems to interact seamlessly. But what exactly are APIs? Are they an internet thing? An API can be for anything e.g. a car has its own API, and even a human being has its own APIs. APIs are not just an internet thing; they are protocols and we have multiple types of APIs, most of which we see on the internet and are known as the REST APIs. Let us begin by outlining the fundamental aspects of REST APIs.
Characteristics of REST APIs
Simply put, we have an interface and certain methods to perform actions according to that interface. You generally involve two parties: a server and a client. Clients are provided with a well-defined set of rules, outlining the available options and how they can be used to communicate data with the server in the form of Get or Post request.
We might consider communication as an exchange of messages but that’s not all; streaming a video on YouTube or accessing your email involves communication between the server and the client. This communication is performed through a well-defined API that in majority of the cases is a REST API.
Now that there is a basic understanding of REST APIs, let us explore the concept of "state" in the context of the Internet.
Understanding "State" in the Internet Context
A short introduction to "state," especially in the internet context, is necessary. Generally, the state refers to the characteristics. Just as APIs can be for anything, states can also be for anything. For example, a car's simple state could be whether it is in ignition or not, whether it is started, or if the handbrake is engaged. Additionally, if the car is turning and its wheels are angled, that represents another state. Similarly there are some states in the client/server communication.
With a grasp on what state means, let us differentiate between stateful and stateless APIs, focusing on REST APIs' stateless nature.
Statelessness in REST APIs
REST APIs themselves are stateless, but there are protocols out there where the state plays a significant role. One example of a stateful protocol is WebSockets. This discussion will briefly introduce what state is in WebSockets to build an understanding of what statelessness means.
Understanding State and Statelessness
State can include the user's information, the user's connectivity, or previous messages from the user. These are the most important aspects when playing an online game, for example. WebSockets are protocols that carry these states. Every time there is a WebSocket connection, there is some user information, a persistent connection, and some previous state maintained.
REST APIs are designed to be stateless, meaning there is no need to save any client context between requests. However, effective communication requires a certain source of truth, some form of state somewhere. For example, logging in. It is necessary to determine if a user is logged in or if the correct password was entered while trying to log in.
Even though REST APIs are stateless, it does not mean there is no memory or no state somewhere else. The server uses databases or other storages to hold data e.g. user credentials for logins. To illustrate how REST APIs handle user authentication without maintaining state, let us walk through the process of logging in.
Example: Logging In with REST APIs
Suppose a REST API call is made to log in. Some information such as an email and a password is sent to the server as an API call. GET or POST requests are used, but the specifics are not detailed here. Credentials are sent to the server, which knows nothing beyond this request and does not retain any information from previous requests. The server uses the credentials stored in a database to match what's sent by the user. If there is a match, we let the user login. The incoming request does not require the user to have previously sent anything else. It only needs the user's email and password to authenticate them right then and there.
Having understood the login process, let us explore how authentication is maintained without a server-side state.
Maintaining Authentication Without Server-Side State
To determine if the user is still authenticated afterward, consider scenarios such as liking a post on Facebook or opening the comment section. Re-authentication is not required in these cases. Typically, logging in once allows all these functions to continue without requiring additional logins. Without state, it is necessary to identify that actions like liking a post or commenting are performed by the same user. This is where tokens come into play, making each request self-sufficient. This brings us to the role of tokens in maintaining authentication in a stateless environment.
Tokens and Stateless Authentication
Upon logging in, the server provides a token, such as a JWT (JSON Web Token), which is included in the Authorization header of subsequent requests. This token helps identify the user in the next request, indicating that the same user who logged in earlier is making the current request. This is why actions like liking a post on Facebook or commenting on another page do not require additional logins. All subsequent requests include this token in their headers. If you were to make a request without this token, you will be prompted to login again.
Even though the REST API is stateless, actions that seem stateful are still manageable. Statelessness, in the context of REST APIs, means that each request is self-sufficient—it contains all the information the server needs to fulfill the request.
To delve deeper into how REST APIs utilize HTTP requests and headers to maintain statelessness, let us examine the technical components involved.
HTTP Requests and Headers
Two components form up a request. Some data that is being sent to the server or being sent by the server and the second, headers. Both requests and responses have headers. Tokens like JWTs are included in request headers to authenticate and authorize requests in a stateless manner. Similarly, additional information can be sent in request headers.
One example is caching. Caching mechanisms are employed to save up on resources on both server and client side, for instance, informing the server, "I already have this image named 'abc.jpg.' If the image you are about to provide me with has not changed since December 31st, do not send it again."
This approach saves data by avoiding the need to resend images that the client already has. Informing the server about existing images is accomplished without maintaining the state on the server because each request is self-sufficient and does not rely on the server-side stored state. The server is informed through the request that the image already exists locally. Network resources are saved by not downloading the image again. This is done using standard HTTP caching headers like If-Modified-Since or ETag.
If the server's resource has not changed since the specified date or ETag, it will not resend it. Instead, the server might return a 304 Not Modified status, indicating that the cached version can be used.
Even though the state is not maintained on the server between requests, actions are performed efficiently. By designing the request architecture thoughtfully, unnecessary data transfers, like re-downloading images, are avoided, saving significant bandwidth.
Having covered the technical aspects, let us discuss the advantages that statelessness brings to REST APIs.
Advantages of Statelessness
One advantage is saving internet bandwidth by maintaining a stateless architecture. Additionally, server resources are conserved and performance is improved. The server's CPU load decreases because it does not need to maintain client-specific session states. It recognizes that each incoming request contains all the necessary information. Storage is saved, and server performance is enhanced by reducing CPU cycles.
Conversely, it is important to understand the potential challenges that arise if REST APIs were not stateless.
Potential Issues Without Statelessness
Large platforms like Amazon, YouTube, or Google Drive that handle millions and millions of requests per second from millions of users, if each of those requests required maintaining a state on the server, the amount of data storage needed would be astronomical.
To further illustrate the importance of statelessness, let us examine how scalability and resource management are handled in large-scale services.
Scalability and Resource Management
When algorithms predict user preferences, such as showing ads on Facebook based on activities, does Facebook store a detailed state for each user indicating their preferences?
No.
While Facebook stores user data for personalization, it does not rely on server-side sessions to maintain states between requests. In this particular example, Facebook might send a Response Header to the user on login. This header serves as a Group Number assigned to the user. Several users can have the same group numbers justifying their similarity in interests. These group numbers relate a user irrespective of their identity, to the preferences.
Conclusion
Maintaining a server-side state for every interaction would render the internet non-functional as it operates today. By keeping requests stateless but self-sufficient, services can scale to millions of users without overburdening the servers.
REST APIs operate effectively by maintaining statelessness. The advantages and potential issues of not being stateless, including scalability challenges, have been discussed. The topic encompasses multiple concepts like tokens, cookies, and sessions that lead to extensive discussions. However, the provided information offers a strong understanding of what statelessness in REST APIs entails.