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

Integrating Node.js

Integrating Node.js

Presentation given at Drupalcamp Austin 2013.

De84f4eabaad2f5c00a7d95c7e4034bf?s=128

Ryan Oles

June 22, 2013
Tweet

Transcript

  1. HELLO. t h e o l e s c h

    o o l . c o m d . o / u s e r / 1 1 4 0 5 8 t w i t t e r . c o m / r h o _ g i t h u b . c o m / r h 0
  2. NODE.JS Server side javascript Single threaded event loop Code must

    be non blocking Socket.io allows for “real time” client server communication.
  3. THATS GREAT, BUT... DRUPAL?

  4. None
  5. I THOUGHT WE WERE INTEGRATING?

  6. D.O/PROJECT/NODE.JS WRITTEN BY JUSTIN RANDELL beejeebus

  7. “IT HANDLES THE PLUMBING.”

  8. AUTHENTICATION

  9. 1. Normal Drupal page load. (with auth token)

  10. 1. Normal Drupal page load. (with auth token) 2. Socket.io

    asks for a connection using the auth token.
  11. 1. Normal Drupal page load. (with auth token) 2. Socket.io

    asks for a connection using the auth token. 3. Node.js sends the auth token to drupal.
  12. 1. Normal Drupal page load. (with auth token) 2. Socket.io

    asks for a connection using the auth token. 3. Node.js sends the auth token to drupal. 4. Drupal sends node a list of channels (and some other information) for that user.
  13. 1. Normal Drupal page load. (with auth token) 2. Socket.io

    asks for a connection using the auth token. 3. Node.js sends the auth token to drupal. 4. Drupal sends node a list of channels for that user. 5. Node.js notifies the client that auth was successful.
  14. None
  15. SUBSEQUENT PAGE LOADS.

  16. MESSAGES ARE THE NAME OF THE GAME.

  17. NODEJS_NOTIFY

  18. SEND A MESSAGE TO ALL USERS. $ s u b

    j e c t = " T o a l l u s e r s : " ; $ b o d y = " H e l l o W o r l d ! " ; n o d e j s _ b r o a d c a s t _ m e s s a g e ( $ s u b j e c t , $ b o d y ) ;
  19. A CLOSER LOOK. n o d e j s .

    m o d u l e f u n c t i o n n o d e j s _ b r o a d c a s t _ m e s s a g e ( $ s u b j e c t , $ b o d y ) { $ m e s s a g e = ( o b j e c t ) a r r a y ( ' b r o a d c a s t ' = > T R U E , ' d a t a ' = > ( o b j e c t ) a r r a y ( ' s u b j e c t ' = > $ s u b j e c t , ' b o d y ' = > $ b o d y , ) , ' c h a n n e l ' = > ' n o d e j s _ n o t i f y ' , ) ; n o d e j s _ e n q u e u e _ m e s s a g e ( $ m e s s a g e ) ; }
  20. MESSAGES ARE SENT ACROSS CHANNELS.

  21. D.O/PROJECT/MESSAGEJS

  22. h o o k _ n o d e j

    s _ u s e r _ c h a n n e l s ( ) m e s s a g e j s . m o d u l e f u n c t i o n m e s s a g e j s _ n o d e j s _ u s e r _ c h a n n e l s ( $ a u t h _ u s e r ) { $ c h a n n e l s = a r r a y ( ) ; i f ( u s e r _ a c c e s s ( ' r e c e i v e m e s s a g e j s n o t i f i c a t i o n s ' , $ a u t h _ u s e r ) ) { $ c h a n n e l s [ ] = ' m e s s a g e j s _ g e n e r a l ' ; } r e t u r n $ c h a n n e l s ; }
  23. SEND A MESSAGE TO CHANNEL SUBSCRIBERS. m e s s

    a g e j s . m o d u l e f u n c t i o n m e s s a g e j s _ s e n d _ m e s s a g e ( $ b o d y , $ s u b j e c t = ' ' ) { $ n o t i f i c a t i o n = n e w s t d C l a s s ( ) ; $ n o t i f i c a t i o n - > c h a n n e l = ' m e s s a g e j s _ g e n e r a l ' ; $ n o t i f i c a t i o n - > d a t a [ ' s u b j e c t ' ] = $ s u b j e c t ; $ n o t i f i c a t i o n - > d a t a [ ' b o d y ' ] = $ b o d y ; $ n o t i f i c a t i o n - > c a l l b a c k = ' n o d e j s N o t i f y ' ; n o d e j s _ e n q u e u e _ m e s s a g e ( $ n o t i f i c a t i o n ) ; }
  24. BUT I WANT TO HANDLE MESSAGES MYSELF!

  25. h t t p : / / g i t

    h u b . c o m / r h 0 / s w a p i t _ d e m o
  26. h o o k _ n o d e j

    s _ h a n d l e r s _ i n f o ( ) s w a p i t _ d e m o . m o d u l e f u n c t i o n s w a p i t _ d e m o _ n o d e j s _ h a n d l e r s _ i n f o ( ) { r e t u r n a r r a y ( d r u p a l _ g e t _ p a t h ( ' m o d u l e ' , ' s w a p i t _ d e m o ' ) . ' / s w a p i t _ d e m o . c l i e n t . j s ' , ) ; }
  27. BUILD AND SEND THE MESSAGE OBJECT. s w a p

    i t _ d e m o . m o d u l e $ m e s s a g e = n e w s t d C l a s s ( ) ; $ m e s s a g e - > c h a n n e l = ' s w a p i t _ d e m o ' ; $ m e s s a g e - > d a t a [ ' b o d y ' ] = $ u s e r _ m s g ; $ m e s s a g e - > c a l l b a c k = ' s w a p I t ' ; n o d e j s _ s e n d _ m e s s a g e ( $ m e s s a g e ) ;
  28. CLIENT SIDE CALLBACK GETS THE MESSAGE s w a p

    i t _ d e m o . c l i e n t . j s D r u p a l . N o d e j s . c a l l b a c k s . s w a p I t = { / / g r a b t h e m e s s a g e a n d i n j e c t i n t o t h e D O M c a l l b a c k : f u n c t i o n ( m e s s a g e ) { i f ( m e s s a g e . c h a n n e l = = ' s w a p i t _ d e m o ' ) { $ ( ' f o r m # n o d e j s - s e l e c t o r ' ) . h t m l ( m e s s a g e . d a t a . b o d y ) ; } } } ;
  29. h t t p : / / d e m

    o . t h e o l e s c h o o l . c o m / s w a p
  30. SO WHERE DO WE STAND? The nodejs module establishes a

    handy node authentication on Drupal rendered pages. “It handles the Plumbing.” Pushes messages to clients via socket.io. Define custom channels to target message delivery using h o o k _ n o d e j s _ u s e r _ c h a n n e l s ( ) . We can customize client side message handling using h o o k _ n o d e j s _ h a n d l e r s _ i n f o ( ) and writing some client side JS.
  31. I WANT TO HAVE MY DRUPAL AND NODE IT TOO!

  32. SERVER EXTENSIONS THEY LET YOU GET YOUR NODE ON! n

    o d e j s / n o d e j s . s e r v e r . e x t e n s i o n . j s . e x a m p l e
  33. THE CONFIG OBJECT IS HERE TO HELP. c o n

    f i g . p u b l i s h M e s s a g e T o C l i e n t ( ) ; c o n f i g . p u b l i s h M e s s a g e T o C h a n n e l ( ) ; c o n f i g . s e n d M e s s a g e T o B a c k e n d ( ) ; e x p o r t s . s e t u p = f u n c t i o n ( c o n f i g ) { . . . }
  34. CALLBACKS p r o c e s s . o

    n c l i e n t - c o n n e c t i o n c l i e n t - a u t h e n t i c a t e d c l i e n t - m e s s a g e c l i e n t - d i s c o n n e c t
  35. A CLIENT HAS CONNECTED, DO SOMETHING! n o d e

    j s / n o d e j s . s e r v e r . e x t e n s i o n . j s . e x a m p l e p r o c e s s . o n ( ' c l i e n t - c o n n e c t i o n ' , f u n c t i o n ( s e s s i o n I d ) { c o n s o l e . l o g ( ' . . . g o t c o n n e c t i o n e v e n t f o r s e s s i o n ' + s e s s i o n I d ) ; c o n f i g . p u b l i s h M e s s a g e T o C l i e n t ( s e s s i o n I d , { d a t a : { s u b j e c t : ' E x a m p l e e x t e n s i o n ' , b o d y : ' H e l l o , y o u j u s t c o n n e c t e d . ' } } ) ; } )
  36. IS THERE ANYBODY OUT THERE?

  37. TALK BACK THROUGH SOCKET.IO D r u p a l

    . N o d e j s . s o c k e t . e m i t ( )
  38. DECIDE WHAT TO SAY. THEN SAY IT n o d

    e _ t o _ d r u p a l . c l i e n t . j s v a r m e s s a g e = { t y p e : ' n o d e T o D r u p a l ' , m e s s a g e B o d y : ' H e l l o f r o m t h e c l i e n t s i d e ! ' } ; $ ( " # n o d e - t o - d r u p a l - f o r m " ) . s u b m i t ( f u n c t i o n ( ) { D r u p a l . N o d e j s . s o c k e t . e m i t ( ' m e s s a g e ' , m e s s a g e ) ; r e t u r n f a l s e ; } ) ;
  39. WE'VE GOT A CALLBACK FOR THAT! AND CAN EVEN RESPOND

    n o d e _ t o _ d r u p a l . s e r v e r . e x t e n s i o n . j s e x p o r t s . s e t u p = f u n c t i o n ( c o n f i g ) { p r o c e s s . o n ( ' c l i e n t - m e s s a g e ' , f u n c t i o n ( s e s s i o n I d , m e s s a g e ) { c o n s o l e . l o g ( ' G o t a m e s s a g e f r o m t h e c l i e n t . T a k e a l o o k : ' ) ; c o n s o l e . l o g ( m e s s a g e ) ; / / D o s o m e s t u f f . . . c o n f i g . p u b l i s h M e s s a g e T o C l i e n t ( s e s s i o n I d , { d a t a : { s u b j e c t : ' S u c c e s s ' , b o d y : " H u z z a h ! " } } ) ; } } ;
  40. ARE YOU THERE DRUPAL? IT'S ME NODE.JS.

  41. h t t p : / / g i t

    h u b . c o m / r h 0 / n o d e _ t o _ d r u p a l
  42. DRUPAL NEEDS TO KNOW WHAT TO EXPECT.

  43. h o o k _ n o d e j

    s _ m e s s a g e _ c a l l b a c k ( ) WHICH DEFINES A HANDLER n o d e _ t o _ d r u p a l . m o d u l e f u n c t i o n n o d e _ t o _ d r u p a l _ n o d e j s _ m e s s a g e _ c a l l b a c k ( $ t y p e ) { s w i t c h ( $ t y p e ) { c a s e ' n o d e T o D r u p a l ' : r e t u r n a r r a y ( ' n o d e _ t o _ d r u p a l _ h a n d l e r ' ) ; } r e t u r n f a l s e ; } f u n c t i o n n o d e _ t o _ d r u p a l _ h a n d l e r ( $ m e s s a g e , & $ r e s p o n c e ) { $ m e s s a g e _ b o d y = $ m e s s a g e [ ' m e s s a g e B o d y ' ] ; w a t c h d o g ( ' n o d e _ t o _ d r u p a l ' , $ m e s s a g e _ b o d y , a r r a y ( ) , W A T C H D O G _ I N F O ) ; $ r e s p o n c e = ' M e s s a g e l o g g e d t o W a t c h d o g ! ' ; }
  44. YEP, IT'S A CALLBACK. c o n f i g

    . s e n d M e s s a g e T o B a c k e n d ( )
  45. SPECIFY THE MESSAGE TYPE SEND THE MESSAGE TO DRUPAL. m

    e s s a g e . m e s s a g e T y p e = ' n o d e T o D r u p a l ' ; c o n f i g . s e n d M e s s a g e T o B a c k e n d ( m e s s a g e , f u n c t i o n ( e r r o r , r e s p o n c e , b o d y ) { i f ( e r r o r ) { c o n s o l e . l o g ( ' E r r o r s e n d i n g m e s s a g e t o b a c k e n d . ' , e r r o r ) ; r e t u r n ; } c o n s o l e . l o g ( ' R e s p o n s e f r o m d r u p a l : ' , b o d y ) ; } ) ;
  46. SO WHAT DOES THIS MEAN? Server extensions allow us to

    augment the default node server. There are several useful callbacks at our disposal. The config object is your friend The client can talk to the node server using D r u p a l . N o d e J S . s o c k e t . e m i t ( ) The Node server can talk to Drupal using c o n f i g . s e n d M e s s a g e T o B a c k e n d with a message targeted to a custom drupal handler.
  47. None
  48. h t t p s : / / g i

    t h u b . c o m / r h 0 / d c h e s s
  49. CONTENT TOKEN CHANNELS

  50. SETUP CHANNEL IN DRUPAL n o d e j s

    _ s e n d _ c o n t e n t _ c h a n n e l _ t o k e n ( ' d c h e s s _ g a m e _ ' . $ n o d e - > n i d ) ;
  51. TOKEN CHANNEL MESSAGE FROM DRUPAL. n o d e j

    s _ s e n d _ c o n t e n t _ c h a n n e l _ m e s s a g e ( $ m e s s a g e ) ;
  52. TOKEN CHANNEL MESSAGE FROM NODE d c h e s

    s . s e r v e r . j s f u n c t i o n s e n d M e s s a g e T o T o k e n C h a n n e l ( m e s s a g e , c o n f i g ) { i f ( ! m e s s a g e . h a s O w n P r o p e r t y ( ' c h a n n e l ' ) ) { c o n s o l e . l o g ( ' . . . i n v a l i d m e s s a g e o b j e c t w a s p r o v i d e d . ' ) ; r e t u r n ; } i f ( ! c o n f i g . t o k e n C h a n n e l s . h a s O w n P r o p e r t y ( m e s s a g e . c h a n n e l ) ) { c o n s o l e . l o g ( ' . . . c h a n n e l " ' + m e s s a g e . c h a n n e l + ' " d o e s n \ ' t e x i s t . ' ) ; r e t u r n ; } f o r ( v a r s o c k e t I d i n c o n f i g . t o k e n C h a n n e l s [ m e s s a g e . c h a n n e l ] . s o c k e t s ) { c o n f i g . p u b l i s h M e s s a g e T o C l i e n t ( s o c k e t I d , m e s s a g e ) ; } }
  53. h t t p : / / c h e

    s s . t h e o l e s c h o o l . c o m
  54. A FEW THINGS TO NOTE h t t p s

    : / / g i t h u b . c o m / j h l y w a / c h e s s . j s h t t p : / / a n g u l a r j s . o r g /
  55. SOME LAST THOUGHTS Works great with pushing messagesto the client.

    You can build more complex node applicaitons with this... but should you?
  56. THANKS t h e o l e s c h

    o o l . c o m d . o / u s e r / 1 1 4 0 5 8 t w i t t e r . c o m / r h o _ g i t h u b . c o m / r h 0