REST is more than just JSON or XML over HTTP. In this presentation we take a closer look how to use links (hypermedia) when designing your RESTful API. Not only does this make your service discoverable and self-descriptive, but it also makes life easier for client developers as the business logic is simply checking the presence or absence of links (HATEOAS).
The presentation is based on a sample application including real business logic and not just basic collection CRUD! We also explore what mediatypes exists for hypermedia and when to use them.
2. Hypermedia API:s @ Jayway
Rickard Öberg (~2010)!
Qi4j & Streamflow!
Usecases as your API!
Mattias Arthursson & Karl-Johan Stenflo (~2011)!
JAX-RS-HATEOAS!
HATEOAS with Standard Java APIs!
Mads Enevoldsen & Jan Kronquist (~2011)!
Forest (CQS conventions, sensible default links, constraints...)!
Gustaf Nilsson Kotte (~2012)!
Adaptive HTML as your API
9. Playing the game
Player A
Player B
Server
rock
paper
Player B: paper
Player A: rock
Game 123
Game 123
winner: Player B
loser: Player A
CREATED WAITING
GAME WON
GAME TIED
any move
other move
(victory)
other move
(tie)
T
11. Towards REST
REST architectural style!
Defined by Roy Fielding !
Richardson maturity model
http://martinfowler.com/articles/richardsonMaturityModel.html
12. Level 0 - Not at all RESTful
Single resource, single verb!
Examples:!
SOAP, XML-RPC, JSON-RPC
18. Level 1 - Analysis
Still just using HTTP as transport
19. Level 2 - Verbs
Resources, verb and status codes!!
GET, POST, PUT, DELETE...
200 OK, 304 Not Modified, 404 Not found…
RESTish!
Uniform interface
20. HTTP 101
GET - safe!
POST - danger!!
PUT - idempotent!
!
Note!
GET will not modify the resource, but other clients might!
Interleaving other requests might break idempotency
21. GET /api/games/123
<-- 200 OK
<-- { "state": "waiting"}
POST /api/games/123
--> { "move": "rock"}
<-- 200 OK
<-- { "state": "won",
"winner": "player1",
"loser": “player2"}
Level 2 - Example
22. GET /api/games/123
<-- 200 OK
<-- { "state": "waiting"}
POST /api/games/123
--> Content-Type: application/json
--> { "move": "rock"}
<-- 200 OK
<-- { "state": "won",
"winner": "player1",
"loser": "player2"}
Level 2 - Mediatype json
23. Level 2 - Mediatype form
GET /api/games/123
<-- 200 OK
<-- { "state": "waiting"}
POST /api/games/123
--> Content-Type: application/x-www-form-urlencoded
--> move=rock
<-- 200 OK
<-- { "state": "won",
"winner": "player1",
"loser": "player2"}
$ curl -d move=rock http://rps.com/api/games/123
24. Level 2 - In the wild
Verbs: GET, DELETE, PUT!
Resources: buckets, objects, acls, policies…!
Why?!
CRUD operations!
GET allows caching
25. Level 2 - Analysis
Using HTTP, not fighting it!
Problems!
Client must construct URLs!
Client must contain business rules
26. GET /api/games
<-- 200 OK
<-- { "totalCount": 23,
"offset": 0,
"pageSize": 10,
"items": [{"id": "111",
"players": ["jan", "cecilia"]},
{"id": "222",
"players": ["jan", "mike"]},
{"id": "333",
"players": ["cecilia", "mike"]},
...]}
Level 2 - Constructing URLs
GET /api/games?offset=10 GET /api/games?page=2
How to navigate to page 2?
27. GET /api/games
<-- 200 OK
<-- { "totalCount": 23,
"offset": 0,
"pageSize": 10,
"items": [{"id": "111",
"players": ["jan", "cecilia"]},
{"id": "222",
"players": ["jan", "mike"]},
{"id": "333",
"players": ["cecilia", "mike"]},
...]}
Level 2 - Constructing URLs
GET /api/games/{game.id}
Navigating to game
28. Level 2 - Business logic
GET /api/games/123
<-- 200 OK
<-- { "state": "waiting",
"players": ["ply1", "ply2"],
"moves": { "ply1" : true}
}
Should the client display the move selector?
29. Level 2 - Business logic solved?
GET /api/games/123
<-- 200 OK
<-- { "state": "waiting",
"players": ["ply1", "ply2"],
"moves": { "ply1" : true},
"shouldMove": true
}
30. Level 3 - Hypermedia Controls
Links & forms!
REST as defined by Roy Fielding
Hypermedia is defined by the presence of application control information embedded within, !
or as a layer above, the presentation of information
The simultaneous presentation of information and controls such that the information
becomes the affordance through which the user obtains choices and selects actions.
34. Level 3 - Changing the rules
For one of the players: Flip a coin!
head - he must play rock!
tail - he can play whatever he wants!
!
How can the other player take advantage of this?
http://blog.gtorangebuilder.com/2014/04/gto-brain-teaser-1-exploitation-and.html
<select name="move">
<option value="rock">Rock</option>
</select>
42. Anatomy of a Link
target url (href)!
human readable string (title)!
semantic information (rel)!
returned media types (type)!
!
http method (method)!
secondary key (name)!
support media types for requests (accept)
RFC 5988
48. Forced resource structure
Collection
of games
/api/games/
Game 111
/api/games/111
Collection of
moves for game
111
/api/games/111/moves
Player 1 move
for game 111
/api/games/111/moves/ply1
item
rps:moves
item
49. GET /api/games/111
<-- 200 OK
<-- Content-Type: application/vnd.collection+json
<-- { "collection": {
"version" : "1.0",
"href" : "http://rps.com/api/games/111",
"links" : [
{"rel" : "rps:moves", "href" : "/api/games/111/moves"}
],
...
}
}
The game links to moves
51. URI templates
Constructing paths
Form-style!
Making a move
Creating a new game
RFC 6570
"http://rps.com/api/games/111{?move}"
"http://rps.com/api/games/{gameId}"
"http://rps.com/api/games{?player1,player2}"
58. Summary
Hypermedia simplifies client development!
No constructing of URLs!
Opportunities for less business logic!
Pick a mediatype with reasonable semantics!
Consider form-encoded when POSTing!
Some useful tools!
CURIE, URITemplates