if(($ACT == 'edit' || $ACT == 'preview') && $INFO['editable']){ ?> } else { ?> } ?>
XEP-0060 defines a Publish-Subscribe extension to the XMPP protocol. Ralph Meijer has written a gateway to interface to the XMPP world via HTTP RPC: Idavoll implements a Jabber publish-subscribe service component, as defined in XEP-0060, aiming to be fully compliant and mostly complete.
I use idavoll for the DokuWiki pubsub plugin and started this wiki page to collect resources during development.
The basic concept works as follows:
Here: the entities are web-servers running a CMS (wiki, repositories etc); the nodes are XML data-containers.
The idavoll gateway accepts Atom-Entries (and Atom-Feeds) as payload1). The content inside the Atom can be any [XML-encoded] data.
Each node has a unique identifier - the NodeID or xmpp-uri - which is generated when publishing an item for the first time.
A document made up of multiple entries can be represented as a feed aka. collection. XEP-0060 defines a collection node as «A type of node that contains nodes and/or other collections but no published items. Collections make it possible to represent hierarchial node structures».
Luckily idavoll hides the gory details, and offers a neat way to “tunnel and distribute” HTTP requests. It runs along with a underlying jabber daemon next to the webserver(s).
This document is a howto use the HTTP-RPC interface of idavoll, follow me walking-through using the interface..
Detailed documentation is available at
see idavoll's dependencies and installation instructions.
sudo apt-get install python-pkg-resources python-twisted-web2 python-twisted-conch python-twisted-words python-simplejson sudo apt-get install jabberd2
#sudo easy install wokkel #sudo easy install idavoll sudo easy_install https://svn.ik.nu/wokkel/trunk/wokkel sudo easy_install https://svn.ik.nu/idavoll/trunk cd /tmp sudo twistd idavoll-http --jid=localhost tail -f twistd.log sudo true && sudo cat twistd.pid | sudo xargs kill
Quick test:
$curl http://localhost:8086/list [""] $curl http://localhost:8086/publish <html><head><title>405 Method Not Allowed</title></head><body><h1>Method Not Allowed</h1>The requested method GET is not supported by /publish.</body></html>
idavoll listens for HTTP requests per default on port 8086. Unless noted otherwise requests must be HTTP POSTs.
Parameters need to be url-encoded and added as query-string to the request URL.
Data (if present) must sent directly after the HTTP Header without waiting for a 100 continue
.
Name | /publish |
---|---|
Parameters | uri (string, optional) xmpp-uri |
Data | Atom entry to publish. The Content-type needs to be application/atom+xml;type=entry;charset=utf-8 .If there is no content, a node-deletion is published. |
Returns | JSON encoded xmpp-uri of the published item. |
Description | publish new content; if no xmpp-uri given create a new one. |
Name | /subscribe |
---|---|
Parameters | none |
Data | JSON encoded array of content-type application/json $data['callback']='<callback-url>'; $data['uri']='<xmpp-uri>'; |
Returns | no-content - HTTP status-code 204 on success. |
Description | subscribe to updates of an xmpp-node. The gateway will send HTTP-POST requests to the specified callback-url. see notification handling below. |
Name | /unsubscribe |
---|---|
Parameters | none |
Data | JSON encoded array of content-type application/json $data['callback']='<callback-url>'; $data['uri']='<xmpp-uri>'; |
Returns | no-content - HTTP status-code 204 on success. |
Description | unsubscribe from receiving notifications. use the same parameters as for the subscribe request. |
Name | /delete |
---|---|
Parameters | uri (string) xmpp-uri |
Data | none content-type must be set to application/atom+xml;type=entry;charset=utf-8 |
Returns | JSON encoded array of known publications. |
Description | same as publishing empty content. |
Name | /items |
---|---|
Parameters | uri (string) xmpp-uri of feed |
Data | none |
Returns | JSON encoded array of entries in the feed. |
Description | query entries in a collection. |
Name | /list - HTTP-GET |
---|---|
Parameters | none |
Data | none |
Returns | JSON encoded array of known publications. |
Description | handy to test, debug or just see what's going on.. |
After successful subscription and for each published update to an xmpp node, idavoll notifies the subscriber via HTTP POST.
Here's an example in PHP to catch those and dump them. Idavoll ignores any replied data, but automatically unsubscribes if it receives a non 2xx HTTP status code2).
The registered callback
uri from the subscription request is used as given. Idavoll adds the originating XMPP URI to the HTTP_REFERER
header (as to not interfere with GET-parameters) and POSTs the Atom-Entry as received via XMPP.
<?php $PSlogfile= '/tmp/PubSub.debug'; error_log('CALLBACK '.date("c ").'request: '.print_r($_REQUEST, true)."\n", 3, $PSlogfile); notify_handler(); function notify_handler() { global $ip_whitelist; global $PSlogfile; $originating_xmpp_url = $_SERVER['HTTP_REFERER']; error_log('CALLBACK '.date("c ").'xmppurl: '.print_r($originating_xmpp_url,true)."\n", 3, $PSlogfile); $xmpp_payload = ''; $fh = fopen('php://input', 'r'); if ($fh) { while (!feof($fh)) { $s = fread($fh, 1024); if (is_string($s)) $xmpp_payload .= $s; } fclose($fh); } error_log('CALLBACK '.date("c ").'data-len:'.strlen($xmpp_payload)."\n", 3, $PSlogfile); if (empty($xmpp_payload)) { # remove subscription and delete page return; } # do sth with the $xmpp_payload - parse it as ATOM }
Idavoll includes support to discover and subscribe to feeds. It automatically creates a collection node for a given RSS or Atom and starts polling the feed, publishes changes. read more about this feature: http://idavoll.ik.nu/wiki/FeedAggregation
What's missing?
idavoll, wokkel, twisted and jabberd provide a method plus infrastructure for communication and put some constraints on the language. You're to supply the user-interface ;)
Publishing is easy. Managing subscriptions is not.. - the latter includes both user/admin wishes to subscribe to content as well as handle data-updates, format-translations etc. YMMV.
A first CMS using idavoll for sharing is anyMeta. Being a well administrated commercial CMS, anyMeta makes use of authoritative source and read-only mirrors which are subscribed to the authoritative source. In the spirit of data-portability these authoritative sources may move and hop to a different server; reversing the role of publisher and subscriber or even be removed. subscribers may also choose if to keep or delete content if the source gets unavailable…
Updates to a node are atomic transaction in the XMPP world. A later publication to a node invalidates the previous one. The jabber server responsible for the node is the authoritative source for the content. This mechanism does allow to build a distributed lock or coherent cache model: fi. one could publish drafts-documents to mark the beginning of a edit-cycle that ends in a re-publication. If an entity receives a Draft it can perform a context appropriate action like locking the page, merging content or reporting a conflict to the user either local or remote (send back a newer Draft).
Furthermore subscribers can implement automatic-actions such as retire subscriptions if the authoritative source gets unavailable or aggregate additional information that is not part of the publication itself. - Subscribers can also choose to act differently depending on content-signature or authentication credentials (eg oAuth over XMPP)..