Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Consuming Hypermedia APIs with Traverson

Bastian Krol
December 18, 2013

Consuming Hypermedia APIs with Traverson

Introducing Traverson a JavaScript Hypermedia API Client for Node.js and the browser

Bastian Krol

December 18, 2013
Tweet

More Decks by Bastian Krol

Other Decks in Programming

Transcript

  1. YOUR NEXT DOOR NEIGHBOUR REST API Method/URI Typical Response GET

    /users 2 0 0 { " u s e r _ i d s " : [ " 1 3 " , " 4 2 " ] } POST /users 2 0 1 { " i d " : " 1 3 " } GET /users/:id 2 0 0 { " i d " : " 1 3 " , " n a m e " : " b a s t i a n PUT /users/:id 2 0 0 { " i d " : " 1 3 " , " n a m e " : " f r e d " } GET /users/:id/posts 2 0 0 { " p o s t s " : [ . . . ] } POST /users/:id/posts 2 0 1 { " t i t l e " : " T e s t " , " c o n t e n t " :
  2. THIS IS NOT A REST API It's not doing HATEOAS

    Clients need out-of-band information: Needs to know each URI Needs to know (in advance) which method works on which resource Tight coupling between client and server
  3. RANTS FROM DOC FIELDING [...] if the engine of application

    state (and hence the API) is not being driven by hypertext, then it cannot be RESTful and cannot be a REST API. Period.
  4. RANTS FROM DOC FIELDING A REST API must not define

    fixed resource names or hierarchies (an obvious coupling of client and server). [...] Instead, allow servers to instruct clients on how to construct appropriate URIs, [...] by defining those instructions within media types and link relations.
  5. REST IS DEAD - LONG LIVE HYPERMEDIA APIS Hypermedia APIs

    ~ "proper" REST APIs Hypermedia constraint (HATEOAS) API: Links between resources Client: Drive application state by following links
  6. HYPERMEDIA APIS IN THE WILD GitHub (JSON + Links) Twitter

    (JSON + Links) Netflix (XML + Links) Amazon AppStream (application/hal+json) ...
  7. EXAMPLE Task: Find the latest gist of user basti1302: -

    > u s e r _ u r l - > - > g i s t s _ u r l - > - > $ [ 0 ] . u r l - > https://api.github.com/ https://api.github.com/users/basti1302 https://api.github.com/users/basti1302/gists https://api.github.com/gists/7166618
  8. We would like to have some tooling to follow links

    automatically... HOW TO CONSUME A HYPERMEDIA API?
  9. WITHOUT TRAVERSON v a r r e q u e

    s t = r e q u i r e ( ' r e q u e s t ' ) r e q u e s t . g e t ( ' h t t p s : / / a p i . g i t h u b . c o m / ' , f u n c t i o n ( e r r , r e s p o n s e ) { i f ( e r r ) { r e t u r n c o n s o l e . l o g ( e r r ) } v a r u r i = g e t U r i ( r e s p o n s e , ' u s e r _ u r l ' , { u s e r : ' b a s t i 1 3 0 2 ' } ) r e q u e s t . g e t ( u r i , f u n c t i o n ( e r r , r e s p o n s e ) { i f ( e r r ) { r e t u r n c o n s o l e . l o g ( e r r ) } u r i = g e t U r i ( r e s p o n s e , ' g i s t s _ u r l ' ) r e q u e s t . g e t ( u r i , f u n c t i o n ( e r r , r e s p o n s e ) { i f ( e r r ) { r e t u r n c o n s o l e . l o g ( e r r ) } u r i = n e x t U r i ( r e s p o n s e , ' $ [ 0 ] . u r l ' ) r e q u e s t . g e t ( u r i , f u n c t i o n ( e r r , r e s p o n s e ) { i f ( e r r ) { r e t u r n c o n s o l e . l o g ( e r r ) } v a r r e s o u r c e = J S O N . p a r s e ( r e s p o n s e . b o d y ) c o n s o l e . l o g ( r e s o u r c e ) } ) } ) } ) } )
  10. WITH TRAVERSON v a r a p i = r

    e q u i r e ( ' t r a v e r s o n ' ) . j s o n . f r o m ( ' h t t p s : / / a p i . g i t h u b . c o m / ' ) a p i . n e w R e q u e s t ( ) . w i t h T e m p l a t e P a r a m e t e r s ( { u s e r : ' b a s t i 1 3 0 2 ' } ) . f o l l o w ( ' u s e r _ u r l ' , ' g i s t s _ u r l ' , ' $ [ 0 ] . u r l ' ) . g e t R e s o u r c e ( f u n c t i o n ( e r r , r e s o u r c e ) { c o n s o l e . l o g ( r e s o u r c e ) } )
  11. CORE FEATURES Follow a sequence of links You: Throw in

    the link relations Traverson: Return the target resource
  12. URI TEMPLATES / / h t t p : /

    / a p i . e x a m p l e . c o m { " u s e r _ l o o k u p " : " h t t p : / / a p i . e x a m p l e . c o m / u s e r s / { u s e r _ n a m e } " } / / h t t p : / / a p i . e x a m p l e . c o m / u s e r s / b a s t i a n { " p o s t _ l o o k u p " : " h t t p : / / a p i . e x a m p l e . c o m / u s e r s / b a s t i a n / p o s t s / { p o s t _ i d } " } / / h t t p : / / a p i . e x a m p l e . c o m / u s e r s / b a s t i a n / p o s t s / 1 3 0 2 { " c o n t e n t " : " L o r e m i p s u m d o l o r s i t a m e t " } a p i . f o l l o w ( ' u s e r _ l o o k u p ' , ' p o s t _ l o o k u p ' ) . w i t h T e m p l a t e P a r a m e t e r s ( { u s e r _ n a m e : ' b a s t i a n ' , p o s t _ i d : 1 3 0 2 } ) . g e t R e s o u r c e ( f u n c t i o n ( e r r o r , d o c u m e n t ) { / / . . . } )
  13. JSONPATH { " d e e p l y "

    : { " n e s t e d " : { " l i n k " : " h t t p : / / a p i . e x a m p l e . c o m / c o n g r a t s / y o u / h a v e / f o u n d / m e " } } } a p i . n e w R e q u e s t ( ) . f o l l o w ( ' $ . d e e p l y . n e s t e d . l i n k ' ) . g e t R e s o u r c e ( f u n c t i o n ( e r r o r , d o c u m e n t ) { . . . } )
  14. HAL Hypertext Application Language Standardized properties for links and embedded

    resources Recently adopted by Amazon (AppStream API)
  15. HAL { " _ l i n k s "

    : { " s e l f " : { " h r e f " : " / o r d e r s " } , " n e x t " : { " h r e f " : " / o r d e r s ? p a g e = 2 " } , " f i n d " : { " h r e f " : " / o r d e r s { ? i d } " , " t e m p l a t e d " : t r u e } } , " _ e m b e d d e d " : { " o r d e r s " : [ { " _ l i n k s " : { " s e l f " : { " h r e f " : " / o r d e r s / 1 2 3 " } } , " t o t a l " : 3 0 . 0 0 , " s t a t u s " : " s h i p p e d " } ] } , " s h i p p e d T o d a y " : 2 0 }
  16. HAL / / h t t p : / /

    h a l . e x a m p l e . c o m / : { " _ l i n k s " : { " f i n d " : { " h r e f " : " / o r d e r s { ? i d } " , " t e m p l a t e d " : t r u e } } } / / h t t p : / / h a l . e x a m p l e . c o m / o r d e r s ? 4 2 : { " _ l i n k s " : { " i t e m s " : { " h r e f " : " / o r d e r s / 4 2 / i t e m s " } } } / / h t t p : / / h a l . e x a m p l e . c o m / o r d e r s / 4 2 / i t e m s : { . . . } } v a r a p i = r e q u i r e ( ' t r a v e r s o n ' ) . j s o n H a l . f r o m ( ' h t t p : / / a p i . e x a m p l e . c o m / ' ) a p i . n e w R e q u e s t ( ) . f o l l o w ( ' f i n d ' , ' i t e m s ' ) . w i t h T e m p l a t e P a r a m e t e r s ( { i d : ' 4 7 1 1 ' } ) . g e t R e s o u r c e ( f u n c t i o n ( e r r o r , d o c u m e n t ) { / / . . . } )
  17. CROSS PLATFORM - NODE.JS & BROWSER Regular Node.js module (in

    npm) Grunt Build Run Mocha Tests in Node.js Browserify Everything -> Single File With UMD Shim some modules (reduces file size) Uglify it Start Test Server Run Mocha Tests in Browser (PhantomJS) ci.testling for cross-browser compatibility