Si son nom n’est pas facile à retenir, le projet PubSubHubbub recouvre à la fois un protocole de type publication/abonnement pour le web, ayant recours au format Atom ou RSS (RSS 2.0) pour les données, ainsi qu’une implémentation de référence de ce protocole pour la partie serveur.
Visant la simplicité, ce nouveau protocole spécifié par Google, applique au web le modèle de publication/abonnement connu, que l’on retrouve avec d’autres technologies telles que JMS (les « topics »), WS-Notification, l’extension de protocole Publish-Subscribe (XEP-0060) d’XMPP, etc.
L’intérêt d’un tel modèle est que l’on peut publier un message, et que les abonnés en soient automatiquement notifiés sans qu’il ait un lien direct entre ces derniers et l’émetteur du message ; en effet, dans le cas de PubSubHubbub, c’est le « hub » qui gère les mécanismes de publication, d’abonnement/désabonnement, et de distribution des messages, qui sont des documents Atom ou RSS. Toutes les interactions entre les émetteurs et le hub, ainsi qu’entre les abonnés et le hub, se font sur le protocole HTTP selon la spécification PubSubHubbub.
Dans ce qui suit, voyons comment une application web développée avec le framework web agile Grails peut entrer en interaction avec un hub supportant PubSubHubbub ; pour cela, prenons comme fil conducteur la démonstration PubSubHubbub dans notre application GrailsBox.
En fait, le formulaire présent sur cette page vous permet de tester le hub de votre choix, et vous avez également accès à un flux Atom de test. Vous pourrez déclencher les opérations décrites plus haut : publication, abonnement et désabonnement, avec la définition de l’URL de rappel (callback) sur laquelle le hub pourra solliciter votre application à des fins de vérification et de notification.
Le flux de test Atom
L’application GrailsBox conserve un flux Atom de test en mémoire, d’URL http://www.grailsworks.com/grailsbox/pubSubHubBub/atom, que vous pouvez modifier uniquement de deux manières, à partir de la page de démonstration PubSunHubbub : soit en ajoutant une nouvelle entrée au flux (lien « Ajouter une entrée »), soit en effaçant toutes les entrées du flux (lien « Remettre à zéro »). Le but de ce flux est de pouvoir tester PubSubHubbub en le publiant sur un hub particulier après une modification. Conformément à la spécification, ce flux contient dans l’élément document feed, les éléments link suivants :
<link rel='self' href='http://www.grailsworks.com/grailsbox/pubSubHubBub/atom' />
S’abonner ou se désabonner
Commençons par le mécanisme d’abonnement/désabonnement ; dans une application Grails, l’envoi d’une requête HTTP d’abonnement ou de désabonnement vers un hub peut se faire grâce à un client HTTP à partir d’un contrôleur ou, mieux encore, d’un service Grails. Dans les exemples qui suivent, nous utiliserons la classe HTTPBuilder du projet du même nom ; cela suppose que, dans votre projet Grails, vous ayez ajouté la librairie du projet, ainsi que ses librairies dépendantes.
Une requête d’abonnement ou de désabonnement, avec HTTPBuilder, peut se réaliser ainsi :
import static groovyx.net.http.Method.POST
import static groovyx.net.http.ContentType.URLENC
// …
def builder = new HTTPBuilder(params.urlhub)
builder.request(POST, URLENC) {
def args = [
// Par exemple : http://www.grailsworks.com/grailsbox/pubSubHubBub/hubCallback
'hub.callback': params.urlcallback,
'hub.mode': params.mode,
'hub.topic': params.topic,
'hub.verify': params.verify
]
if (params.verify_token)
args.'hub.verify_token' = params.verify_token
body = args
// response handler for a success response code:
response.success = { resp ->
render "Abonnement ou désabonnement réussi (code de statut ${resp.statusLine.statusCode}) !"
}
// handler for any failure status code:
response.failure = { resp ->
render erreur("Echec d'abonnement ou de désabonnement (code de statut : ${resp.status} : ${resp.statusLine.reasonPhrase}) !")
}
}
Dans l’exemple ci-dessus (qui reprend le contenu d’une action de contrôleur Grails), params est une Map Groovy contenant les différents paramètres tirés d’un formulaire et repris dans l’envoi de la commande de type POST envoyée vers l’URL du hub contenue dans l’entrée params.urlhub. Vous pouvez toujours utiliser la valeur http://pubsubhubbub.appspot.com/ qui est l’URL du hub du projet PubSubHubub qui, à noter, est déployé sur Google app engine.
Parmi les autres paramètres à transmettre dans le corps de requête, dont le Content-type doit être application/x-www-form-urlencoded, nous trouvons également principalement : le paramètre hub.mode ayant la valeur subscribe ou unsubscribe, pour une requête d’abonnement ou de désabonnement respectivement ; le paramètre hub.topic donnant tout simplement l’URL du flux Atom, ou RSS, auquel on souhaite s’abonner ou se désabonner (par exemple http://www.grailsworks.com/grailsbox/pubSubHubBub/atom pour le flux Atom de test) ; et le paramètre hub.callback définissant une URL de rappel vers laquelle les notifications du hub seront acheminées vers votre application.
Cette dernière URL permet également au hub de déterminer si celle-ci est une URL valide en la sollicitant par une requête HTTP de type GET (et certains paramètres), tandis que les notifications du hub seront transmises au travers de requêtes de type POST avec des données Atom (ou RSS).
Quelle URL utiliser et comment répondre à ces requêtes avec Grails ?
Tout simplement en utilisant une action de contrôleur Grails, qui correspond donc à une URL précise. Voici un exemple d’une telle action de contrôleur :
if (params['hub.mode'] in ['subscribe', 'unsubscribe']) {
if (params.'hub.verify_token' == '…') {
// …
render params['hub.challenge']
}
else {
response.status = 404
render ""
}
}
else {
// Traiter ici la notification dans request.XML
// …
render ""
}
}
Le premier test de cette action permet de déterminer si le hub nous transmet une requête de vérification ou bien de notification.
Dans le premier cas, si l’on souhaite confirmer l’abonnement ou le désabonnement au/du flux dont l’URL est passée dans le paramètre hub.topic, il suffit de renvoyer la valeur du paramètre hub.challenge transmis dans la requête ; dans le cas contraire, une réponse est retournée avec la valeur de statut 404. Il est aussi possible, comme dans le cas de notre exemple de code, de tester la valeur du paramètre hub.verify_token qui devrait correspondre à celle transmise pour le paramètre de même nom, lors de l’envoi de la requête d’abonnement ou de désabonnement.
Dans le second cas, lorsque l’URL de rappel reçoit une notification, le hub transmet, sous la forme d’un flux XML Atom (ou RSS), toutes les entrées du flux à l’origine de la notification, qui ont été modifiées à la suite d’une nouvelle publication de ce flux.
Grâce à Grails, le flux Atom (ou RSS) peut être aisément traité en accédant à l’objet request.XML qui est de type groovy.util.XmlSlurper !
Publier
La publication d’un flux Atom/RSS, qui est plus simple, demande l’envoi d’une requête de type POST vers l’URL du hub cible, avec deux paramètres dans le corps de la requête : l’opération demandée, et l’URL du flux.
Voyons comment réaliser une publication grâce à HTTPBuilder :
builder.request(POST, URLENC) {
body = [
'hub.mode': 'publish',
'hub.url': params.topic
]
// response handler for a success response code:
response.success = { resp ->
render "Publication réussie (code de statut ${resp.statusLine.statusCode}) !"
}
// handler for any failure status code:
response.failure = { resp ->
render erreur("Echec de la publication (code de statut ${resp.status}, raison : ${resp.statusLine.reasonPhrase}) !")
}
}
Le code Groovy ci-dessus est extrait de la démonstration de PubSubHubbub dans notre application GrailsBox, et provient plus précisément de l’action qui gère la publication d’un flux après soumission du formulaire de publication ; c’est la raison pour laquelle les deux paramètres à transmettre au hub, ainsi que l’URL du hub, sont tirés de l’objet params. On donne la valeur publish au paramètre hub.mode pour indiquer qu’il s’agit d’une publication, et au paramètre hub.url, l’URL du flux à publier.
Il existe différents hub publiques supportant le protocole PubSubHubbub, alors n’hésitez pas à utiliser la page de démonstration de PubSubHubbub de GrailsBox pour vos tests, après avoir implémenter dans votre application Grails, ou dans un autre technologie serveur, un contrôleur susceptible de gérer l’URL de rappel.
Et si jamais vous modifiez et publiez notre flux de test Atom auquel vous vous seriez auparavant abonné, sur le hub de référence du projet PubSubHubbub, nous en serions alors également notifiés !