padrino-framework
padrino-framework copied to clipboard
Padrino websockets
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
I personally like how sinatra-websockets implements it. I think it should be compatible, haven't tried it.
@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?
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?