padrino-framework icon indicating copy to clipboard operation
padrino-framework copied to clipboard

Padrino websockets

Open dariocravero opened this issue 10 years ago • 3 comments

Hey @padrino/core-members,

How're things?

Many people have been asking us about WebSockets support in Padrino and even though it's not up fully up to us, I think that we should make it easier and consistent for our users to implement those. After all, streamed communications are a crucial building block of the web :).

That's why I've just open sourced padrino-websockets an agnostic WS implementation for Padrino. Tons of thanks to @stakach for the amazing base and for doing SpiderGazelle a rack web server based on libuv which looks very promissing (highly recommended)!

It will let us do stuff like:

websocket :channel do
  event :test do |context, message|
    "test on channel"
    send_message message
  end
end

websocket :another_channel, map: '/blah' do
  event :test do |context, message|
    "test on channel"
    broadcast message
  end
end

At the moment it only supports SpiderGazelle as its backend but stuff like faye-websocket-ruby should be simple enough to be integrated, giving us support for Goliath, Phusion Passenger >= 4.0 with nginx >= 1.4, Puma >= 2.0, Rainbows and Thin (from its README).

I haven't released it as a gem it might make sense to include it in core and I'd like your advise and thoughts on it.

Cheers! Darío

dariocravero avatar Jan 28 '14 14:01 dariocravero

I personally like how sinatra-websockets implements it. I think it should be compatible, haven't tried it.

Ortuna avatar Feb 01 '14 20:02 Ortuna

@Ortuna it is simple to build an app that works like sinatra-websockets. Padrino-websockets deals with message parsing, abstracts the web servers implementation details from the handler code and provides a nice DSL.

To achieve a sinatra-websockets style app on spider-gazelle without using padrino-websockets you'd write: (this is the sinatra-websockets example modified for spider-gazelle)

get '/' do
    if !request.env['rack.hijack']
        render :index
    else
        request.env['rack.hijack'].call.then do |hijacked|
            ws = ::SpiderGazelle::Websocket.new hijacked.socket, hijacked.env
            ws.on_open do
                ws.text("Hello World!")
                settings.sockets << ws
            end
            ws.progress do |msg|
                ws.loop.next_tick { settings.sockets.each{|s| s.text(msg) } }
            end
            ws.finally do
                warn("websocket closed")
                settings.sockets.delete(ws)
            end
            ws.start
        end
    end
end

I guess what you are after is a raw websocket without any of the message parsing?

stakach avatar Feb 01 '14 22:02 stakach

Hi @Ortuna, thanks for your comment.

This is actually a bit higher on the stack, as @stakach says, it's a DSL that acts as a common interface to multiple WebSockets implementations easily allowing you to define channels and handle users and messages on them.

sinatra-websockets could be added as a backend in the same way SpiderGazelle is implemented now.

What do you think about that?

dariocravero avatar Feb 03 '14 19:02 dariocravero