Mettez du temps réel dans votre Drupal avec Node JS

37
Mettez du temps réel dans votre Drupal avec NodeJS

description

 

Transcript of Mettez du temps réel dans votre Drupal avec Node JS

Page 1: Mettez du temps réel dans votre Drupal avec Node JS

Mettez du temps réel dans votre Drupal avec NodeJS

Page 2: Mettez du temps réel dans votre Drupal avec Node JS

Qui sommes nous ?

● Matthieu Guillermin - MultitaskConsultant chez @mguillermin

● Nicolas Chambrier - Nodefag TrollDéveloppeur chez @naholyr

Page 3: Mettez du temps réel dans votre Drupal avec Node JS

● On va de plus en plus vers des architectures

hétérogènes

● Utiliser chaque techno pour ce qu'elle sait

bien faire

● Les besoins de "temps-réels" sont de plus

en plus présents

Pourquoi intégrer Drupal / NodeJS ?

Page 4: Mettez du temps réel dans votre Drupal avec Node JS

Le Cas d'Utilisation

Page 5: Mettez du temps réel dans votre Drupal avec Node JS

Le Cas d'Utilisation

● Notre but était de :○ Utiliser Drupal pour ce qu'il fait de mieux

○ Utiliser NodeJS pour ce qu'il fait de mieux

○ Trouver un cas d'utilisation réellement utile

● En utilisant des fonctionnalités classiques à

la fois pour Drupal et pour NodeJS

Page 6: Mettez du temps réel dans votre Drupal avec Node JS

Le Cas d'Utilisation

● Drupal :○ Gestion de contenu

○ Contribution

○ Workflow

● NodeJS :○ Mise en place d'une API REST

○ Application "temps réel"

Page 7: Mettez du temps réel dans votre Drupal avec Node JS

Le Cas d'Utilisation

● Système de notification○ Messages affichés directement dans le navigateur

○ En réponse à des événements Drupal

○ Envoi en "temps-réel"

● Paramétrable○ Définition de règles d'envoi de messages

○ Définition des destinataires des message

Page 8: Mettez du temps réel dans votre Drupal avec Node JS

Comment le réaliser ?

Page 9: Mettez du temps réel dans votre Drupal avec Node JS

Comment le réaliser ?

● Utilisation de standards Web

● Communication depuis Drupal○ Web Services

○ REST

● Communication depuis le client○ Accès direct au serveur NodeJS

Page 10: Mettez du temps réel dans votre Drupal avec Node JS

Comment le réaliser ?

Serveur NodeJSDrupal

Navigateur client

Navigateur clientNavigateur

client

Action

Appel Web Service

Dispatch & Notification

Page 11: Mettez du temps réel dans votre Drupal avec Node JS

Mise en oeuvre NodeJS

Page 12: Mettez du temps réel dans votre Drupal avec Node JS

Comment on a travaillé

● Pas de super-héros !○ Je n'y connais rien à Drupal○ Il n'y connait pas grand chose à Node

● Il faut:○ Savoir installer et faire tourner le travail de l'autre

■ Drupal: LAMP + dump MySQL■ Node: NodeJS → `node app.js`

○ Définir l'API avant tout■ Sur un coin de table 3 jours avant

○ C'est tout !

Page 13: Mettez du temps réel dans votre Drupal avec Node JS

Un serveur HTTP + WebSocket

● On veut que ce soit simple○ Toute la stack dans une seule application○ Notifier = une requête HTTP simple○ Afficher les notifications = une inclusion de script +

une ligne de config

● On veut que ce soit sécurisé, performant, et scalable○ Oui mais c'est un tout autre sujet ;)

Page 14: Mettez du temps réel dans votre Drupal avec Node JS

One app to rule them all

Notifications

Fichiers statiques WebSockets

var app = http.createServer(handler) function handler (req, res) {

if (req.url === "/" && req.method === "POST") { newNotification(req, res) }

else { serveStatic(req, res); }}

var io = require('socket.io') io.listen(app)

Page 15: Mettez du temps réel dans votre Drupal avec Node JS

Modèle de données

● Identifier les paramètres requis:

○ On veut un message→ "message": String

○ On veut cibler les utilisateurs par rôle→ "roles": [String]

○ On veut éventuellement cibler par utilisateur→ "users": [String]

● JSON: { "roles": ["administrator"], "users": [1], "message": "hello, world" }

Page 16: Mettez du temps réel dans votre Drupal avec Node JS

API REST

● JSON

● Création = POST● Réponse adaptée:

201 - Created400 - Bad Request500 - Server Error

● Broadcast viaWebSocket

function newNotification (req, res) { if (!isJSON(req)) { error400() } var notif = JSON.parse(req.body) validateNotif(notif) notif.id = uuid() broadcastViaWebSocket(notif) respond(res, 201, "application/json", JSON.stringify(notif))}

Page 17: Mettez du temps réel dans votre Drupal avec Node JS

API Client

● Script servi parl'application

● Une seule fonction

● Ajoute seul lesdépendancesJS & CSS

● Enrichit le DOM

● Gère le WebSocket

function display (id, roles) { addJS("socket.io.js") addCSS("notifications.css") addDOMContainer() var socket = io.connect() socket.on('connect', function () { socket.emit('roles', roles) socket.emit('user_id', id) }) socket.on('error', function (e) { notifyError(e) }) socket.on('notif', function (n) { notifyInfo(n) }) }

Page 18: Mettez du temps réel dans votre Drupal avec Node JS

API : Utilisation

Client

Serveur

Simple enough ?

<script src="http://localhost:8080/notifications.js"></script><script>notifications.display(1, ["administrator"])</script>

POST http://localhost:8080Content-Type: application/json {"roles":["administrator"],"message":"Show me your big power"}

Page 19: Mettez du temps réel dans votre Drupal avec Node JS

Socket.IO

● Pourquoi Socket.IO ?○ Puissant, simple, efficace, hyper-compatible.

● Comment distribuer les messages ?○ Filtrer côté client ? Pas efficace○ Côté serveur: comment router les message ?

● Socket.IO à la rescousse: les "rooms":○ Client: socket.join("room")○ Serveur: io.sockets.in("room").emit(data)○ Nos salons: "USER:$id" & "ROLE:$role"

● Problème des notifications en double

Page 20: Mettez du temps réel dans votre Drupal avec Node JS

Socket.IO - implémentation

● Client

● Serveur

● Notification

socket.on('connect', function () { socket.emit('user_id', user_id);});

socket.on('user_id', function (user_id) { socket.join('USER:' + user_id);});

notification.users.forEach(function (id) { io.sockets .in('USER:' + id) .emit('notification', notification);});

Page 21: Mettez du temps réel dans votre Drupal avec Node JS

Résultat [WARNING: PROTOTYPE]

naholyr/node-drupal-notifications

Page 22: Mettez du temps réel dans votre Drupal avec Node JS

Mise en oeuvre Drupal

Page 23: Mettez du temps réel dans votre Drupal avec Node JS

Appel de Web Service

● Utilisation du module wsclient○ Permet de définir des "services"

○ Et sur chaque services, des "opérations"

● Différents types de services : ○ SOAP

○ REST

Page 24: Mettez du temps réel dans votre Drupal avec Node JS

Appel de Web Service

● Les opérations sont définies avec○ une URL

○ une Method HTTP

○ des paramètres

○ un type de retour

● Paramètres○ Type, Required, Multiple, Default value

Page 25: Mettez du temps réel dans votre Drupal avec Node JS

Appel de Web Service

● Paramétrage possible ○ depuis l'interface

○ via l'API

● L'utilisation de l'API offre plus de possibilités

○ Ex : HTTP Method de l'opération

○ Ex : Format à utiliser (Json, Form,...)

Page 26: Mettez du temps réel dans votre Drupal avec Node JS

Appel de Web Service

● Une fois définis, les opérations peuvent être

appelées via l'API

$serviceName = "notification";$operationName = "send_message"; $service = wsclient_service_load($serviceName); $service->invoke($operationName,

array("message" => "Ceci est mon message"));

Page 27: Mettez du temps réel dans votre Drupal avec Node JS

Déclenchement des envois de message

● La solution : ○ Utiliser l'API de wsclient directement en

l'implémentant dans un module

● Problème :○ Tout doit être prévu dans le code (quand envoyer le

message ? à qui ? ...)

Page 28: Mettez du temps réel dans votre Drupal avec Node JS

Déclenchement des envois de message

● Utilisation de Rules○ wsclient expose les opérations sous forme d'actions

Rules

○ Avec possibilité de renseigner les paramètres

● Avantages○ Tout est configurable depuis le backoffice

○ Les valeurs des paramètres peuvent contenir des

tokens

Page 29: Mettez du temps réel dans votre Drupal avec Node JS

Intégration javascript "client"

● Pour communiquer avec NodeJS, il faut

inclure un javascript côté client○ Ce script doit être chargé systématiquement sur

chaque page

● On doit aussi initialiser en js l'Id et les rôles

de l' utilisateur○ Utilisation de drupal_add_js()

Page 30: Mettez du temps réel dans votre Drupal avec Node JS

Intégration javascript "client"function node_demo_init() { drupal_add_js('http://localhost:8080/notifications.js', 'file'); global $user; drupal_add_js(array( 'node_demo' => array( 'uid' => $user->uid, 'roles' => array_values($user->roles), ) ), 'setting');}

Page 31: Mettez du temps réel dans votre Drupal avec Node JS

Résultat [WARNING: PROTOTYPE]

mguillermin/node-drupal-notifications-demo

Page 32: Mettez du temps réel dans votre Drupal avec Node JS

Démonstration

Page 33: Mettez du temps réel dans votre Drupal avec Node JS

Pistes d'amélioration

● Ajout de nouveaux attributs aux messages○ Type

○ Priorité / "Sticky"

○ Emetteur

○ ...

● A ajouter à l'API REST, dans la définition de

service wsclient et à gérer dans le javascript

client

Page 34: Mettez du temps réel dans votre Drupal avec Node JS

Pistes d'amélioration

● Gérer l'authentification utilisateur côté

NodeJS○ Pour s'assurer que l'ID utilisateur envoyé est bien

celui de l'utilisateur courant

● Mécanisme de jeton envoyé par le client et

vérifié par NodeJS auprès de Drupal (SSO)○ Cette vérification renverrait l'ID et les rôles

utilisateurs

Page 35: Mettez du temps réel dans votre Drupal avec Node JS

Pistes d'amélioration

● Sécuriser l'API REST○ Eviter qu'un tiers n'utilise l'API REST pour envoyer

des messages en n'autorisant les envois de

message que depuis Drupal

● Utilisation d'une clé d'API○ la clé serait validée à chaque appel d'API

Page 36: Mettez du temps réel dans votre Drupal avec Node JS

● Améliorer l'UI des notifications○ Afficher/cacher

○ Persister les notifications entre les pages (statut

lu/non lu)

● Utiliser un vrai pub/sub pour la transmission○ Redis, RabbitMQ, ØMQ…

● Les améliorations de performance du serveur

Pistes d'amélioration

Page 37: Mettez du temps réel dans votre Drupal avec Node JS

@naholyr / @mguillermin