Hypermedia
APIs of the Web
Sébastien Cevey
APIDays / APIStrat
Berlin, 24th April 2015
About me
Sébastien Cevey
Hypermedia
APIs
REST
“REpresentational State Transfer”
Architectural style inspired by the design of the Web
(Roy Fielding's dissertation, 2000)
RESTful API
REST applied to design scalable APIs
Pick a baseline network protocol
0. HTTP protocol*
POST /getImage imageId = 123
client
server
{ ... }
* not necessarily HTTP, but usually is
Model “things” as Resources
Give Resources a Uniform Resource Identifier
1. URIs
GET
client
server
{ ... }
/images/123
Map actions to HTTP methods
2. Verbs
GET POST PUT PATCH DELETE
retrieve
create/update
replace
partial update
delete
PUT { ... }
client
server
{ ... }
/images/123
No, we’re not done yet.
Hypermedia
Key constraint of REST and the Web
“the simultaneous presentation of information and controls such that the information becomes the affordance through which the user obtains choices and selects actions”
(Fielding, 2008)
Hypermedia API ≈ strict REST API
3. Hypermedia Controls
<article class="image">
<img src="http://example.io/cat.jpg" width="800" height="600">
<a href="/images/123/crops">crops</a>
<form action="/images/123" method="POST">
<div>Resize dimensions</div>
<label><input name="width" type="number"> width</label>
<label><input name="height" type="number"> height</label>
<input type="submit" value="Update">
</form>
</article>
Embed controls in API response:
- Links to related resources
- Forms to describe actions
API optimised
XML or JSON
+
Hypermedia semantics
Media-Types
{
"properties": {
"type": "image",
"url": "http://example.io/cat.jpg",
"width": 800,
"height": 600,
},
"links": [
{ "rel": ["crops"], "href": "/images/123/crops" }
],
"actions": [{
"name": "resize",
"title": "Resize dimensions",
"href": "/images/123",
"method": "POST",
"fields": [
{ "name": "width", "type": "number" },
{ "name": "height", "type": "number" }
]
}]
}
Content-Type: application/vnd.siren+json
“HATEOAS”
Hypermedia As The Engine Of Application State
GET
client
server
/
/
/
client.resource('https://api.media.gu.com');
theseus (JavaScript library for argo APIs)
Follow link
GET
client
server
/images/123
/images/123
/images/123
/
resource.follow('image', {id: '123'});
{
"data": {
"description": "This is the Media API"
},
"links": [
{"rel":"image", "href": "/images/{id}"},
{"rel":"cropper","href":"https://cropper.media.gu.com"},
...
]
}
/
PATCH
/images/123
{width: 300,
height: 400}
client
server
/images/123
/images/123
Update state
resource.perform('resize', {
width: 300,
height: 400
});
{
"data": {
"src": "http://example.io/cat.jpg",
"width": 600,
"height": 800,
"credit": "Graham"
},
"actions": [{
"name": "resize",
"title": "Resize dimensions",
"method": "PATCH",
"href": "/images/123",
"fields": [
{ "name": "width", "type": "number" },
{ "name": "height", "type": "number" }
]
}]
}
/images/123
/images/123
/images/123
State transfer
Resources as state
Model state on client and server
Hypermedia as affordances
Links to other resources
Forms to describe available actions on resources
Verbs to transfer
Synchronise state between client and server
Apply changes to both
Benefits of Hypermedia APIs
“The best network-based
application performance is obtained by not using the network”
Cacheable
client
server
/images/123
browser cache
CDN edge cache
caching proxy
client
server
app cache
server cache
Hypermedia
RPC
HTTP POST, TCP
Cacheable
0
1
Uniform HTTP interface, standard semantics
Resource URI as cache key
Verb semantics: GET is safe & idempotent
2
Layer standard HTTP components
CDN, proxy, server, etc.
Control caching from the server
Headers: Cache-Control, Vary, E-Tag, etc.
Transparently respected downstream
Cache stories
theguardian.com
Edge cache JSON
Control TTL with headers
zik.ca
Serve expensive responses
from file on disk
Split out and link to
dynamic part of response
Discoverable
URI as explicit reference (unlike IDs)
Links and forms self-documenting (in-band)
1
3
Web-like
Browse API from the root or any resource
Submit forms while exploring in browser
Resource address returns its data
Discoverable
API federation
Links to Media API from our Content API
Self-service
Give root of the Media API
to other teams
Service index in Media API
Discoverable
API as UI
Use content negociation
JSON ⇒ HTML
URI templates ⇒ forms
Evolveable
Persistent URIs
Clients rely on links, not out-of-band config
Extensible
Add data properties
Add links & form fields
Ignored if unsupported
Server configures clients
Only config is API root
No URL construction
Change link targets transparently
1
3
Composeable
Add new services via links and forms
Shared media-type helps
Avoids monolithic library
Simple
Plain HTTP
JSON or XML + Hypermedia layer
Visibility
Send URL around
Server request logs
Browser network panel
Wireshark
Scalable
cURL
Bookmarklets
Apple Scripts
Small web clients
Mobile apps
Large single-page apps
0
3
1
2
Authoritative
Conditional links/forms drive the UI
Based on permissions, business logic
Avoids hardcoding rules in both server & client
Server rules can change, apply to all clients
if valid, expose link
if invalid, omit link
Requirement:
can only crop valid images
Links & forms as affordances
3
Forms drive client-side validation
Expose constraints in form fields
Apply to HTML UI form
Avoids hardcoding rules in both server & client
R&D
e.g. required, min/max length, “email”, etc
Authoritative
Limitations
Performance
Serialisation/Deserialisation
Payload size
Plain JSON: 23.0KB
Argo+JSON: 37.4KB
+40%
gzipped
4.4KB
5.1KB
+15%
No data schema
Versioning
State transfer model
Avoid side-effects
Poll, no PUSH
Weak tooling
References
RESTful Web APIs
Leonard Richardson, Mike Amundsen
Richardson Maturity Model
Martin Fowler
Hypermedia
Uniform HTTP interface
Cacheable for performance
Simple to integrate and debug
Resources model state
Verbs transfer state
Hypermedia controls as affordances
Discoverable for developers
Dynamic link structure allows evolveability
Authoritative source of client actions through forms
Thank you!
Sébastien Cevey
Hypermedia: APIs of the Web [APIDays/APIStrat Berlin '15]
By Sébastien Cevey
Hypermedia: APIs of the Web [APIDays/APIStrat Berlin '15]
- 7,197