10-01-2011, 03:40 PM
(Modification du message : 10-01-2011, 03:42 PM par Sephi-Chan.)
Sur Beacon, seul l'envoi d'un message au serveur est crédité. On peut donc vraiment publier gratuitement un million de messages par mois.
Voici la très simple application de démonstration que je vous ai préparé : http://real-time-tutorial.heroku.com/ ainsi que son code source (en pièce jointe).
Ça implique de créer un compte sur Beacon.
La page d'accueil ne contient qu'un simple formulaire. Lorsque celui-ci est soumis, une requête POST est envoyée. Cet envoi est effectué de manière asynchrone (Ajax) afin de ne pas recharger la page, ce qui occasionnerai la perte des messages reçus jusque là.
La requête est captée par le contrôleur suivant :
Comme les champs de formulaire avaient les noms message[author] et message[content], on dipose d'un hash (un tableau associatif) message contenant nos clés author et content et leur valeurs.
Dans ce contrôleur, je récupère donc ce hash et crée un objet Message à partir de celui-ci. Cette classe message sert juste à simplifier le code du contrôleur en injectant une date parmi les attributs de l'objets et fournissant une méthode de validation.
Si notre message est valide, notre contrôleur instancie un objet Beacon (qui est un wrapper partiel et ultra-simplifié de l'API Beacon que j'ai écris pour l'occasion). L'utilisation d'une classe ici permet — comme pour la classe Message — de ne garder que l'essentiel dans le contrôleur, pour maximiser la lisibilité du code.
J'appelle ensuite la méthode publish de l'objet avec comme paramètre le nom du canal sur lequel je souhaite publier ainsi que les données que je souhaite y envoyer.
Cette opération aura pour résultat d'envoyer une requête HTTP au serveur de Beacon qui se chargera de retransmettre ces données aux clients qui écoutent ce canal.
L'écoute s'effectue du côté de Javascript :
Le script se charge de récupèrer la clé publique, nécessaire à l'écoute. On utilise ici une balise meta pour transmettre cette clé de Ruby à Javascript, ça évite de l'avoir en dur dans le code Ruby ET Javascript et ça évite aussi de déclarer une variable globale côté Javascript.
L'utilisation de l'API cliente de Beacon est documentée sur le site. Je n'ai fais que copier leur code : la seule chose à implémenter est le callback : que faire quand un message est reçu.
L'API étant un peu bizarre, on doit spécifier des callbacks et discriminer par canal ensuite. Si notre application avait plusieurs canaux, il faudrait faire attention à ça puisque ce callback serait appelé pour tous les canaux écoutés.
Quand un message arrive, on construit un peu de HTML et on l'ajoute à la fin de la liste messages.
Et c'est tout.
Je reviens un peu sur ce qui se cache derrière la méthode publish de ma classe Beacon.
Le service Beacon expose aux utilisateurs un service Web fonctionnant par HTTP. C'est un ensemble de scripts accessibles via HTTP (contrairement à d'autres systèmes comme SOAP, XML-RPC, etc.). Il s'agit d'une API REST dont voici les spécifications.
Par exemple, pour envoyer un message, il faut envoyer une requête HTTP avec la méthode POST à l'adresse api.beaconpush.com/1.0.0/:api_key/channels/:channel (où :api_key et :channel sont des placeholders pour notre API Key et le nom du canal).
Envoyer ce genre de requête se fait généralement via cURL (Curl pour PHP, Curb pour Ruby, etc.) ou par d'autres classes d'accès, bas niveau (Net::HTTP pour Ruby) ou haut niveau ([url=Patron]Patron pour Ruby[/url].
Ici, j'utilise Net::HTTP, c'est assez bas niveau et pas aussi joli que d'autres alternatives, mais ça permet de comprendre ce qu'on fait.
Pour authentifier l'appel (afin que tout le monde ne puisse pas publier sur vos channel, il faut ajouter un header nommé "X-Beacon-Secret-Key" à la requête, avec comme contenu votre clé secrète.
Il est indispensable de spécifier le corps de la requête (en l'occurrence, le contenu à envoyer, encodé en JSON) et sa taille (la longueur de la chaîne JSON produite).
Sephi-Chan
Voici la très simple application de démonstration que je vous ai préparé : http://real-time-tutorial.heroku.com/ ainsi que son code source (en pièce jointe).
Ça implique de créer un compte sur Beacon.
La page d'accueil ne contient qu'un simple formulaire. Lorsque celui-ci est soumis, une requête POST est envoyée. Cet envoi est effectué de manière asynchrone (Ajax) afin de ne pas recharger la page, ce qui occasionnerai la perte des messages reçus jusque là.
$('#send-message').submit(function(event){
var url = $(this).attr('action');
var data = $(this).serialize();
$.post(url, data, function(){
$('#message-content').val('').focus();
});
event.preventDefault();
});
La requête est captée par le contrôleur suivant :
post '/messages' do
message = Message.new(params[:message])
if message.valid?
beacon = Beacon.new(BEACON_API_KEY, BEACON_SECRET_KEY)
beacon.publish('chat', {
:author => message.author,
:content => message.content,
:timestamp => message.timestamp.strftime("%H:%M")
})
end
end
Comme les champs de formulaire avaient les noms message[author] et message[content], on dipose d'un hash (un tableau associatif) message contenant nos clés author et content et leur valeurs.
Dans ce contrôleur, je récupère donc ce hash et crée un objet Message à partir de celui-ci. Cette classe message sert juste à simplifier le code du contrôleur en injectant une date parmi les attributs de l'objets et fournissant une méthode de validation.
Si notre message est valide, notre contrôleur instancie un objet Beacon (qui est un wrapper partiel et ultra-simplifié de l'API Beacon que j'ai écris pour l'occasion). L'utilisation d'une classe ici permet — comme pour la classe Message — de ne garder que l'essentiel dans le contrôleur, pour maximiser la lisibilité du code.
J'appelle ensuite la méthode publish de l'objet avec comme paramètre le nom du canal sur lequel je souhaite publier ainsi que les données que je souhaite y envoyer.
Cette opération aura pour résultat d'envoyer une requête HTTP au serveur de Beacon qui se chargera de retransmettre ces données aux clients qui écoutent ce canal.
L'écoute s'effectue du côté de Javascript :
var beaconApiKey = $('meta[name=beacon-api-key]').attr('content');
Beacon.connect(beaconApiKey, [ 'chat' ]);
Beacon.listen(function(data){
var messages = $('#messages');
var message = $('<li />');
message.append($('<span class="timestamp" />').text('[' + data.timestamp + ']'));
message.append($('<span class="author" />').text('[' + data.author + ']'));
message.append($('<span class="message" />').text(data.content));
messages.append(message);
});
Le script se charge de récupèrer la clé publique, nécessaire à l'écoute. On utilise ici une balise meta pour transmettre cette clé de Ruby à Javascript, ça évite de l'avoir en dur dans le code Ruby ET Javascript et ça évite aussi de déclarer une variable globale côté Javascript.
L'utilisation de l'API cliente de Beacon est documentée sur le site. Je n'ai fais que copier leur code : la seule chose à implémenter est le callback : que faire quand un message est reçu.
L'API étant un peu bizarre, on doit spécifier des callbacks et discriminer par canal ensuite. Si notre application avait plusieurs canaux, il faudrait faire attention à ça puisque ce callback serait appelé pour tous les canaux écoutés.
Quand un message arrive, on construit un peu de HTML et on l'ajoute à la fin de la liste messages.
Et c'est tout.
Je reviens un peu sur ce qui se cache derrière la méthode publish de ma classe Beacon.
Le service Beacon expose aux utilisateurs un service Web fonctionnant par HTTP. C'est un ensemble de scripts accessibles via HTTP (contrairement à d'autres systèmes comme SOAP, XML-RPC, etc.). Il s'agit d'une API REST dont voici les spécifications.
Par exemple, pour envoyer un message, il faut envoyer une requête HTTP avec la méthode POST à l'adresse api.beaconpush.com/1.0.0/:api_key/channels/:channel (où :api_key et :channel sont des placeholders pour notre API Key et le nom du canal).
Envoyer ce genre de requête se fait généralement via cURL (Curl pour PHP, Curb pour Ruby, etc.) ou par d'autres classes d'accès, bas niveau (Net::HTTP pour Ruby) ou haut niveau ([url=Patron]Patron pour Ruby[/url].
Ici, j'utilise Net::HTTP, c'est assez bas niveau et pas aussi joli que d'autres alternatives, mais ça permet de comprendre ce qu'on fait.
Pour authentifier l'appel (afin que tout le monde ne puisse pas publier sur vos channel, il faut ajouter un header nommé "X-Beacon-Secret-Key" à la requête, avec comme contenu votre clé secrète.
Il est indispensable de spécifier le corps de la requête (en l'occurrence, le contenu à envoyer, encodé en JSON) et sa taille (la longueur de la chaîne JSON produite).
Sephi-Chan