Question

Hi does anybody know how to put in place a quick code example of a Sinatra app running on top of Celluloid:IO and using websocket?

I know of the existance of Reel for Celluloid ("Reel is a fast, non-blocking 'evented' web server built on top of Celluloid:IO" ... and supports websockets straight away) but nonetheless I'd like to keep using Sinatra because I like it, I've become accustomed with it, and I'd rather not rewrite a lot of code...

Hope you can help.

Was it helpful?

Solution

Celluloid::IO has an evented HTTP/WebSocket server called Reel ( http://github.com/celluloid/reel ), which is best setup for what you want, but still, this is pretty new, apart from Thin and Rainbows. This goes beyond Sinatra and has to involve Rack itself. So far it has been specific to certain HTTP servers, and each "Rack Handler" had approached WebSockets their own way. Now it is somewhat standardized, but in Rack 2.0 it will become permanent. I'd guess this temporary way is going to remain, but become more mature in 2.0 than it is in +1.5.* now.

This is about to be released into the master branch of Reel, but is right now in a branch of halgorium's fork, here:

https://github.com/halorgium/reel/tree/hijacked-websocket

The ongoing progress of this issue is here:

https://github.com/celluloid/reel/issues/42

Implementation of this feature involves interacting with pretty new and somewhat temporary functionality called the hijack API in Rack, underneath Sinatra. It is fairly convoluted but once you get the hang of it, it is pretty cool. Complete information on this is here:

...where it all got decided in a github thread: https://github.com/rack/rack/pull/481

There is no formal support for WebSockets through Rack hijack for Sinatra yet, and none is planned except by Middleware, according to @rhk. So it'll always be something you selectively handle, based on your server and choice of implementation style.

The way I've handled it is to use Reel, but Puma ( http://puma.io ) is also very good. Any hijack_io capable HTTP server will operate the same. The way I do it is illustrated in a gist linked below. It uses websocket-protocol-ruby to actually handle interaction with the client, and on the client side, I use portal.js rather than just the plain HTML5 approach. I believe it to be much better.

Portal.js: https://github.com/flowersinthesand/portal

websocket-protocol-ruby: https://github.com/faye/websocket-protocol-ruby

It all hinges on this piece, as mentioned in the Rack API thread on github:

env['rack.hijack'].call
@env = env
@io = env['rack.hijack_io']

There are two ways to use hijack_io, but as I said, it is very Rack involved. There is no much Sinatra code out there, because it's not really a Sinatra thing. Again, as I mentioned, it's not even really planned to become seamless. It'll be a sinatra/contrib thing or some other Middleware. So here is my way, in one instance where I use hijack_io, as a rough sketch.

...a gist: https://gist.github.com/digitalextremist/5441315

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top