Faye 0.7: new event APIs and an open WebSocket stack

I’m very excited to announce the release of Faye 0.7, available now through gem and npm. This release focuses on two main areas: new event APIs for hooking into the framework, and a polished stand-alone WebSocket implementation.

Let’s deal with the new APIs first. The main one is an API for listening to what’s going on inside the engine. People have historically used extensions for various sorts of monitoring but there are certain events extensions can’t catch. For example, when a client session ends due to inactivity rather than because the client sent a /meta/disconnect message, there’s no way to detect that. Well now you can:

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

bayeux.bind('disconnect', function(clientId) {
  // event listener logic
});

There’s a complete API for listening to all the major events in Faye’s pub/sub model, and I encourage you to use it over extensions if all you want is a little monitoring.

The second new event API is on the client side. Faye will always attempt to reconnect for you if the network connection is dropped, but often it’s useful to signal the connection loss to the user. You can now do this using these events on the client:

client.bind('transport:down', function() {
  // Fires when the connection is lost
});
client.bind('transport:up', function() {
  // Fires when the connection is established
});

You don’t need to reconnect the client yourself, these events are just there to notify you of what’s going on. And to give you even more feedback, publish() now supports the same Deferrable API as subscribe().

Now onto the WebSocket changes. The first of which is that Faye now includes a WebSocket client, and will use this instead of HTTP for server-side clients. The server-side HTTP transports now support cookies, and all transports support SSL. The WebSocket stack has received a lot of bug fixes based on the Autobahn test suite, and is now one of the most complete WebSocket implementations available for Node or Ruby. (Want proof? Here’s the server and client test report.)

Faye’s WebSocket stack also has the advantage of having been reasonably decoupled from the rest of the codebase since it was first introduced in version 0.5, and now I’ve taken the decision to open it up for everyone to use. It makes adding WebSocket support to existing Node and Rack apps very easy indeed; you can drop sockets right into your existing application and they expose the same API you use in the browser:

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

var server = http.createServer();

server.addListener('upgrade', function(request, socket, head) {
  var ws = new faye.WebSocket(request, socket, head);

  ws.onmessage = function(event) {
    ws.send(event.data);
  };

  ws.onclose = function(event) {
    console.log('close', event.code, event.reason);
    ws = null;
  };
});

server.listen(8000);

The sockets implement the standard WebSocket API on both the server- and client-side. They handle text and binary data, and transparently handle ping/pong, close, and fragmented messages for you. The server supports a wide range of protocol versions and the client should be able to talk to any modern WebSocket server.

If, however, you don’t want to use WebSockets for your Faye client, you can easily switch them off:

client.disable('websocket');

I think the WebSocket tools are important because while there are plenty of messaging frameworks and transport abstractions around (e.g. libraries that present the WebSocket API on top of other wire transports), the state of pure WebSocket implementations seems to be somewhat lacking at the moment. Hopefully this can improve the situation as we move towards broader socket support across the web.

So that’s about it for the 0.7 release. Work is already underway on the 0.8 release, and the current plan is to focus on refactoring. The Faye distribution contains several components, such as the WebSocket code and the Redis backend, that can be broken off into separate projects. Indeed, work is already underway on extracting the WebSocket code for Ruby. As usual, this release should be backward compatible but if you have problems don’t hesitate to post on the mailing list.