11436 SSO

API Design: Ruminating Over REST

Brian Mulloy
Jun 11, 2013

Over the next several blog posts, we’d like to discover what hypermedia as the engine of application state, or HATEOAS (“Hay-dee-us”), means. We'll start by considering each of the six constraints of the architectural style of REST as defined by Roy Fielding in his PhD dissertation, with an emphasis on HATEOAS.

The Constraints of REST

  1. Client-server
  2. Stateless server
  3. Cache
  4. Uniform interface
    a. Identification of resources
    b. Manipulation of resources through representations
    c. Self-descriptive messages
    d. Hypermedia as the engine of application state or HATEOAS
  5. Layered system
  6. Code-on-demand (optional)

Client-Cache-Stateless-Server Architecture

The first three constraints—client-server, stateless server, and cache—combine to give us the robust client-cache-stateless-server architecture that allows today’s Web to scale. Requests travel to and exchange information with the server. The server does not store data from client requests, but the client can reuse response data, sent by the server, by storing it in a local cache.

Let’s move on to the layered systems  constraint; we’ll save the uniform interface constraint for a later discussion.

Layered System Architecture

The layered systems constraint lets us add features like a gateway, a load balancer, or a firewall to accommodate system scaling. Layers can encapsulate legacy services and protect new services from legacy clients. Each layer is also limited to communication with its immediate neighbors. The trade off is reduced performance from increased levels of indirection associated with multiple layers.

Code-on-Demand Architecture

The optional code-on-demand constraint allows clients to request and execute code from servers. This, in turn, allows the server to deploy new features to clients. The result is improved extensibility and configurability for servers, and improved performance and efficiency for clients. From an API perspective, JavaScript returns an HTTP response that is executed on a local Web browser.

Our Focus: Uniform Interface Constraint

The four parts of the uniform interface constraint are resource identifiers, resource representations, self-descriptive messages, and HATEOAS. We’ll save HATEOAS for a later discussion.

Resource Identifier

Resource identifiers interact between components. On today’s Web, they are expressed as:


Resource Representations

<!DOCTYPE html>
<html data-nav-highlight-class-name="highlight-global-nav-home">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta charset="utf-8" />
    <meta name="description" content="Instantly connect to what&#39;s most important to you. Follow your friends, experts, favorite celebrities, and breaking news." />
  <link rel="dns-prefetch" href="http://a0.twimg.com"/>
  <link rel="dns-prefetch" href="http://api.twitter.com"/>
<script type="text/javascript" charset="utf-8">
  document.domain = 'twitter.com';
  // this will be copied to twttr.appStartTime once our JS has started up
  document.startTime = new Date().getTime();
  var twttr = {};
  twttr.versionName = 'phoenix';
  twttr.isT1 = true;
  twttr.didPingKeynote = false;
  twttr.keynoteTTFTPing = function() {
    if (!twttr.didPingKeynote && window.location.href.indexOf('keynoteTest') > 0) {
      var image = document.createElement('img');
      image.src = '/images/keynote.gif';
      twttr.didPingKeynote = true;
  window.console||function(){var a=["log","debug","info","warn","error","assert","dir","dirxml","group","groupEnd","time","timeEnd","count","trace","profile","profileEnd"];window.console={};for(var b=0;b<a.length;++b)window.console[a[b]]=function(){}}();

Resource representations are the state of a resource that is transferred between components. The code above, shows an example of an HTML and JavaScript that is returned from the first ever tweet on Twitter. As requests arrive, the elements that fulfill these requests are presented. For example, using a modern API use case, your OAuth credentials travel with your request, rather than being saved on a server.

Self-Descriptive Messages

GET /#!/jack/status/20 HTTP/1.1
User-Agent: Chrome/18.0.1025.11
Host: twitter.com
Accept: text/html

Self-descriptive messages contain metadata to describe the meaning of the message. The methods used to invoke the message must be standard and agreeable between the first three constraints - client-server, stateless server, and cache.

To join the conversation around APIs, check out the API Craft Google Group and the IRC Channel #api-craft on freenode.

For further reading, see:

A special thanks to the api-craft Google group, who helped pull this content together.

Next: API Design: Honing in on HATEOAS

Scaling Microservices