HATEOAS 101An Opinionated Introduction
Brian Mulloy@landlessness
Apigee@apigee
groups.google.com/group/api-craft
youtube.com/apigee
IRC Channel#api-crafton freenode
New!
WARNING: The author may betray a bias against the application of REST constraints to web APIs.
What is HATEOAS?
Hypermedia As The Engine Of Application State
Let’s put HATEOAS in the full context of REST.
The Constraints of REST
1. Client-server2. Stateless server3. Cache4. Uniform interface
a. Identification of resourcesb. Manipulation of resources through representationsc. Self-descriptive messagesd. Hypermedia as the engine of application state
5. Layered System6. Code-On-Demand (optional)
Let’s break it down.
The first three constraints…
1. Client-server2. Stateless server3. Cache
…give us the client-cache-stateless-server web architecture.
statelessserver
client
cache
client
cache
Each request must contain
all information. No stored context on the
server.
Client has the right to reuse
response data.
(we’ll come back to the 4th constraint)
The 5th constraint, Layered System, lets us add features like a gateway, load balancer and firewall.
client
Each layer cannot "see" beyond it’s
immediate neighbor.
statelessserver
statelessserver
statelessserver
loadbalancer
gatewayfirewall
Each layer provides services to it’s neighbors.
Layers can encapsulate legacy services & protect new services from legacy
clients.
The optional 6th constraint, Code-on-Demand, allows the client to request code from the server & execute it.
statelessserver
client
Better user-perceived performance and
efficiency
Add features to a deployed client, which provides for improved
extensibility and configurability
code
Now lets tackle the 4 parts of the 4th constraint,Uniform Interface
With help from the Twitter UI.
a. Resource Identifier identifies the particular resource involved in an interaction between components.
http://twitter.com/#!/jack/status/20
b. Resource Representation represents the state of a resource for transfer between components.
<!DOCTYPE html><html data-nav-highlight-class-name="highlight-global-nav-home"> <head> <title>Twitter</title><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta charset="utf-8" /> <meta name="description" content="Instantly connect to what'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(){}}();</script>…
c. Self-descriptive messages contains all the information necessary to complete transformations.
GET /#!/jack/status/20 HTTP/1.1 User-Agent: Chrome/18.0.1025.11Host: twitter.comAccept: text/html
d. Hypermedia as the engine of application state
state
state
state
state
state
transition transition
transitiontransition
The name ‘Representational State Transfer’ is intended to evoke an image of how a well-designed Web application behaves: a network of web pages (a virtual state-machine), where the user progresses through the application by selecting links (state transitions), resulting in the next page (representing the next state of the application) being transferred to the user and rendered for their use.
“
-Roy FieldingArchitectural Styles and the
Design of Network-based Software ArchitecturesChapter 6
States are web pages.
Transitions are hyperlinks.
The key to implementing HATEOAS is pretty simple
In each response message include the links for the next request message.
AppUser UI Server
AppDeveloper
REST Interface
BrowserApp
home connect discover search my profile direct messages
lists
help
google: jack’s first
tweet
keyboard shortcuts
settings
new tweet@jackFollow @jackadd or remove
from listsblock @jack
turn off retweets
retweet
reply to @jack
favorite about
tweet to @jack
sign outreport @jack
for spam
1 transition in, 32 transitions out
A quick aside
The three greatest inventions of all time are:
Bicycles
Beer
The Hyperlink
With a browser I can start at http://twitter.com
And navigate my way through every state of the entire Twitter application.
It’s amazing!
HATEOAS is not scary.
HATEOAS is the key constraint that makes surfing the web with a browser possible.
Let’s look at HATEOAS and APIs
With help from the Twitter API.
GET /1/statuses/show/20.jsonHTTP/1.1Host: api.twitter.com
{ "created_at": "Tue Mar 21 20:50:14 +0000 2006", "id": 20, "id_str": "20",
"text": "just setting up my twttr", "source": "web", "truncated": false, "in_reply_to_status_id": null, "in_reply_to_status_id_str": null, "in_reply_to_user_id": null, "in_reply_to_user_id_str": null, "in_reply_to_screen_name": null, "user": { "id": 12, "id_str": "12",
"name": "Jack Dorsey", "screen_name": "jack", "location": "San Francisco", "description": "Executive Chairman of Twitter, CEO of Square, a founder of both.", "url": null, "protected": false, "followers_count": 1935426, "friends_count": 1148, "listed_count": 17312, "created_at": "Tue Mar 21 20:50:14 +0000 2006", "favourites_count": 988, "utc_offset": -28800, "time_zone": "Pacific Time (US & Canada)", "geo_enabled": true, "verified": true, "statuses_count": 10894, "lang": "en", "contributors_enabled": true, "is_translator": false, "profile_background_color": "EBEBEB", "profile_background_image_url": "http://a0.twimg.com/images/themes/theme7/bg.gif", "profile_background_image_url_https": "https://si0.twimg.com/images/themes/theme7/bg.gif", "profile_background_tile": false, "profile_image_url": "http://a0.twimg.com/profile_images/1563216547/image_normal.jpg", "profile_image_url_https": "https://si0.twimg.com/profile_images/1563216547/image_normal.jpg", "profile_link_color": "990000", "profile_sidebar_border_color": "DFDFDF", "profile_sidebar_fill_color": "F3F3F3", "profile_text_color": "333333", "profile_use_background_image": true, "show_all_inline_media": true, "default_profile": false, "default_profile_image": false, "following": null, "follow_request_sent": null, "notifications": null }, "geo": null, "coordinates": null, "place": null, "contributors": null, "retweet_count": 5973, "favorited": false, "retweeted": false}
Uh oh. There are zero hyperlinks.
How many should there be to respect the HATEOAS constraint?
At least one.
{ "created_at": "Tue Mar 21 20:50:14 +0000 2006", "id": 20, "id_str": "20",
"text": "just setting up my twttr", "source": "web", "truncated": false, "in_reply_to_status_id": null, "in_reply_to_status_id_str": null, "in_reply_to_user_id": null, "in_reply_to_user_id_str": null, "in_reply_to_screen_name": null, "user": { "id": 12,
"link": ”http://api.twitter.com/1/users/show.json?user_id=12", "id_str": "12",
"name": "Jack Dorsey", "screen_name": "jack", "location": "San Francisco", "description": "Executive Chairman of Twitter, CEO of Square, a founder of both.", "url": null, "protected": false, "followers_count": 1935426, "friends_count": 1148, "listed_count": 17312, "created_at": "Tue Mar 21 20:50:14 +0000 2006", "favourites_count": 988, "utc_offset": -28800, "time_zone": "Pacific Time (US & Canada)", "geo_enabled": true, "verified": true, "statuses_count": 10894, "lang": "en", "contributors_enabled": true, "is_translator": false, "profile_background_color": "EBEBEB", "profile_background_image_url": "http://a0.twimg.com/images/themes/theme7/bg.gif", "profile_background_image_url_https": "https://si0.twimg.com/images/themes/theme7/bg.gif", "profile_background_tile": false, "profile_image_url": "http://a0.twimg.com/profile_images/1563216547/image_normal.jpg", "profile_image_url_https": "https://si0.twimg.com/profile_images/1563216547/image_normal.jpg", "profile_link_color": "990000", "profile_sidebar_border_color": "DFDFDF", "profile_sidebar_fill_color": "F3F3F3", "profile_text_color": "333333", "profile_use_background_image": true, "show_all_inline_media": true, "default_profile": false, "default_profile_image": false, "following": null, "follow_request_sent": null, "notifications": null }, "geo": null, "coordinates": null, "place": null, "contributors": null, "retweet_count": 5973, "favorited": false, "retweeted": false}
A few questions.
Now are we HATEOAS compliant?
If we add another link does it change the consuming application’s state machine?
Is it ok for the developer to ignore included links?
Can the developer add out-of-band links to her app?
What happens when an app relies on multiple APIs? Where is the state machine?
If the Twitter API had complied with HATEOAS
When Loren Brichter
Created Tweetie
Would he have been able to decide which user actions to include in his design?
Or would those decisions have been driven by the links in the response from the Twitter API?
Nearly all popular web UIs adhere to HATEOAS.
Nearly all popular web APIs violate HATEOAS.
Why?
Let’s examine the two worlds.
AppUser UI Server
AppDeveloper
REST Interface
BrowserApp
I decide where to click, aka
change state.
I craft the user experience, aka state diagram.
I guarantee hypermedia is engine of app
state
The person who crafts the experience (state diagram) and the app user have the REST interface between them.
And the hypermedia links are given directly to the app user at runtime.
So the hypermedia in each response message is genuinely the engine of application state.
This pattern is not limited to user interfaces.
We see the same pattern for syndication feeds.
Feed ReaderApp
AppUser
FeedServer
ContentPublisher
REST Interface
I decide where to click, aka
change state.
I craft stories, categories & related
media, aka state diagram.
I guarantee hypermedia is engine of app
state
But the world of apps and web APIs seems different.
App 1 AppDeveloper 1
AppUser
API Server
Interface
App 2 AppDeveloper 2
App 3 AppDeveloper 3
App 1 AppDeveloper 1
AppUser
API Server
Interface
App 2 AppDeveloper 2
App 3 AppDeveloper 3
I decide where to click, aka
change state.
I craft the user experience, aka state diagram.
I get no HATEOAS respect.
I craft the user experience, aka state diagram.
I craft the user experience, aka state diagram.
The person who crafts the experience (state machine) and the app user do not have the REST interface between them.
And the hypermedia links are not given directly to the app user at runtime.
Instead, the hypermedia are given to the developer at design time.
And the developer decides which states are possible for the app user at runtime.
We need a Yoda moment.
You must unlearn what you have learned.“-Yoda
I used to call the world of popular, non-HATEOAS, non-SOAP web APIs, Pragmatic REST.
Oops.
How do we answer the questions many API teams are asking
1. Should we go down the HATEOAS path?
As a practical matter, for many teams that previous question is the same as the next question.
2. Should we include links in our responses?
But they have different answers.
1. For an API to be HATEOAS-compliant it requires a client app that is also HATEOAS-compliant.
A user-interface app driven by web APIs would be akin to a feed reader for syndicated content.
But designed to handle generic web APIs.
RESTful APIClient App
AppUser
APIDeveloper
REST Interface
API Server
?
I decide where to click, aka
change state.
I craft a system of interrelated resources,
aka state diagram.
I guarantee hypermedia is engine of app
state
Special thanks to @elasticpath for this metaphor.
There are interesting non-UI applications as well.
However, the style does not assume that all applications are browsers. In fact, the application details are hidden from the server by the generic connector interface, and thus a user agent could equally be an automated robot performing information retrieval for an indexing service, a personal agent looking for data that matches certain criteria, or a maintenance spider busy patrolling the information for broken references or modified content [39].
“
-Roy FieldingArchitectural Styles and the
Design of Network-based Software ArchitecturesChapter 5
If you’re not going down the HATEOAS client path, should you include links anyway?
2. If you think including links in the API response will be helpful for developers at design time, then go for it.
But I wouldn’t call it HATEOAS because those links are probably not the engine of application state for the app user at run time.
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. Is there some broken manual somewhere that needs to be fixed?
“
-Roy Fielding“REST APIs must be hypertext-driven”Untangled: Musings of Roy T. Fielding
Here’s a call to action
We know what REST with the HATEOAS constraint is and isn’t.
We know what SOAP is and isn’t.
But we don’t have an intellectual framework for the way so many popular apps and web APIs work today.
We need a really smart person
Who cares about web APIs
To examine the constraints of REST
The Constraints of REST
1. Client-server2. Stateless server3. Cache4. Uniform interface
a. Identification of resourcesb. Manipulation of resources through representationsc. Self-descriptive messagesd. Hypermedia as the engine of application state
5. Layered System6. Code-On-Demand (optional) Applicable to APIs
at all?
What are the
HATEOAS app
characteristics?
If the API drives app state, are we still
respecting client-server separation?
While keeping in mind how custom apps are built by people using web APIs
App 1 AppDeveloper 1
AppUser
API Server
Interface
App 2 AppDeveloper 2
App 3 AppDeveloper 3
To give us a new foundation
The Constraints of ____
1. ???2. ???3. ???4. ???5. ???6. ???
So that we will have a better shared idea of what we’re really doing
We will be able to communicate more effectively
And we will be able to create more value for the planet and the people on it.
But please choose a nice, pronounceable acronym.
Further Exploring
• http://steveklabnik.com/• http://pinboard.in/u:earth2marsh/t:hateoas/• http://www.ics.uci.edu/~fielding/pubs/dissert
ation/top.htm
• http://martinfowler.com/articles/richardsonMaturityModel.html
• http://timelessrepo.com/haters-gonna-hateoas
Questions?
THANK YOUSubscribe to API webinars at:
youtube.com/apigee
THANK YOUIRC#api-crafton freenode
THANK YOUQuestions and ideas to:
groups.google.com/group/api-craft
THANK YOUContact me at: