Links, forms and unicorns

Preview:

Citation preview

@serialsebseb@serialseb.com

http://codebetter.com/sebastienlambla/

Architect, trainer, speaker, developer, mayhem inducer…

by the people, for the people

Web Development Done Right

Building Hypermedia APIs

Why links and forms will make your ReSTful API better

Building Hypermedia APIs

Why links and forms will make your ReSTful API better

Links, forms and unicorns

Oh no!

Mission Completed

Agent Resty Galore

Your mission should you accept it…

• Go to Paris, give the agent your name and ask for his favourite monument

• Go to Brussels, tell the agent what you learnt, ask for their favourite food

• Go to Copenhagen, tell them what you learnt, ask for their favourite painter

• In Malmo, tell them what you learnt, receive the secret message

Your mission should you accept it…

• POST to /paris, expect {“status”: “ok”, “monument”: ??}

• POST to /brussels with {“monument”: ??}, expect {“status”: “ok”, “food”: ??}

• POST to /copenhagen with {“food”: ??}, expect {“status”:”ok”, “artist”: ??}

• POST to /malmo with {“artist”: ??}, expect {“status”: “ok”, “secret”: ??}

public void travel() { var response = _client .Post(“/paris”, new{name=“Pixie”}) .Send(); if (response.body.status == “ok”) { response = _client.Post(“/brussels”, new { monument=response.body.monument }).Send(); // etc }}

> POST /paris> {“name”: “resty galore”}

Oh no!

The French don’t speak English!(who knew!)

Oh no!

> POST /paris> {“name”: “resty galore”}

< 200 OK< {“status”: “oui”, “monument”: “eiffel tower”}

public void travel() { var response = _client .Post(“/paris”, new{name=“Pixie”}) .Send(); if (response.status == 200) { response = _client.Post(“/brussels”, new { monument=response.body.monument }).Send(); // etc }}

> POST /paris> {“name”: “resty galore”}

< 200 OK< {“monument”: “eiffel tower”}

Mission Paris Completed

> POST /brussels> {“monument”: “eiffel tower”}

Oh no!

The Belgium agent was captured and the message is now London!

Oh no!

> POST /brussels> {“monument”: “eiffel tower”}

< 410 Gone somewhere colder

We could send an agent to Brussels to warn Resty Galore…

> POST /brussels> {“monument”: “eiffel tower”}

< 307 Redirect to London, quick!

Keeping agents in each location we need to redirect is expensive.

Travelling for nothing is also expensive.

Or Resty Galore could start her journey with…

Keeping agents in each location we need to redirect is expensive.

Or Resty Galore could start her journey with…

> POST /paris> {“name”: “resty galore”}

< 200 OK< Link: </london>; rel=“next”< {“monument”: “eiffel tower”}

public void travel() { var response = _client .Post(“/paris”, new{name=“Pixie”}) .Send(); if (response.status == 200) { response = _client.Post(response.links.next, new { monument = response.body.monument }).Send(); // etc }}

> POST /london> {“monument”: “eiffel tower”}

< 418 I’m a teapot< < < < <

> POST /london> {“monument”: “eiffel tower”}

< 200 OK< Link: </copenhagen>; rel=“next”< {“food”: “Chicken Tikka Massala”}

Mission London Completed

> POST /copenhagen> {“monument”: “eiffel tower”}

Oh no!

The Danish wants more security and require both the food and the

monument!

Oh no!

> POST /copenhagen> {“monument”: “eiffel tower”}

< 400 Bad request dudette

Forms

> GET /copenhagen< 200 OK< {“form”: {< “monument”: null,< “food”: null< }}

> POST /copenhagen> {“monument”: “eiffel tower”,> “food”: “Chicken Tikka Massala”}< 200 OK< Link: </malmo>; rel=“next”< {“author”: “hans christian andersen”}

Mission Copenhagen Completed

> GET /malmo< 200 OK< {“form”: {< “author”: null< }}

Oh no!

The agent in Malmo is a Mole! They have to be decommissioned!

Oh no!

> GET /malmo< 200 OK< {“form”: {< “author”: null< }}

> POST /malmo> {“author”: “hans christian andersen”}< 200 OK< {“secret”: “not yet…”}

Forms with control data

> GET /malmo< 200 OK< {“form”: {< “method”: “DELETE”< “href”: “/malmo/mole”< }}

> DELETE /malmo/mole> 200 OK< {“secret”: “ReST is amazing.”}

Mission AccomplishedWell done agent Resty Galore!

Resty Galore can take a holiday

We lowered coupling by…

• Respecting the Uniform Interface (status codes, verbs…)

• Introducing Links to navigate• Introducing forms to know what to send• Introducing control data in forms to enable a

change in workflow with no change in the client code.

• OpenRasta - http://openrasta.org• OpenWrap – http://openwrap.org

• Web linking - http://tools.ietf.org/html/rfc5988