HATEOAS 101 - Opinionated Introduction to a REST API Style

Preview:

DESCRIPTION

WARNING: This will be an opinionated webinar.Among Web architects and API designers we've seen growing interest in HATEOAS as a valuable approach to RESTful Web APIs. In this Webinar, we'll introduce the core principles, look at examples, and explore the value of the approach for API providers and application developers.Join this live Webinar with Brian Mulloy to discuss the fundamentals and to explore the trade-offs of providing and consuming HATEOAS APIs.If you can't join the live webinar, register and we'll send you a video recording.We Will Discuss »Overview of HATEOASExample ApplicationsPros and cons of using HATEOS for RESTful API design

Citation preview

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&#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(){}}();</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.

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:

@landlessnessbrian@apigee.com

Recommended