Sébastien Cevey
APIDays / APIStrat
Berlin, 24th April 2015
Sébastien Cevey
“REpresentational State Transfer”
Architectural style inspired by the design of the Web
(Roy Fielding's dissertation, 2000)
REST applied to design scalable APIs
Pick a baseline network protocol
POST /getImage imageId = 123
client
server
{ ... }
* not necessarily HTTP, but usually is
Model “things” as Resources
Give Resources a Uniform Resource Identifier
GET
client
server
{ ... }
/images/123
Map actions to HTTP methods
GET POST PUT PATCH DELETE
retrieve
create/update
replace
partial update
delete
PUT { ... }
client
server
{ ... }
/images/123
No, we’re not done yet.
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
<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:
XML or JSON
+
Hypermedia semantics
{
"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
Hypermedia As The Engine Of Application State
GET
client
server
/
/
/
client.resource('https://api.media.gu.com');
theseus (JavaScript library for argo APIs)
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
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
Model state on client and server
Links to other resources
Forms to describe available actions on resources
Synchronise state between client and server
Apply changes to both
“The best network-based
application performance is obtained by not using the network”
client
server
/images/123
browser cache
CDN edge cache
caching proxy
client
server
app cache
server cache
Hypermedia
RPC
HTTP POST, TCP
0
1
Uniform HTTP interface, standard semantics
Resource URI as cache key
Verb semantics: GET is safe & idempotent
2
CDN, proxy, server, etc.
Headers: Cache-Control, Vary, E-Tag, etc.
Transparently respected downstream
Edge cache JSON
Control TTL with headers
Serve expensive responses
from file on disk
Split out and link to
dynamic part of response
URI as explicit reference (unlike IDs)
Links and forms self-documenting (in-band)
1
3
Browse API from the root or any resource
Submit forms while exploring in browser
Resource address returns its data
Links to Media API from our Content API
Give root of the Media API
to other teams
Service index in Media API
Use content negociation
JSON ⇒ HTML
URI templates ⇒ forms
Persistent URIs
Clients rely on links, not out-of-band config
Add data properties
Add links & form fields
Ignored if unsupported
Only config is API root
No URL construction
Change link targets transparently
1
3
Add new services via links and forms
Shared media-type helps
Avoids monolithic library
Plain HTTP
JSON or XML + Hypermedia layer
Send URL around
Server request logs
Browser network panel
Wireshark
cURL
Bookmarklets
Apple Scripts
Small web clients
Mobile apps
Large single-page apps
0
3
1
2
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
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
Serialisation/Deserialisation
Payload size
Plain JSON: 23.0KB
Argo+JSON: 37.4KB
+40%
gzipped
4.4KB
5.1KB
+15%
Avoid side-effects
Poll, no PUSH
RESTful Web APIs
Leonard Richardson, Mike Amundsen
Richardson Maturity Model
Martin Fowler
Cacheable for performance
Simple to integrate and debug
Discoverable for developers
Dynamic link structure allows evolveability
Authoritative source of client actions through forms
Sébastien Cevey