Websockets made easy with Cramp 8

Posted by pratik
on Friday, January 15

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.

Comments

Leave a response

  1. Jim NeathJanuary 15, 2010 @ 08:28 PM

    What about the fucking Internet Explorer?

    Fuck em, they don’t deserve internets.

  2. Alex WolfeJanuary 15, 2010 @ 08:36 PM

    You’ve got Ilya’s name misspelled. Just sayin’.

  3. PratikJanuary 15, 2010 @ 08:42 PM

    @Alex : Fixed it. Thanks for pointing it out!

  4. Peter LubbersJanuary 29, 2010 @ 04:26 PM

    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.

  5. PratikJanuary 29, 2010 @ 05:58 PM

    @Peter : Emulation is already possible over flash sockets. Check out Akita’s demo application

  6. IsmaelFebruary 09, 2010 @ 01:03 PM

    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.

  7. PratikFebruary 09, 2010 @ 04:19 PM

    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.

  8. IsmaelFebruary 10, 2010 @ 01:43 AM

    @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.

Comment