Upload
3scale
View
911
Download
2
Embed Size (px)
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.
Citation preview
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