It’s been over four years in the making, but I’m very happy to announce the release of Faye 1.0. The Faye project – both the pub/sub messaging tools and the WebSocket/Redis modules that have been extracted over time – have reached a level of stability where I think it’s grown out of the ‘beta’ 0.x phase of development. Judging by the volume of bug reports and questions I get, the codebase has settled into something stable, usable, and free of commonly encountered faults.
The 1.0 release does not introduce many new major features, but rather builds on the stability of the 0.8 release and adds some much-needed polish in a few areas. Let’s start with the big changes you need to be aware of.
First, several methods have been removed. The most significant of these is the
server’s listen()
method. This was really just a little sugar over starting an
HTTP/HTTPS server and attaching Faye to it, and over time the amount of
different options people needed, from configuring the SSL cipher suite to
picking a different Ruby webserver, indicates this one method should not try and
cover all use cases. Instead, users should set up their HTTP server as they
want, and bind Faye to it. The documentation covers how to do this.
On the client side, getClientId()
and getState()
have been removed. They
were only ever there to support tests, they were never documented, and I have
constantly discouraged their use. If you’re going to miss them and don’t know
how to adapt your application, please ask the mailing list.
At the protocol level, the server no longer forwards the clientId
field of
messages to subscribers. I have discouraged use of this value as a security
credential, and it was never intended as such, but to remove the risk for people
who are using it this way I have made sure it does not get shared between
clients.
Those are all the breaking changes. There’s a few places where existing APIs still work but have been augmented with modern equivalents.
Objects that represent publication/subscription and respond to the
callback()
/errback()
API are now Promises, and callback/errback are
internally implemented on top of then()
. This is a spec-compatible promise
implementation and should interoperate with any other promise library you’re
using.
Objects like the server/adapter that respond to bind()
for handling events now
implement the EventEmitter
API. bind()
still works, it’s just sugar for
on()
/addListener()
.
Elsewhere there is plenty of polish and modernisation. At the transport level,
custom header support has been added to the cross-origin-long-polling
and
server-side websocket
transports. When using a client outside the browser,
all transports now support cookies and share a cookie jar scoped to the
client. The transports have all been refactored and are now more reliable at
detecting and recovering from network errors and from client
devices/applications going to sleep.
In the Client
class, we’ve added a ca
option to the constructor; like
elsewhere in the core Node APIs this lets you pass in an array of trusted server
certificates if you need to go beyond the certificates trusted by OpenSSL.
Clients can also be instantiated with URI objects (from Node’s url.parse()
or
Ruby’s URI.parse()
) instead of URL strings, and they are treated as objects in
all internal URL-handling code. You can also use protocol-relative URIs in the
browser, no problem.
In Ruby, some major changes mean that we now support JRuby. For example, Yajl
has been replaced with MultiJson so you can choose the JSON engine that’s right
for your project. And you no longer need to use Thin; Faye::RackAdapter
supports the rack.hijack
streaming API supported by Puma, Rainbows 4.5 and
Passenger 4.0, so you have more choices for which server to use (this was a
major motivator for the removal of the Thin-specific listen()
method).
Beyond all these little bits of polish, we come to the one real new feature of 1.0. Until now, Faye has not let you access HTTP request data in server-side extensions, since the aim was to hide all the messy transport details. But over the years it’s become apparent some people want to use various HTTP auth mechanisms and other features in their extensions, so Faye 1.0 makes this available with the caveat that usage is at your own risk. For certain HTTP features, you must read the updated security docs, particularly the material on CSRF protection.
In short, if your extension methods have 3 parameters, the second one will now
be a request object (http.Request
on Node, Rack::Request
on Ruby). This
gives you access to the path, headers and body of the request, which you can use
to filter messages.
server.addExtension({
incoming: function(message, request, callback) {
if (request.headers.authorization !== 'open sesame') {
message.error = '403::Access denied';
}
callback(message);
}
});
2-parameter extensions still work exactly the same as they always did.
That just about covers the main changes in the 1.0 release. As always, file bugs on GitHub and ask questions on the mailing list.
On a personal note, I want to thank everyone who has built stuff, asked questions, reported bugs, fixed code, and donated their time to this project. It has been and continues to be really rewarding to work on, and has taken me all over the place talking at confs and meeting people who want to hear about it. It was particularly gratifying to see Faye powering the GOV.UK exhibit at the 2013 Design Awards, at one of my favourite London museums. I’m proud to have helped a lot of projects build on my work but there’s nothing quite like seeing something you helped build in the real world, especially somewhere as dear to me as the Design Museum.
Thank you, and I hope you keeping putting Faye to good use.