XMPP: Private XML storage with strophe.js and ejabberd

During the last days I was playing around with a Javascript web chat application using strophe.js. To save user preferences on the ejabberd XMPP server I use Private XML storage (XEP-0049). The specification is pretty straight forward, but due to the lack of a real world example it still took me a while to get it working — hence this post. Thanks to badlop from the ejabberd@conference.jabber.ru XMPP chat room for valuable pointers. Here is how I did it:

1. Make sure mod_http_bind and mod_private are activated in ejabberd.cfg:

{modules,
 [
  {mod_http_bind, []},
  {mod_private, []},
  ...
 ]}.

2. Open BOSH connection to XMPP server (in your Javascript application):

sc = new Strophe.Connection('/http-bind/');
sc.connect('user@example.org', 'password');

3. Build and send IQ stanza for storing data:

var stanza = $iq({type: 'set', id: '_set1'})
  .c('query', {xmlns: 'jabber:iq:private'})
  .c('myclient', {xmlns: 'myclient:prefs'})
  .c('mypreference', 'yes')
  .tree();
sc.sendIQ(stanza);

Replace “myclient” and “myclient:prefs” with your own invented namespace and use your key/value names instead of “mypreference”/”yes”.

The IQ stanza sent to the server will look something like this:

<iq type='set' id='_set1' xmlns='jabber:client'>
  <query xmlns='jabber:iq:private'>
    <myclient xmlns='myclient:prefs'>
      <mypreference>yes</mypreference>
    </myclient>
  </query>
</iq>

Server response:

<iq xmlns='jabber:client' from='...' to='...' id='_set1' type='result'>
  <query xmlns='jabber:iq:private'/>
</iq>

4. Build and send IQ stanza for retrieving data:

var stanza = $iq({type: 'get', id: '_get1'})
  .c('query', {xmlns: 'jabber:iq:private'})
  .c('myclient', {xmlns: 'myclient:prefs'})
  .tree();
sc.sendIQ(stanza, parsePrefs);

function parsePrefs(element) {
  ...
}

Sent to server:

<iq type='get' id='_get1' xmlns='jabber:client'>
  <query xmlns='jabber:iq:private'>
    <myclient xmlns='myclient:prefs'/>
  </query>
</iq>

Server response:

<iq xmlns='jabber:client' from='...' to='...' id='_get1' type='result'>
  <query xmlns='jabber:iq:private'>
    <myclient xmlns='myclient:prefs'>
      <mypreference>yes</mypreference>
    </myclient>
  </query>
</iq>

5. Write parsePrefs() function and enjoy your XML storage! 🙂

Questions?