Class: ActionCable::Connection::Base
Relationships & Source Files | |
Super Chains via Extension / Inclusion / Inheritance | |
Class Chain:
|
|
Instance Chain:
|
|
Inherits: | Object |
Defined in: | actioncable/lib/action_cable/connection/base.rb |
Overview
For every WebSocket
connection the Action Cable server accepts, a ::ActionCable::Connection
object will be instantiated. This instance becomes the parent of all of the channel subscriptions that are created from there on. Incoming messages are then routed to these channel subscriptions based on an identifier sent by the Action Cable consumer. The Connection itself does not deal with any specific application logic beyond authentication and authorization.
Here’s a basic example:
module ApplicationCable
class Connection < ActionCable::Connection::Base
identified_by :current_user
def connect
self.current_user = find_verified_user
logger. current_user.name
end
def disconnect
# Any cleanup work needed when the cable connection is cut.
end
private
def find_verified_user
User.find_by_identity( .encrypted[:identity_id]) ||
end
end
end
First, we declare that this connection can be identified by its current_user. This allows us to later be able to find all connections established for that current_user (and potentially disconnect them). You can declare as many identification indexes as you like. Declaring an identification means that an attr_accessor is automatically set for that key.
Second, we rely on the fact that the WebSocket
connection is established with the cookies from the domain being sent along. This makes it easy to use signed cookies that were set when logging in via a web interface to authorize the WebSocket
connection.
Finally, we add a tag to the connection-specific logger with the name of the current user to easily distinguish their messages in the log.
Pretty simple, eh?
Constant Summary
::ActiveSupport::Callbacks
- Included
Identification
- Attributes & Methods
::ActiveSupport::Rescuable
- Attributes & Methods
Class Method Summary
Instance Attribute Summary
- #config readonly
- #env readonly
- #event_loop readonly
- #logger readonly
- #protocol readonly
- #pubsub readonly
- #server readonly
- #subscriptions readonly
- #worker_pool readonly
Callbacks
- Included
Instance Method Summary
- #beat
-
#close(reason: nil, reconnect: true)
Close the
WebSocket
connection. - #handle_channel_command(payload)
-
#send_async(method, *arguments)
Invoke a method on the connection asynchronously through the pool of thread workers.
-
#statistics
Return a basic hash of statistics for the connection keyed with
identifier
,started_at
, #subscriptions, andrequest_id
. -
#cookies
private
The cookies of the request that initiated the
WebSocket
connection. -
#request
private
The request that initiated the
WebSocket
connection is available here.
::ActiveSupport::Rescuable
- Included
#rescue_with_handler | Delegates to the class method, but uses the instance as the subject for rescue_from handlers (method calls, |
::ActiveSupport::Callbacks
- Included
#run_callbacks | Runs the callbacks for the given event. |
Authorization
- Included
#reject_unauthorized_connection | Closes the |
Identification
- Included
#connection_identifier | Return a single connection identifier that combines the value of all the registered identifiers into a single gid. |
Constructor Details
.new(server, env, coder: ActiveSupport::JSON) ⇒ Base
# File 'actioncable/lib/action_cable/connection/base.rb', line 67
def initialize(server, env, coder: ActiveSupport::JSON) @server, @env, @coder = server, env, coder @worker_pool = server.worker_pool @logger = new_tagged_logger @websocket = ActionCable::Connection::WebSocket.new(env, self, event_loop) @subscriptions = ActionCable::Connection::Subscriptions.new(self) @message_buffer = ActionCable::Connection::MessageBuffer.new(self) @_internal_subscriptions = nil @started_at = Time.now end
Class Attribute Details
.identifiers (rw)
[ GitHub ]# File 'actioncable/lib/action_cable/connection/identification.rb', line 11
class_attribute :identifiers, default: Set.new
.identifiers? ⇒ Boolean
(rw)
[ GitHub ]
# File 'actioncable/lib/action_cable/connection/identification.rb', line 11
class_attribute :identifiers, default: Set.new
.rescue_handlers (rw)
[ GitHub ]# File 'activesupport/lib/active_support/rescuable.rb', line 15
class_attribute :rescue_handlers, default: []
.rescue_handlers? ⇒ Boolean
(rw)
[ GitHub ]
# File 'activesupport/lib/active_support/rescuable.rb', line 15
class_attribute :rescue_handlers, default: []
Instance Attribute Details
#config (readonly)
[ GitHub ]# File 'actioncable/lib/action_cable/connection/base.rb', line 65
delegate :event_loop, :pubsub, :config, to: :server
#env (readonly)
[ GitHub ]# File 'actioncable/lib/action_cable/connection/base.rb', line 64
attr_reader :server, :env, :subscriptions, :logger, :worker_pool, :protocol
#event_loop (readonly)
[ GitHub ]#identifiers (rw)
[ GitHub ]# File 'actioncable/lib/action_cable/connection/identification.rb', line 11
class_attribute :identifiers, default: Set.new
#identifiers? ⇒ Boolean
(rw)
[ GitHub ]
# File 'actioncable/lib/action_cable/connection/identification.rb', line 11
class_attribute :identifiers, default: Set.new
#logger (readonly)
[ GitHub ]# File 'actioncable/lib/action_cable/connection/base.rb', line 64
attr_reader :server, :env, :subscriptions, :logger, :worker_pool, :protocol
#protocol (readonly)
[ GitHub ]# File 'actioncable/lib/action_cable/connection/base.rb', line 64
attr_reader :server, :env, :subscriptions, :logger, :worker_pool, :protocol
#pubsub (readonly)
[ GitHub ]# File 'actioncable/lib/action_cable/connection/base.rb', line 65
delegate :event_loop, :pubsub, :config, to: :server
#rescue_handlers (rw)
[ GitHub ]# File 'activesupport/lib/active_support/rescuable.rb', line 15
class_attribute :rescue_handlers, default: []
#rescue_handlers? ⇒ Boolean
(rw)
[ GitHub ]
# File 'activesupport/lib/active_support/rescuable.rb', line 15
class_attribute :rescue_handlers, default: []
#server (readonly)
[ GitHub ]# File 'actioncable/lib/action_cable/connection/base.rb', line 64
attr_reader :server, :env, :subscriptions, :logger, :worker_pool, :protocol
#subscriptions (readonly)
[ GitHub ]# File 'actioncable/lib/action_cable/connection/base.rb', line 64
attr_reader :server, :env, :subscriptions, :logger, :worker_pool, :protocol
#worker_pool (readonly)
[ GitHub ]# File 'actioncable/lib/action_cable/connection/base.rb', line 64
attr_reader :server, :env, :subscriptions, :logger, :worker_pool, :protocol
Instance Method Details
#beat
[ GitHub ]# File 'actioncable/lib/action_cable/connection/base.rb', line 147
def beat transmit type: ActionCable::INTERNAL[: ][:ping], message: Time.now.to_i end
#close(reason: nil, reconnect: true)
Close the WebSocket
connection.
# File 'actioncable/lib/action_cable/connection/base.rb', line 120
def close(reason: nil, reconnect: true) transmit( type: ActionCable::INTERNAL[: ][:disconnect], reason: reason, reconnect: reconnect ) websocket.close end
#cookies (private)
The cookies of the request that initiated the WebSocket
connection. Useful for performing authorization checks.
# File 'actioncable/lib/action_cable/connection/base.rb', line 187
def # :doc: request. end
#handle_channel_command(payload)
[ GitHub ]# File 'actioncable/lib/action_cable/connection/base.rb', line 109
def handle_channel_command(payload) run_callbacks :command do subscriptions.execute_command payload end end
#request (private)
The request that initiated the WebSocket
connection is available here. This gives access to the environment, cookies, etc.
# File 'actioncable/lib/action_cable/connection/base.rb', line 178
def request # :doc: @request ||= begin environment = Rails.application.env_config.merge(env) if defined?(Rails.application) && Rails.application ActionDispatch::Request.new(environment || env) end end
#send_async(method, *arguments)
Invoke a method on the connection asynchronously through the pool of thread workers.
# File 'actioncable/lib/action_cable/connection/base.rb', line 131
def send_async(method, *arguments) worker_pool.async_invoke(self, method, *arguments) end
#statistics
Return a basic hash of statistics for the connection keyed with identifier
, started_at
, #subscriptions, and request_id
. This can be returned by a health check against the connection.
# File 'actioncable/lib/action_cable/connection/base.rb', line 138
def statistics { identifier: connection_identifier, started_at: @started_at, subscriptions: subscriptions.identifiers, request_id: @env["action_dispatch.request_id"] } end