building hypermedia apis in javascript

Post on 02-Jul-2015

904 Views

Category:

Technology

2 Downloads

Preview:

Click to see full reader

DESCRIPTION

Nicolas Grenie's presentation from HTML5 Dev Conf. 2014: There is currently a major shift sweeping over the software industry. With each passing day the world is becoming more and more API-driven. When building an API there are many design options and Hypermedia is the new emerging way of designing APIs. Hypermedia APIs are widely used by companies such as Paypal and Amazon. In this session I will discuss the principles of Hypermedia APIs and the different ways to implement one in Node.js. I will first introduce you to a basic implementation using Express and then move on to a more advanced solution using a dedicated framework: Fortune.js. I will also share my experience of building APIbunny (http://apibunny.com), an API-driven easter game.

TRANSCRIPT

Building Hypermedia APIs in Javascriptfrom homemade solution to using Fortune.js

HTML5 Conference SF Oct. 2014 Nicolas Grenié - !picsoung

You?

HTML5 Conference SF Oct. 2014 Nicolas Grenié - !picsoung

You?

• Who uses APIs?

HTML5 Conference SF Oct. 2014 Nicolas Grenié - !picsoung

You?

• Who uses APIs?

• Who knows what Hypermedia APIs are?

HTML5 Conference SF Oct. 2014 Nicolas Grenié - !picsoung

You?

• Who uses APIs?

• Who knows what Hypermedia APIs are?

• Who had ever build one?

HTML5 Conference SF Oct. 2014 Nicolas Grenié - !picsoung

Me

HTML5 Conference SF Oct. 2014 Nicolas Grenié - !picsoung

Me

• 3scale evangelist

HTML5 Conference SF Oct. 2014 Nicolas Grenié - !picsoung

Me

• 3scale evangelist

• API freak

HTML5 Conference SF Oct. 2014 Nicolas Grenié - !picsoung

Me

• 3scale evangelist

• API freak

• Hacker in Residence

HTML5 Conference SF Oct. 2014 Nicolas Grenié - !picsoung

Me

• 3scale evangelist

• API freak

• Hacker in Residence

• Node.js, Meteor

HTML5 Conference SF Oct. 2014 Nicolas Grenié - !picsoung

Hypermedia 101

HTML5 Conference SF Oct. 2014 Nicolas Grenié - !picsoung

you are already using Hypermedia APIs

HTML5 Conference SF Oct. 2014 Nicolas Grenié - !picsoung

Core values

HTML5 Conference SF Oct. 2014 Nicolas Grenié - !picsoung

Core values

• Discoverable API

HTML5 Conference SF Oct. 2014 Nicolas Grenié - !picsoung

Core values

• Discoverable API

• Machine readable API

HTML5 Conference SF Oct. 2014 Nicolas Grenié - !picsoung

Core values

• Discoverable API

• Machine readable API

• Link-based

HTML5 Conference SF Oct. 2014 Nicolas Grenié - !picsoung

Example: GithubGET api.github.com { current_user_url: "https://api.github.com/user", authorizations_url: "https://api.github.com/authorizations", code_search_url: "https://api.github.com/search/code?q={query}{&page,per_page,sort,order}", emails_url: "https://api.github.com/user/emails", emojis_url: "https://api.github.com/emojis", events_url: "https://api.github.com/events", feeds_url: “https://api.github.com/feeds",ed{/owner}{/repo}", … team_url: "https://api.github.com/teams", user_url: "https://api.github.com/users/{user}", user_organizations_url: "https://api.github.com/user/orgs", user_repositories_url: "https://api.github.com/users/{user}/repos{?type,page,per_page,sort}", user_search_url: "https://api.github.com/search/users?q={query}{&page,per_page,sort,order}" }

HTML5 Conference SF Oct. 2014 Nicolas Grenié - !picsoung

Example: building

REST approach

/rooms/r123

/doors/d123

HTML5 Conference SF Oct. 2014 Nicolas Grenié - !picsoung

Example: buildingAdding relations

/rooms/r123

• /rooms/r123/doors/d123

/doors/d123

• /doors/d123/rooms/r123

HTML5 Conference SF Oct. 2014 Nicolas Grenié - !picsoung

Example: buildingBuildings have hallways

/doors/1/rooms/1

/doors/1/hallways/1

/rooms/1/doors/1

/rooms/1/hallways/1

/hallways/1/doors/1

/hallways/1/rooms/1

HTML5 Conference SF Oct. 2014 Nicolas Grenié - !picsoung

Me…

HTML5 Conference SF Oct. 2014 Nicolas Grenié - !picsoung

Me…

HTML5 Conference SF Oct. 2014 Nicolas Grenié - !picsoung

Let’s put Hypermedia in itLinking ressources

• /rooms/1

- rel: door, href: /what/ever/door

- rel: door, href: /another/door

• /door

- rel: entry-to, href: /rooms/1

- rel: entry-to, href: /hallways/1

• /hallways/1

- rel: floor, href: /floors/1

HTML5 Conference SF Oct. 2014 Nicolas Grenié - !picsoung

HATEOAS

• Basic implementation with Express

• add “link” properties to the JSON response

Hypermedia as the Engine of Application State

HTML5 Conference SF Oct. 2014 Nicolas Grenié - !picsoung

HATEOASGET mybuilding.com/rooms/1 { "data": { "name": "Kitchen", "id": "1", "links" : [ { "rel": "door", "href": "https://mybuilding.com/rooms/12345678" }, { "rel": "door", "href": "https://theirbuilding.com/rooms/12345678" } ] } }

HTML5 Conference SF Oct. 2014 Nicolas Grenié - !picsoung

There is a framework for that

HTML5 Conference SF Oct. 2014 Nicolas Grenié - !picsoung

Fortune.js

HTML5 Conference SF Oct. 2014 Nicolas Grenié - !picsoung

Fortune.js• simple to setup

var fortune = require('fortune') , app = fortune({ db: 'petstore' }) .resource('person', { name: String, age: Number, pets: ['pet'] // "has many" relationship to pets }) .resource('pet', { name: String, age: Number, owner: 'person' // "belongs to" relationship to a person }) .listen(1337);

HTML5 Conference SF Oct. 2014 Nicolas Grenié - !picsoung

Fortune.jsHTTP Person Pet Notes

GET /people /pets Get a collection of resources, accepts query ?

POST /people /pets Create a resource

GET /people/:id /pets/:id Get a specific resource, or multiple: 1,2,3

PUT /people/:id /pets/:id Create or update a resource

PATCH /people/:id /pets/:id Patch a resource (see RFC 6902)

DELETE /people/:id /pets/:id Delete a resource

GET /people/:id/pets /pets/:id/owner Get a related resource (one level deep)

HTML5 Conference SF Oct. 2014 Nicolas Grenié - !picsoung

Fortune.js• JSON API spec

{ "people": [ { "id": "tO69XnLz7amaYVRq", "name": "Wall-E", "age": 1000, "links": { "pets": [ "dPuXqUJxRIn9cOdH" ] } } ], "links": { "people.pets": { "href": "/pets/{people.pets}", "type": "pets" } } }

HTML5 Conference SF Oct. 2014 Nicolas Grenié - !picsoung

Fortune.js• JSON API spec

/people/tO69XnLz7amaYVRq { "people": [ { "id": "tO69XnLz7amaYVRq", "name": "Wall-E", "age": 1000, "links": { "pets": [ "dPuXqUJxRIn9cOdH" ] } } ], "links": { "people.pets": { "href": "/pets/{people.pets}", "type": "pets" } } }

HTML5 Conference SF Oct. 2014 Nicolas Grenié - !picsoung

Fortune.js• JSON API spec

/people/tO69XnLz7amaYVRq { "people": [ { "id": "tO69XnLz7amaYVRq", "name": "Wall-E", "age": 1000, "links": { "pets": [ "dPuXqUJxRIn9cOdH" ] } } ], "links": { "people.pets": { "href": "/pets/{people.pets}", "type": "pets" } } }

/pets/dPuXqUJxRIn9cOdH { "pets": [ { "id": "dPuXqUJxRIn9cOdH", "name": "Cucaracha", "age": 1000, "links": { "owner": "tO69XnLz7amaYVRq" } } ], "links": { "pets.owner": { "href": "/people/{pets.owner}", "type": "people" } } }

HTML5 Conference SF Oct. 2014 Nicolas Grenié - !picsoung

Fortune.js

adapters for NeDB, MongoDB, MySQL, Postgres, SQLite handles all the routing handles database interactions hooks for specific logic before/after interacting with

resources authentication not implemented (build your own)

HTML5 Conference SF Oct. 2014 Nicolas Grenié - !picsoung

API-based game: APIbunny

HTML5 Conference SF Oct. 2014 Nicolas Grenié - !picsoung

APIbunny{ north: { ref: 'cell', inverse: 'south' }, east: { ref: 'cell', inverse: 'west' }, south: { ref: 'cell', inverse: 'north' }, west: { ref: 'cell', inverse: 'east' } }

HTML5 Conference SF Oct. 2014 Nicolas Grenié - !picsoung

APIbunny• Inverse relation does not work in case of maze{ north: { ref: 'cell', inverse: 'south' }, east: { ref: 'cell', inverse: 'west' }, south: { ref: 'cell', inverse: 'north' }, west: { ref: 'cell', inverse: 'east' } }

HTML5 Conference SF Oct. 2014 Nicolas Grenié - !picsoung

APIbunny• Inverse relation does not work in case of maze{ north: { ref: 'cell', inverse: 'south' }, east: { ref: 'cell', inverse: 'west' }, south: { ref: 'cell', inverse: 'north' }, west: { ref: 'cell', inverse: 'east' } }

1 4 7

2 5 8

3 6 9

HTML5 Conference SF Oct. 2014 Nicolas Grenié - !picsoung

APIbunny• Inverse relation does not work in case of maze{ north: { ref: 'cell', inverse: 'south' }, east: { ref: 'cell', inverse: 'west' }, south: { ref: 'cell', inverse: 'north' }, west: { ref: 'cell', inverse: 'east' } }

1 4 7

2 5 8

3 6 9

{ west:1 east:7 south:5 }

expected on #4

HTML5 Conference SF Oct. 2014 Nicolas Grenié - !picsoung

APIbunny• Inverse relation does not work in case of maze{ north: { ref: 'cell', inverse: 'south' }, east: { ref: 'cell', inverse: 'west' }, south: { ref: 'cell', inverse: 'north' }, west: { ref: 'cell', inverse: 'east' } }

1 4 7

2 5 8

3 6 9

{ west:1 east:7 south:5 }

expected on #4

east of #1 is #4 -> west of #4 is #1

but east of #7 is #4 -> west of #4 is #7

HTML5 Conference SF Oct. 2014 Nicolas Grenié - !picsoung

APIbunny• POST requests format is not usual

{"people":[{"age":1000,"name":"Wall-E"}]}

HTML5 Conference SF Oct. 2014 Nicolas Grenié - !picsoung

APIbunny

• thousands players, 44 winners, ~10 code shared

• Open https://github.com/picsoung/apibunny/

• V2 is coming ;)

HTML5 Conference SF Oct. 2014 Nicolas Grenié - !picsoung

Ressources• http://apicodex.3scale.net/

• http://amundsen.com/hypermedia/

• http://www.designinghypermediaapis.com/

• https://www.youtube.com/watch?v=_UG7u7ARTfM (APIStrat SF)

• APIdays and APIstrat conferences

• API-craft meetup + google group

HTML5 Conference SF Oct. 2014 Nicolas Grenié - !picsoung

Questions?

!picsoung" picsoung

top related