Faye 0.5: WebSockets, protocol extensions API and CometD integration

It’s been a few months since the last major Faye update, and in the interim the new release ended up getting so much feature creep that I’ve decided to skip a version number. That’s how much awesome is in the new release! 0.2 versions worth! It’s now available through npm, as well as Rubygems:

# for Node
sudo npm install faye

# for Ruby
sudo gem install faye

Anyway, what’s new? First up, to satisfy the buzzword junkies (I mean, make the network layer more efficient) the Faye client and server now support WebSockets. This is totally transparent to the user; Faye will just use it instead of XMLHttpRequest or JSON-P if your browser supports it. We’re currently only supporting the draft-75 version of the WebSocket protocol, and that’s what’s in Chrome 5 and Safari 5. We’ll add draft-76 support as new browsers are released.

There is a major API addition in the form of an extension system. This essentially lets you add middleware-style filters that can modify incoming and outgoing messages both on the server and on the client. You can run arbitrary logic on every message passing through the system – including the /meta/* messages that the Bayeux protocol uses – in order to implement extensions to the protocol. Common uses for this include user authentication and message acknowledgement, but really the possibilities are wide open. This should satisfy those of you who’ve been forking away on GitHub adding extra functionality to the core components for the last few months.

Extensions are fully documented in the server-side documentation, and you’ll probably benefit from skimming the Bayeux protocol spec (it’s only small) if you want to write extensions.

The final major improvement is that Faye is now protocol-compatible with CometD, the reference implementation of Bayeux with a high-performance Java server. You can connect Faye clients to CometD servers and vice versa; this means you can use CometD as a drop-in replacement for Faye’s server if you find you need to scale out your Bayeux app. It even works with the new WebSocket support that just came out as part of CometD 2.0.

Apart from all that, the client now handles multiple subscriptions to the same channel and makes unsubscribing easy:

var subscription = client.subscribe('/foo', function() {
  // ...
});

// Later on...
subscription.cancel();

There’s a bunch more tweaks that make it all a little faster and more robust, in particular the clients are now much better at reconnecting and re-establishing subscriptions if there’s a network disconnection or the server goes down. This actually means you can take down one server and replace it with another implementation without restarting any of the clients.

There are some backward-incompatible changes forced by the introduction of WebSocket support. You now set up a Node server like this, without calling Faye during a request:

var http = require('http'),
    faye = require('faye');

var bayeux = new faye.NodeAdapter({
  mount:    '/faye',
  timeout:  45
});

// Handle non-Bayeux requests
var server = http.createServer(function(request, response) {
  response.writeHead(200, {'Content-Type': 'text/plain'});
  response.write('Hello, non-Bayeux request');
  response.end();
});

bayeux.attach(server);
server.listen(8000);

The attach() method places filters in front of your request handlers to intercept Bayeux calls, so make sure you call attach() after adding your own request handlers. We had to do this because HTTP and WebSocket traffic each go through different event handlers in Node, and making the user forward these calls to Faye would have introduced far too much boilerplate for my liking.

The Ruby version now only supports Thin as the frontend webserver. You should have been using this anyway, since it’s much better at highly concurrent traffic than almost anything else in the Ruby world, but just make sure you specify Thin when racking up your application:

rackup -s thin -E production config.ru

Faye makes use of some extensions to Thin from the Cramp project, so thanks to Pratik for open-sourcing that work.

I think that just about covers it for now. Grab a download, and let me know how you get on. I’ve already heard from a few folks doing cool things with it, and I’d love to hear more!