Les applications Web ont de plus en plus la nécessité d’être dynamiques et de se comporter comme des applications de bureau traditionnelles.
Du fait de la décentralisation des données et des traitements par rapport à l’utilisateur, il devient important de pouvoir interagir de façon bidirectionnelle entre le serveur et les clients.
Dans cet article nous allons voir comment Faye, une bibliothèque JavaScript et Ruby peut nous aider a écrire de telles applications.
Faye est une bibliothèque divisée en deux parties : le serveur, disponible en JavaScript ou Ruby, et le client, disponible uniquement en JavaScript (puisque chargé dans le navigateur).
Cette bibliothèque permet d’implémenter le protocole de Bayeux dans votre application.
Pour faire court, ce protocole décrit une façon pour un serveur et plusieurs clients de mettre en place un modèle publish/subscribe par HTTP.
L’objectif étant d’établir des connexions persistantes, il faut une technologie le permettant. C’est la partie transport du protocole.
Faye assure cette partie en utilisant l’une des techniques suivantes :
POST
HTTP ;Comme un bon exemple est sûrement plus parlant, nous allons écrire une petite application de chat utilisant Faye.
On commence par créer un dossier pour notre projet, puis après s’être déplacé
dedans on installe les module node
nécessaires :
$ npm install express faye
La partie serveur est plutôt simple, on va utiliser Express pour
servir un dossier qui contiendra un fichier index.html
où l’on écrira plus
tard le code du client.
On écrit le fichier index.js
qui, lancé avec node
, démarrera l’application
en écoutant sur localhost:3000
:
var faye = require('faye'),
express = require('express'),
bayeux = new faye.NodeAdapter({mount: '/faye'})
app = express()
app.use(express.static(__dirname))
app.use(bayeux)
app.listen(3000)
On peut alors lancer ce fichier à l’aide de la commande node index.js
et
ouvrir son navigateur sur http://localhost:3000.
Il permet de servir les fichiers statiques du dossier avec Express,
et d’avoir un serveur Faye qui écoute à l’adresse /faye
.
Ce serveur simple ne fait rien à par permettre de relayer des messages entre les différents clients connectés.
Commençons par écrire l’interface de notre client de chat :
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8" />
<title>faye demo</title>
<link rel="stylesheet" href="stylesheets/reset.css" type="text/css" media="screen" charset="utf-8" />
<link rel="stylesheet" href="stylesheets/main.css" type="text/css" media="screen" charset="utf-8" />
</head>
<body>
<div id="toolbar">
<form action="/" name="chat-form">
<input id="nick" name="nick" type="text" placeholder="nick" />
<input id="message" name="message" type="text" placeholder="message" />
<input type="submit" value="Send" />
</form>
</div>
<dl id="message-list"></dl>
<script type="text/javascript" src="faye/client.js"></script>
<script type="text/javascript" src="script/client.js"></script>
</body>
</html>
Vous remarquerez que l’on inclut le script faye/client.js
. Celui-ci est servi
par le serveur que l’on a écrit précédemment.
Le code même du client est placé dans le fichier script/client.js
:
;(function () {
var client = new Faye.Client('/faye'), // (1)
ui = {}
ui.messageList = document.getElementById('message-list') // (2)
ui.chatForm = document.forms['chat-form']
ui.nickField = document.getElementById('nick')
ui.messageField = document.getElementById('message')
function addMessage(message) { // (3)
var dt = document.createElement('dt'),
dd = document.createElement('dd'),
frag = document.createDocumentFragment()
dt.textContent = message.nick
dd.textContent = message.message
frag.appendChild(dt)
frag.appendChild(dd)
ui.messageList.appendChild(frag)
}
client.subscribe('/chat', function(message) { // (4)
addMessage(message)
})
ui.chatForm.addEventListener('submit', function(event) { // (5)
client.publish('/chat', {
nick: ui.nickField.value,
message: ui.messageField.value
})
ui.messageField.value = ""
ui.messageField.focus()
event.preventDefault()
}, true)
})(window);
Détaillons le pas à pas.
Faye.Client
;addMessage
permet d’ajouter une ligne de message dans la liste
des messages reçus ;/chat
en passant une fonction de callback qui sera
appelée à chaque message reçu sur ce canal et à laquelle le message sera
passé en argument. Ici, cette fonction appelle simplement addMessage
;Vous voyez rapidement que la partie la plus compliquée est celle qui concerne la manipulation du DOM, et non la communication entre les clients.
Vous pouvez maintenant ouvrir deux navigateurs et accéder à http://localhost:3000 puis tester l’échange de message entre deux clients.
Un mécanisme d’extensions permet de rajouter des fonctionnalités aux clients ou au serveur.
Nous allons rajouter un mécanisme de logging au serveur. Ceci est presque trivial !
On rajoute dans le fichier index.js
, avant la configuration de l’application :
var consoleLogger = function(type) {
return function(message, callback) {
console.log(type + ': ' + JSON.stringify(message, null, 4))
callback(message)
}
}
var consoleLoggerExtension = {
incoming: consoleLogger('incoming'),
outgoing: consoleLogger('outgoing'),
}
bayeux.addExtension(consoleLoggerExtension)
Un extension est un objet possédant des propriétés incoming
et/ou outgoing
,
permettant respectivement d’agir sur les messages entrant ou sortants (ici du
côté du serveur).
Le mécanisme est strictement identique au niveau du client.
On peut notamment bloquer des messages en ajoutant un champ error
sur l’objet
du message.
Si vous relancez le serveur, vous verrez apparaître dans la console tous les messages reçus et émis par le serveur.
La lecture du protocole de Bayeux est le point de départ pour pouvoir bâtir des applications plus conséquentes en utilisant Faye. Il est assez simple en soi et les concepts sont implémentés fidèlement dans Faye, à l’exception des canaux de service (entre un client et le serveur uniquement), l’auteur n’étant pas convaincu de leur intérêt.
On peut aussi obtenir un client côté serveur (server-side client) qui permet de publier sur les canaux auxquels les clients réguliers sont abonnés.
Le code de cette exemple est disponible sur notre compte GitHub, vous pouvez le télécharger librement et le modifier pour expérimenter avec Faye.
La documentation sur les extensions montre comment implémenter un système d’authentification basique pour que les clients ne voient que les messages auxquels ils ont accès.
Avec cette brique supplémentaire et la flexibilité de Faye, on peut développer des applications beaucoup plus riches faisant intervenir la communication entre clients.
Il faut enfin noter qu’une version Ruby du serveur est disponible dans le cas de l’utilisation au sein d’une stack Rack ou Rails. Elle reprend les mêmes fonctionnalités et quasiment la même API (en plus ruby-esque) que la version JavaScript.
L’équipe Synbioz.
Libres d’être ensemble.