Pusher is a glitzy websockets service for pushing messages from server to clients. I wondered how difficult it would be to copy their syntax.
The server is a ruby rack application that must be run or mounted. It is accessed globally just like the real Pusher.
# config.ru
require 'faye'
class Pusher
@server = Faye::RackAdapter.new(mount: '/faye', timeout: 25)
def self.call(env)
@server.call(env)
end
def self.trigger(channel, event, data = nil)
@server.get_client.publish("/#{channel}", event: event, data: data)
end
end
Assuming we're listening on 9292, the following code will get websockets working on the client.
var faye = new Faye.Client('http://localhost:9292/faye');
window.pusher = {
subscribe: function(channel) {
var handlers = {};
faye.subscribe('/' + channel, function(message) {
handlers[message.event](message.data);
});
function bind(evt, handler) { handlers[evt] = handler; }
return { bind: bind };
}
};
21 LOC.
To cascade it with a sinatra app takes a few more lines of code, and serves as an example of a chat application.
# config.ru
require 'sinatra'
get '/' do
erb :index
end
post '/messages' do
Pusher.trigger('messages', 'create', params[:messages])
'message created'
end
run Rack::Cascade.new([ Pusher, Sinatra::Application ])
Client subscriptions work the same as well.
<!-- views/index.html.erb -->
<script src="http://localhost:9292/faye.js"></script>
<script>
var channel = pusher.subscribe('messages');
channel.bind('create', function(message) {
console.log(message);
});
</script>
Use the same syntax, and sub out Pusher for load-balanced redis-backed auto-scaling faye applications in production.
To test it out locally, run the cascaded app specifying the production environment. The puma web server deals with sockets nicely, and is multi-threaded.
$ gem install puma
$ puma config.ru -p 9292 -e production
Open http://localhost:9292 in a browser, and open the console.
$ curl localhost:9292/messages -d "message=hello"
The message "hello" should appear in the console of the web browser.