If you aren’t aware already, HTML5 has Websockets API – enabling bidirectional communication between client and server. You should check Ilya’s post Ruby & WebSockets: TCP for the Browser for a better explanation.
Starting with version 0.9, Cramp has in built support for Websockets. Unlike other solutions, Cramp extends the underlying webserver ( thin or Rainbows! ) to add the websockets superpower. As websockets protocol is an extension of the HTTP protocol, hopefully the webservers will be supporting it out of the box once websockets are well established.
For working with websockets, Cramp::Controller provides a class called Cramp::Controller::Websocket. Cramp::Controller::Websocket is very similar to Cramp::Controller::Action. If you don’t know much about Cramp::Controller::Action, you could read my introductory post on cramp.
As Cramp extends the underlying webserver to support websockets, you must tell it which webserver you are using :
Cramp::Controller::Websocket.backend = :thin # or :rainbows |
Cramp::Controller::Websocket adds a new callback called on_data in addition to the functionalities available to Cramp::Controller::Action. Whenever the client sends any data over the websocket, Cramp will call the specified on_data callbacks, passing client supplied data as the lone argument. To send any data to the client over the websocket, you could use render() as usual.
Here’s a very basic example using Cramp’s websockets, which echoes everything received over the socket :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
require 'rubygems' require 'cramp/controller' Cramp::Controller::Websocket.backend = :thin class WelcomeController < Cramp::Controller::Websocket on_data :received_data def received_data(data) render "Got your #{data}" end end Rack::Handler::Thin.run WelcomeController, :Port => 3000 |
Demo
I have ported Jetty’s Websocket example to Cramp. You can find the code at http://gist.github.com/273794. It’s currently running at http://cramp.in:8080, however I wouldn’t bring it up once it dies of natural causes :) Make sure you open the demo in Google Chrome or Webkit. On a related note, Firefox should have websockets support soonish.
But what about the fucking Internet Explorer ?!
As you might have guessed, no such luck as websockets support for IE. But not all is lost. You can very easily fallback to flash sockets if the browser doesn’t have websockets support. Check out web-socket-js library by Hiroshi Ichikawa which does exactly that.
Fabio’s Demo Application
Fabio Akita has written an excellent demo application for Cramp – http://github.com/akitaonrails/cramp_chat_demo. The chat application has two versions : long polling and websockets. The websockets version even falls back to flash socket if the browser doesn’t provide the support. It’s an excellent example of how you should write cramp applications, and rack applications in general.







What about the fucking Internet Explorer?
Fuck em, they don’t deserve internets.
You’ve got Ilya’s name misspelled. Just sayin’.
@Alex : Fixed it. Thanks for pointing it out!
Re. “F@#ng Internet Explorer,” you can also use the Kaazing WebSocket Gateway, which provides complete emulation for all the old (read: non-Chrome) browsers.
@Peter : Emulation is already possible over flash sockets. Check out Akita’s demo application
Hi Pratik. Truly excellent work!
I’ve got a question: in your demo you’re using Usher for routing. I tried Rack::Builder and Rack::URLMap directly but they don’t seem to work… Any idea why? I presume you used Usher for that very reason.
Hey Ismael,
I’m not sure why Rack::Builder and Rack::URLMap aren’t working. They really should work. I used Usher so that I get param parsing + routing for free, no other reason.
@pratik yes it’s weird, I’ll give it another try tomorrow.
Also: I’m doing a lighting talk at LRUG tomorrow on WebSocket + EventMachine. Not Cramp specifically but I want to mention it as the most polished solution I’ve found so far.