Exploring REST API Architecture

When building APIs to handle HTTP messages we’re faced with decisions about URL route structures, request methods, headers, payloads, status codes, safe and idempotent behavior, and more. Which if any of these are REST principles? In this post we’ll look at the initial REST architecture proposed by it’s inventor, Roy Fielding, including resources, representations, and examples.

REST Constraints #

Fielding outlines REST as an architectural style for distributed applications with 6 constraints[1].

layers5.png

Advantages #

We can see some advantages.

Fielding wrote REST architecture “ignores details of protocol syntax and component implementation”[1]. 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[1]. 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,

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 perform actions 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[1]. 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.

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 given representation.
PUT Overwrite a current resource with given representation.
PATCH Partially modify a current resource with given representation.
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.

movie5.jpg

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 servers know best what state transitions and resources are available. 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. Period.

He later explains hypertext as presentation of information and controls such that the information becomes the affordance through which the user (or automaton) obtains choices and selects actions.

As examples see links in these 2 response bodies.

Request

GET /orders/523 HTTP/1.1
Host: www.example.com
Accept: application/hal+json

HAL - Hypertext Application Language

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
}

[2]

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
      }
    }, 
    ...
  ]
}

[3]

How RESTful is that API? #

We can check how RESTful is an API from Fielding’s definition with some questions. The client-server constraint is a given.

In this post we covered Fielding’s initial REST architecture including constraints, resources, and representations. I hope you found something useful.

References #

[1] Fielding, Roy G. Chapter 5 Representational State Transfer (REST)

[2] JSON Hypertext Application Language

[3] JSON:API A specification for building APIs in JSON

 
32
Kudos
 
32
Kudos

Now read this

What’s “new” in JavaScript?

Few syntactic features highlight JavaScript’s object oriented nature more than the new operator. Many of us have been using it for years but do we really know what it does? In languages like Java it allocates memory for an instance... Continue →