Exploring REST API Architecture
When building APIs to handle HTTP messages we often set up URL structures, request methods, headers, payloads, response status codes, safe and idempotent behavior, and more. These HTTP features implement a set of interfaces for one of the most prominent API architectures, called Representational State Transfer. In Postman’s latest State of the API survey, REST is the dominant architectural style used by 93.4% of respondents[1]. So what makes APIs RESTful?
In this post we’ll look at the initial REST architecture introduced in Roy Fielding in his dissertation. We’ll cover REST constraints, resources, and representations, then HTTP examples, and a REST API checklist.
REST Constraints #
Fielding outlines REST as an architectural style for distributed applications with 6 constraints[3].
- Client-server architecture - The most straightforward constraint, the client-server model makes clients, e.g. browsers and crawlers, separate from data storage. Clients make requests to servers and receive responses.
- Caching - Responses are labeled as cacheable or non-cacheable and caching is restricted to the client or an intermediary between the server. This is referred as client-cache-stateless-server.
Layered System - A set of hierarchical layers restricts components to interact only with the adjacent layer. For example, a 4-tier architecture has the client layer, web server layer, API layer with caching, and data layer. Each of these interact with their adjacent layers. Intermediaries can include load balancers, proxies, and security.
-
Uniform Interface - A central feature of REST is a set of interfaces between clients and servers. These 4 interfaces listed include resources, representations, and hypermedia, which we’ll cover shortly.
- Resource identification
- Representations manipulate resources
- Self-descriptive request and response messages
- Hypermedia as the engine of application state
Stateless - The server is stateless as each request contains all data necessary for the server to fulfill it, rather than one request split and managed on the server across multiple partial requests. Session state is kept entirely on the client.
Code-On-Demand - An optional constraint. Clients can download and execute code in the form of applets or scripts.
Advantages #
We can see some advantages.
- Flexibility - Client/server design with uniform interfaces allow clients and servers to have different implementations and develop independently. A layered system enables intermediaries e.g. proxies, gateways, and firewalls without changing interfaces. Hypermedia-as-the-engine-of-application-state allows clients to decouple from servers. Stateless server enables intermediaries to view requests in isolation, which may be necessary when services are dynamically rearranged.
- Performance - Caching can significantly improve performance, especially when a layered system adds more network requests.
- Scalability - A stateless server model eases horizontal scaling, avoids shared state problems, and simplifies concurrent requests. A layered system allows hardware resources to scale at specific layers.
- Maintainability - Uniform interfaces include messages as self-descriptive and visible to intermediaries which helps for debugging and network tracing.
Fielding wrote REST architecture “ignores details of protocol syntax and component implementation”[3]. REST is an architecture, whereas HTTP is one implementation of the architecture. Each could be built independently.
Resources, URLs, and Representations #
Resources are a central feature to REST, abstractly defined as anything which can be data[3]. Examples are an image file, a POJO, a document, the distance from San Francisco to Tokyo.
URLs #
URLs can map to a single resource e.g. movie/1234
or a,
- collection resource - group of resource members of the same type e.g.
movies/
. - composite resource - group of different resources. e.g. a homepage with various components.
URL paths are named after resource attributes and we can think of them as nouns instead of verbs. Their paths are also structured hierarchically, in order of increasing specificity left to right. Some resource URL examples.
#profile resource
https://twitter.com/SpaceX
#profile photo resource
https://twitter.com/SpaceX/photo
#single tweet resource
https://twitter.com/SpaceX/status/15892
Representations #
Clients request actions to be performed on resources using representations, e.g. to retrieve, create, update, and delete. Abstractly, representations are key-value metadata and bytes that transfer state between clients and servers[3]. This metadata allows decision making about the bytes without parsing them.
A representation is information that reflects a past, current, or desired state of a given resource, in a format that can be readily communicated via the protocol. [RFC-7231].
Additionally, multiple types of representations could be used for a single request. Let’s look at an example.
Using HTTP #
Finally we’ll use HTTP to implement REST.
- Representation metadata = HTTP headers, response code, and status message.
- Representation bytes = HTTP message payload.
We covered resources and representations so request methods in the HTTP spec make more sense.
Method | Description |
---|---|
GET | Retrieve a current representation of the resource. |
POST | Create a new resource using the enclosed representation. |
PUT | Replace all current representations of the resource with the request payload. |
DELETE | Remove all current representations of the resource. |
HEAD | Same as GET, but only transfer the status line and header section. |
OPTIONS | Describe the communication options for the resource. |
[RFC7231]
Fielding also introduces media type
in REST. Check out how Accept
and Content-Type
headers relate to payload.
Request
GET /movie/1234 HTTP/1.1
Host: www.moviequotes.com
Accept: application/json
Response
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
{
"id": 1234,
"title": "Inception",
"quotes": [
"Dreams feel real while we're in them.
It's only when we wake up that we
realize something was actually
strange.",
"If you're going to perform inception,
you need imagination."
],
...
}
Request
GET /movie/1234 HTTP/1.1
Host: www.moviequotes.com
Accept: text/html
Response
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
<html>
<body>
<input type="hidden" id="id" value="1234"/>
<div class="title">
Inception
</div>
<ul class="quotes">
<li>Dreams feel real while we're in
them. It's only when we wake up that
we realize something was actually
strange.</li>
<li>If you're going to perform
inception, you need imagination.</li>
</ul>
...
</body>
</html>
You see how payload format changed in these GET requests to /movie/1234
? The client used Accept
to request the payload data format, also called media type. The server responded with Content-Type
that states the payload as JSON or HTML. Each of these response payloads and its HTTP headers – are different representations of the same resource.
Using HTTP to Choose a Representation #
Choosing the best representation goes beyond Accept
and Content-Type
when multiple representations are available. In server-driven content negotiation, these 4 HTTP request and 4 response headers are used.
Request Header | Response Header |
Effect | Example Values |
---|---|---|---|
Accept | Content-Type | Media type |
application/json application/javascript text/html text/css application/xml multipart/form-data
|
Accept-Language | Content-Language | Human language |
en-US, fr;q=0.9 en-GB zh
|
Accept-Encoding | Content-Encoding | Compression |
gzip, br compress deflate identity
|
Accept-Charset | Content-Type “charset” parameter |
Character encoding | text/html; charset=utf-8 |
Hypermedia as the engine of application state #
Hypermedia is content with non-sequential links to other content types e.g. pages, text files, PNG and JPEG images, video, and more. In short, the Web. To the user, clicking links on a website makes application state transitions.
Fielding says it’s essential for servers to return representations with links for clients, as server know next best available resources for users. Servers provide the engine of state changes e.g. HATEOAS. Fielding wrote,
What needs to be done to make the REST architectural style clear on the notion that hypertext is a constraint? In other words, if the engine of application state (and hence the API) is not being driven by hypertext, then it cannot be RESTful and cannot be a REST API.
Two hypermedia examples.
HAL - Hypertext Application Language #
Request
GET /orders/523 HTTP/1.1
Host: www.example.com
Accept: application/hal+json
Response
HTTP/1.1 200 OK
Content-Type: application/hal+json; charset=utf-8
{
"_links": {
"self": { "href": "/orders/523" },
"warehouse": { "href": "/warehouse/56" },
"invoice": { "href": "/invoices/873" }
},
"currency": "USD",
"status": "shipped",
"total": 10.20
}
JSON:API #
Request
GET /articles HTTP/1.1
Host: example.com
Accept: application/vnd.api+json
Response
HTTP/1.1 200 OK
Content-Type: application/vnd.api+json; charset=utf-8
{
"links": {
"self": { "href": "/orders/523" },
"warehouse": { "href": "/warehouse/56" },
"invoice": { "href": "/invoices/873" }
},
"data": [
{
"type": "orders",
"id": "1",
"attributes": {
"currency": "USD",
"status": "shipped",
"total": 10.20
}
},
...
]
}
The response payloads return hypermedia links with self, warehouse, and invoice links for user to click.
How RESTful is that API? #
Let’s bring Fielding’s definition of REST architecture concepts and APIs together. When looking at an API these questions can be used to figure how much REST constraints are applied. The client-server constraint is a given.
- Does the API use caching either by shared caches e.g. Redis, or browser caches with HTTP headers? (caching)
- Does the API have a single high-level purpose that contributes to (or able to support) a layered system? (layered system)
- Are resource URL paths labeled as nouns and structured hierarchically, increasing in specificity left to right? (uniform interface)
- If multiple representations of a resource are available, are they selected by HTTP headers e.g.
Content-Type
? (uniform interface) - Is the protocol implemented to it’s specification e.g. HTTP? This includes effective use of request methods like GET, POST, and PATCH. (uniform interface)
- Does the server provide links (hypermedia) to the client for application state changes? (uniform interface)
- Are servers stateless between requests with session state stored on the client? (stateless)
Maybe the definition of a REST API is changing. In this post we covered Fielding’s initial REST architecture including constraints, resources, representations. I hope you found something useful.
References #
[1] Postmans’ 2020 State of the API Survey
[2] Steven Holl, Linked Hybrid, Placesjournal
[3] Fielding, Roy G. Chapter 5 Representational State Transfer (REST)
[4] Inception, image from Subculture Media
[5] JSON Hypertext Application Language
[6] JSON:API A specification for building APIs in JSON