class ActionCable::Connection::Base
For every WebSocket the Action Cable server accepts, a 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.add_tags current_user.name end def disconnect # Any cleanup work needed when the cable connection is cut. end protected def find_verified_user if current_user = User.find_by_identity cookies.signed[:identity_id] current_user else reject_unauthorized_connection end 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?
Attributes
Public Class Methods
# File actioncable/lib/action_cable/connection/base.rb, line 54 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, server.config.client_socket_class) @subscriptions = ActionCable::Connection::Subscriptions.new(self) @message_buffer = ActionCable::Connection::MessageBuffer.new(self) @_internal_subscriptions = nil @started_at = Time.now end
Public Instance Methods
# File actioncable/lib/action_cable/connection/base.rb, line 119 def beat transmit type: ActionCable::INTERNAL[:message_types][:ping], message: Time.now.to_i end
# File actioncable/lib/action_cable/connection/base.rb, line 99 def close websocket.close end
Close the WebSocket connection.
# File actioncable/lib/action_cable/connection/base.rb, line 104 def send_async(method, *arguments) worker_pool.async_invoke(self, method, *arguments) end
Invoke a method on the connection asynchronously through the pool of thread workers.
# File actioncable/lib/action_cable/connection/base.rb, line 110 def statistics { identifier: connection_identifier, started_at: @started_at, subscriptions: subscriptions.identifiers, request_id: @env['action_dispatch.request_id'] } end
Return a basic hash of statistics for the connection keyed with `identifier`, `started_at`, and `subscriptions`. This can be returned by a health check against the connection.
Protected Instance Methods
# File actioncable/lib/action_cable/connection/base.rb, line 149 def cookies request.cookie_jar end
The cookies of the request that initiated the WebSocket connection. Useful for performing authorization checks.
# File actioncable/lib/action_cable/connection/base.rb, line 141 def request @request ||= begin environment = Rails.application.env_config.merge(env) if defined?(Rails.application) && Rails.application ActionDispatch::Request.new(environment || env) end end
The request that initiated the WebSocket connection is available here. This gives access to the environment, cookies, etc.
© 2004–2018 David Heinemeier Hansson
Licensed under the MIT License.