class Middleware
Rack middleware that intercepts WebSocket upgrade requests and dispatches them to ActionCable, passing all other requests to the next app in the middleware stack.
Definitions
def initialize(app, path: "/cable", server: ActionCable.server)
Create a new middleware instance.
Signature
-
parameter
app#call The next Rack application in the middleware stack.
-
parameter
pathString The URL path that the cable endpoint is mounted at.
-
parameter
serverActionCable::Server::Base The ActionCable server to use.
Implementation
def initialize(app, path: "/cable", server: ActionCable.server)
@app = app
@path = path
@server = server
@coder = ActiveSupport::JSON
@protocols = ::ActionCable::INTERNAL[:protocols]
end
def valid_path?(env)
Check whether the request path matches the configured cable path.
Signature
-
parameter
envHash The Rack environment.
-
returns
Boolean Whether the request is for the cable endpoint.
Implementation
def valid_path?(env)
env["PATH_INFO"] == @path
end
def call(env)
Handle an incoming Rack request. WebSocket upgrade requests on the configured path are handed off to ActionCable; all other requests are forwarded to the next app in the middleware stack.
Signature
-
parameter
envHash The Rack environment.
-
returns
Array A Rack response triple.
Implementation
def call(env)
if valid_path?(env) and Async::WebSocket::Adapters::Rack.websocket?(env) and allow_request_origin?(env)
Async::WebSocket::Adapters::Rack.open(env, protocols: @protocols) do |websocket|
handle_incoming_websocket(env, websocket)
end
else
@app.call(env)
end
end
def allow_request_origin?(env)
TODO: Shouldn't this be moved to ActionCable::Server::Base?
Implementation
def allow_request_origin?(env)
if @server.config.disable_request_forgery_protection
return true
end
proto = ::Rack::Request.new(env).ssl? ? "https" : "http"
if @server.config.allow_same_origin_as_host && env["HTTP_ORIGIN"] == "#{proto}://#{env["HTTP_HOST"]}"
return true
elsif Array(@server.config.allowed_request_origins).any?{|allowed_origin| allowed_origin === env["HTTP_ORIGIN"]}
return true
end
Console.warn(self, "Request origin not allowed!", origin: env["HTTP_ORIGIN"])
return false
end