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

Transcript

23 slides
  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

More Decks by Bastian Krol

Other Decks in Programming