43
Building Hypermedia APIs in Javascript from homemade solution to using Fortune.js

Building Hypermedia APIs in JavaScript

  • 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

Page 1: Building Hypermedia APIs in JavaScript

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

Page 2: Building Hypermedia APIs in JavaScript

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

You?

Page 3: Building Hypermedia APIs in JavaScript

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

You?

• Who uses APIs?

Page 4: Building Hypermedia APIs in JavaScript

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

You?

• Who uses APIs?

• Who knows what Hypermedia APIs are?

Page 5: Building Hypermedia APIs in JavaScript

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

You?

• Who uses APIs?

• Who knows what Hypermedia APIs are?

• Who had ever build one?

Page 6: Building Hypermedia APIs in JavaScript

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

Me

Page 7: Building Hypermedia APIs in JavaScript

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

Me

• 3scale evangelist

Page 8: Building Hypermedia APIs in JavaScript

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

Me

• 3scale evangelist

• API freak

Page 9: Building Hypermedia APIs in JavaScript

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

Me

• 3scale evangelist

• API freak

• Hacker in Residence

Page 10: Building Hypermedia APIs in JavaScript

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

Me

• 3scale evangelist

• API freak

• Hacker in Residence

• Node.js, Meteor

Page 11: Building Hypermedia APIs in JavaScript

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

Hypermedia 101

Page 12: Building Hypermedia APIs in JavaScript

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

you are already using Hypermedia APIs

Page 13: Building Hypermedia APIs in JavaScript

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

Core values

Page 14: Building Hypermedia APIs in JavaScript

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

Core values

• Discoverable API

Page 15: Building Hypermedia APIs in JavaScript

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

Core values

• Discoverable API

• Machine readable API

Page 16: Building Hypermedia APIs in JavaScript

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

Core values

• Discoverable API

• Machine readable API

• Link-based

Page 17: Building Hypermedia APIs in JavaScript

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}" }

Page 18: Building Hypermedia APIs in JavaScript

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

Example: building

REST approach

/rooms/r123

/doors/d123

Page 19: Building Hypermedia APIs in JavaScript

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

Example: buildingAdding relations

/rooms/r123

• /rooms/r123/doors/d123

/doors/d123

• /doors/d123/rooms/r123

Page 20: Building Hypermedia APIs in JavaScript

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

Page 21: Building Hypermedia APIs in JavaScript

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

Me…

Page 22: Building Hypermedia APIs in JavaScript

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

Me…

Page 23: Building Hypermedia APIs in JavaScript

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

Page 24: Building Hypermedia APIs in JavaScript

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

Page 25: Building Hypermedia APIs in JavaScript

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" } ] } }

Page 26: Building Hypermedia APIs in JavaScript

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

There is a framework for that

Page 27: Building Hypermedia APIs in JavaScript

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

Fortune.js

Page 28: Building Hypermedia APIs in JavaScript

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);

Page 29: Building Hypermedia APIs in JavaScript

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)

Page 30: Building Hypermedia APIs in JavaScript

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" } } }

Page 31: Building Hypermedia APIs in JavaScript

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" } } }

Page 32: Building Hypermedia APIs in JavaScript

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" } } }

Page 33: Building Hypermedia APIs in JavaScript

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)

Page 34: Building Hypermedia APIs in JavaScript

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

API-based game: APIbunny

Page 35: Building Hypermedia APIs in JavaScript

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' } }

Page 36: Building Hypermedia APIs in JavaScript

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' } }

Page 37: Building Hypermedia APIs in JavaScript

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

Page 38: Building Hypermedia APIs in JavaScript

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

Page 39: Building Hypermedia APIs in JavaScript

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

Page 40: Building Hypermedia APIs in JavaScript

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

APIbunny• POST requests format is not usual

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

Page 41: Building Hypermedia APIs in JavaScript

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 ;)

Page 42: Building Hypermedia APIs in JavaScript

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

Page 43: Building Hypermedia APIs in JavaScript

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

Questions?

!picsoung" picsoung