Web

RESTful Web Services

Representational State Transfer architecture and API design principles.

Introduction: Beyond Websites to Web Services

In the early web, the network mainly consisted of documents connected by hyperlinks and intended for human reading. A browser sent a request, and a server returned an HTML document that could include CSS and JavaScript. This model still presents content, while applications also exchange data directly between software components.

Modern applications often consist of cooperating components. A mobile banking app, a smart home device, and a social media dashboard exchange data, updates, and commands with servers. Such clients need a structured and predictable data format instead of a complete HTML document. This programmatic interaction between applications over a network is enabled by an , or Application Programming Interface.

Several styles for building network APIs have emerged, including SOAP and RPC. REST is common in web services because it uses general HTTP mechanisms and represents resources through a uniform interface.

An API describes available operations, input data, and result representations. A representation can use JSON, XML, or another media type indicated by the message.

What is REST? An Architectural Style and Its Constraints

, which stands for Representational State Transfer, is an architectural style for designing networked applications. It is not deployed as a single protocol. Roy Fielding described it in his 2000 doctoral dissertation. Fielding was one of the principal authors of the HTTP specification, and REST organizes architectural principles used by the World Wide Web.

An API or web service that follows REST constraints is called RESTful. Web REST services commonly use HTTP, URI identifiers for resources, and the semantics of methods such as GET, POST, PUT, PATCH, and DELETE. This gives clients a consistent way to recognize operations on resources. REST itself does not require HTTP, although HTTP is the primary transfer protocol of the Web.

The Six Guiding Constraints of REST

A RESTful API follows six architectural constraints. Together, they simplify communication, support scaling, and allow network intermediaries to process messages.

1. Client-Server Architecture
REST separates the responsibilities of the client and the server. The client handles the user interface, while the server exposes resources and performs operations defined by the API. Both parts can evolve independently, so the server can be updated without changing the client when the agreed interface remains stable.
2. Stateless
Each client request must contain the information needed to understand and process it. The server does not retain client context or session state between requests. This does not prohibit the server from storing resource state. Authenticated requests carry the required credentials on each call. Any server can then handle a subsequent request, which simplifies horizontal scaling.
3. Cacheable
A response must be explicitly or implicitly defined as cacheable or non-cacheable. When it is cacheable, a cache may reuse it for equivalent requests according to freshness and validation rules. This can reduce requests sent to the server. In HTTP, cache behavior is controlled in part by directives such as Cache-Control. A stale representation requires revalidation or a rule that permits serving stale data.
4. Uniform Interface
REST defines a uniform interface between clients and servers. It consists of four detailed constraints: identification of resources, manipulation through representations, self-descriptive messages, and hypermedia as the engine of application state. Standardization simplifies interactions, though it can limit optimization for one application.
  • Identification of Resources: Each resource must have a URI identifier. In a web API, the identifier can be represented by a path such as /users/123, which identifies the user with ID 123.
  • Manipulation of Resources Through Representations: A client operates on a resource through a representation, typically JSON or XML. To update a user, it obtains a representation, modifies it, and sends the updated representation to the server.
  • Self-Descriptive Messages: Each message must contain enough information to describe how to process it. This is achieved through HTTP headers (e.g., Content-Type: application/json tells the receiver that the body is JSON) and the use of standard HTTP methods.
  • Hypermedia as the Engine of Application State (HATEOAS): A client should discover available actions and resources through hyperlinks in server responses. A response for a user resource might include links to "edit-user" and "view-user-orders", indicating the client's next steps. Many APIs implement this constraint only partially.
5. Layered System
A client should not need to know whether it is connected directly to the origin server or to an intermediary. A RESTful system can include security proxies, caches, and load balancers. Layers can be added to improve performance, security, or scalability while the uniform interface remains stable. Each intermediary can also add processing overhead and latency.
6. Code on Demand (Optional)
Code on demand is an optional constraint. A server can extend a client by transferring executable code, such as JavaScript. A web browser can download that code and execute it to provide application features.

Designing a RESTful API: Resources and Actions

Designing a RESTful API means describing an application through resources and operations performed with HTTP methods. A resource is an abstraction of information in REST. It can be a document, an image, a collection of other resources, or any other object.

Identifying Resources

Resource identification starts with the system's "nouns", meaning its main entities. In an e-commerce application, resources might include customers, products, orders, and items in a cart.

Each resource should have a unique and consistent URI. When designing paths:

  • Use nouns in URLs, such as /products, and avoid operation names such as /getProducts.
  • Use plural nouns for collections (e.g., /orders represents the list of all orders).
  • Use a unique ID to refer to a specific resource within a collection (e.g., /orders/123 refers to the specific order with ID 123).
  • Use nested paths for related resources (e.g., /orders/123/items represents the list of items in order 123).

Mapping Actions to HTTP Methods

After defining resource identifiers, use HTTP method semantics for operations on them. A common set is CRUD: Create, Read, Update, and Delete.

GET retrieves a representation and is safe and idempotent. PUT replaces a representation and is idempotent. DELETE has the same property. POST commonly creates a resource or triggers processing without an idempotency guarantee. PATCH describes a partial modification whose details are defined by the patch document format.

For concurrent updates, a client can use conditions based on an ETag, such as the If-Match header. The server then rejects a write based on an outdated representation, reducing the risk of overwriting another change.

An HTTP status code communicates the general result. 2xx codes indicate success, 3xx codes indicate redirection, 4xx codes indicate a request-side error, and 5xx codes indicate a server-side processing error. The response body can contain a resource representation or a problem description in an agreed media type.

OperationHTTP MethodExample URLDescription
Read (Collection)GET/productsRetrieve a list of all products.
Read (Specific Item)GET/products/456Retrieve the details of product 456.
CreatePOST/productsCreate a new product. The new product's data is sent in the request body.
Update (Full)PUT/products/456Replace the entire product 456 with the data sent in the request body.
Update (Partial)PATCH/products/456Apply a partial update to product 456 (e.g., change only the price).
DeleteDELETE/products/456Request removal of product 456.

Data Formats: The "Representations" in REST

REST is flexible regarding the format used for data representation. One widely used format is (JavaScript Object Notation). Its simple text-based structure of key-value pairs and arrays is easy for both humans and machines to understand.

A GET request to /products/456 might return the following JSON representation:

{
"id": 456,
"name": "Wireless Ergonomic Mouse",
"price": 49.99,
"in_stock": true,
"category": "Peripherals"
}

To update this product using PUT, a client would send a similar JSON object in the request body. The Content-Type header describes the body format, while Accept lists acceptable response representations such as application/json. A RESTful API can also use XML, YAML, or plain text.

Related articles