lib/jugglite/app.rb in jugglite-0.4.0 vs lib/jugglite/app.rb in jugglite-0.5.0
- old
+ new
@@ -9,12 +9,16 @@
'Content-Type' => 'text/event-stream;charset=utf-8',
'Cache-Control' => 'no-cache' # IE (through the Polyfill) will trip without this
}
# Options include:
- # +path+ : the URI path to listen to ('/stream')
- # +keepalive_timeout+ : the timeout in seconds between keepalive comments
+ # +path+ : the URI path to listen to (defaults to '/stream')
+ # +keepalive_timeout+ : the timeout in seconds between keepalive comments (defaults to 20)
+ # +namespace+ : a namespace used as prefix for redis pubsub channels
+ # +allowed_channels+ :
+ # * an array with allowed channel names
+ # * a proc that takes a Rack::Request and returns an array of allowed channels for that particular request
def initialize(app = nil, options = {})
@app = app
@options = {
path: '/stream',
namespace: '',
@@ -49,11 +53,11 @@
end
connection.callback { unregister_connection(connection) }
connection.errback { unregister_connection(connection) }
- # Needed for crappy Rack::Lint
+ # Needed for Rack::Lint
throw :async
# Returning a status of -1 keeps the connection open
# You need to use env['async.callback'].call to send the status, headers & body later
AsyncResponse
@@ -75,13 +79,22 @@
end
end
end
def channels_for_request(request)
- # TODO: Sanitize? Check signature?
channels = Array(request.params["channel"].split(","))
+ # Sanitize channels
+ channels = channels & allowed_channels(request) if @options[:allowed_channels]
channels.map! { |channel| @options[:namespace] + channel }
Set.new(channels)
+ end
+
+ def allowed_channels(request)
+ case @options[:allowed_channels]
+ when Proc then @options[:allowed_channels].call(request)
+ when Array then @options[:allowed_channels]
+ else raise(ArgumentError, ":allowed_channels should be nil, Array or a Proc")
+ end
end
def register_connection(connection)
requested_channels = channels_for_request(connection.request)
subscribe_to_new_channels(requested_channels - @redis_channels)