RESTful
This note is complete, reviewed, and considered stable.
REST (Representational State Transfer) is an architectural style for designing networked applications. It is based on a set of constraints and principles that make it suitable for creating scalable, reliable, and stateless web services. RESTful APIs (Application Programming Interfaces) are those that conform to the REST principles.
The RESTful approach to building web services is commonly used in web applications because it leverages the stateless nature of HTTP and is simple to implement and use. RESTful APIs are typically used for creating web services that interact with databases or other services in a client-server model.
Core Principles of REST
REST is not a protocol or a standard; rather, it is an architectural style that promotes a set of constraints. These constraints are as follows:
-
Stateless: Each request from a client to a server must contain all the necessary information to understand and process the request. The server should not store any client context between requests. Each request is independent, meaning that the server doesn’t need to retain any session information between requests.
-
Client-Server: RESTful APIs follow the client-server model. The client (typically a browser or mobile application) interacts with the server (where the data or resources reside). The client and server communicate via HTTP, but the server does not need to know anything about the client beyond the request.
-
Uniform Interface: RESTful APIs define a uniform interface for communication between clients and servers. This means that the API design is consistent and predictable, and clients interact with the resources in a standard way (e.g., via HTTP methods like GET, POST, PUT, DELETE).
-
Cacheable: Responses from the server should explicitly state whether they can be cached or not. Caching can improve the performance of the system by reducing the need for redundant requests. It can be done at the client-side, server-side, or in intermediary caches.
-
Layered System: REST allows an architecture to be composed of multiple layers, where each layer has a distinct role and functionality. For example, an intermediary server could be used for load balancing, caching, or security enforcement, without the client needing to be aware of these intermediate layers.
-
Code on Demand (optional): In some cases, the server can provide executable code (such as JavaScript) to the client, which can be executed on the client-side. This is an optional constraint and is rarely used in practice but adds flexibility to RESTful APIs.
HTTP Methods in RESTful APIs
The HTTP methods are used to define the actions that can be performed on resources in a RESTful API. These methods correspond to the CRUD (Create, Read, Update, Delete) operations:
- GET: Retrieves data from the server (e.g., fetching a resource or a list of resources). It is a read-only operation and should not modify the resource.
- POST: Submits data to the server to create a new resource. It is used when adding new data to the server (e.g., creating a new record in a database).
- PUT: Updates or replaces a resource on the server. It is typically used to update an existing resource or create a new resource if it does not already exist.
- DELETE: Removes a resource from the server. It is used to delete a specific resource.
- PATCH: Partially updates a resource, as opposed to PUT, which replaces the entire resource.
Resources in RESTful API
In the context of REST, resources are the key abstractions. A resource is any piece of information that can be named and represented, such as data or objects. Each resource should be identified by a unique URI (Uniform Resource Identifier), typically in the form of a URL.
Examples of resources:
- A user resource:
http://example.com/users/123 - A book resource:
http://example.com/books/456
These resources can be operated on using the standard HTTP methods (GET, POST, PUT, DELETE, PATCH).
Response Format
RESTful APIs typically use JSON or XML as the data format for responses. JSON is the most commonly used format because it is lightweight and easy to work with in modern web applications.
Example response in JSON:
{
"id": 1,
"name": "John Doe",
"email": "john.doe@example.com"
}
The response will also include HTTP status codes that indicate the result of the operation:
- 200 OK: The request was successful and the response contains the requested data.
- 201 Created: The request was successful and a new resource has been created.
- 400 Bad Request: The request was malformed or invalid.
- 404 Not Found: The resource could not be found.
- 500 Internal Server Error: There was a server-side error.
RESTful URL Design
The design of the URLs is an essential part of RESTful APIs. URLs should represent resources and should be easy to understand and follow. Some best practices include:
- Use nouns to represent resources (e.g.,
/users,/products,/orders). - Use plural nouns for collections of resources (e.g.,
/usersfor a collection of users,/users/123for a specific user). - Avoid verbs in the URL, as the HTTP methods (GET, POST, PUT, DELETE) already define the actions to be performed.
Examples of good URL design:
/users– A collection of users/users/123– A specific user with ID 123/orders/456/items– A collection of items in an order with ID 456
RESTful API Benefits
- Scalability: REST APIs are stateless and can handle a large number of requests efficiently.
- Simplicity: RESTful APIs are simple to understand and use, as they rely on standard HTTP methods.
- Flexibility: REST allows different types of clients (web browsers, mobile apps, etc.) to interact with the same server using the same API.
- Interoperability: Since REST is based on HTTP, it can be used across different platforms and programming languages.
RESTful API Example
Here’s a simple example of a RESTful API for managing users:
- GET /users: Retrieves a list of all users.
- POST /users: Creates a new user.
- GET /users/123: Retrieves a specific user with ID 123.
- PUT /users/123: Updates the information of the user with ID 123.
- DELETE /users/123: Deletes the user with ID 123.
Stateless vs Cookies
REST requires that each request contains all the information needed for the server to process it. The server should not maintain conversational state between requests.
Using cookies does not automatically violate REST principles. A cookie is simply another HTTP header used to transmit data.
Stateful Session (Not RESTful)
If a cookie contains a session ID, the server must look up session data stored in memory or a database.
Client
|
| Cookie: session_id=abc123
|
Server
|
| Lookup session
| Restore user state
Since the server relies on stored session state, this does not satisfy REST's stateless constraint.
Stateless Authentication (RESTful)
Cookies can also be used to carry self-contained credentials, such as a signed JWT or refresh token. The server validates the token from the request without restoring any conversational session.
Client
|
| Cookie: refresh_token=...
|
Server
|
| Validate token
| Issue new access token
In this case, the cookie is merely a transport mechanism, and the request remains self-contained.
A cookie itself does not make an API stateful. What matters is whether the server must maintain per-client session state between requests.
Sessions and REST
Traditional web applications often use server-side sessions for authentication and user state management. The client receives a session ID (typically stored in a cookie) and sends it with every request. The server then uses the session ID to retrieve user context from a session store such as memory, Redis, or a database.
Client
|
| Cookie: session_id=abc123
|
Server
|
| Lookup session
| Restore user context
This approach violates REST's stateless constraint because the server must maintain and restore per-client session state between requests.
In contrast, a stateless REST API includes all information required to process a request within the request itself, often using self-contained tokens such as JWTs.
Client
|
| Authorization: Bearer <JWT>
|
Server
|
| Validate token
| Process request
Storing application data in a database is compatible with REST. What REST discourages is maintaining per-client conversational state on the server between requests.