Async::CableSourceAsyncCableMiddleware

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 path String

The URL path that the cable endpoint is mounted at.

parameter server ActionCable::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 env Hash

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 env Hash

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