класс ActionCable::Connection::Base
Для каждого WebSocket-соединения, принимаемого сервером Action Cable, будет создан объект Connection. Этот экземпляр становится родителем всех подписок на каналы, которые создаются далее. Входящие сообщения затем маршрутизируются к этим подпискам на каналы на основе идентификатора, отправленного потребителем Action Cable. Сам Connection не обрабатывает никакой специфической логики приложения, за исключением аутентификации и авторизации.
Вот пример:
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
private
def find_verified_user
User.find_by_identity(cookies.encrypted[:identity_id]) ||
reject_unauthorized_connection
end
end
end
Во-первых, мы объявляем, что это соединение может быть идентифицировано по текущему пользователю. Это позволяет нам впоследствии найти все соединения, установленные для этого текущего пользователя (и, возможно, отключить их). Вы можете объявлять любое количество индексов идентификации. Объявление идентификации означает, что для этого ключа автоматически устанавливается attr_accessor.
Во-вторых, мы полагаемся на то, что соединение WebSocket устанавливается с кукисами домена, отправленными вместе. Это упрощает использование подписанных кукисов, которые были установлены при входе в систему через веб-интерфейс, для авторизации WebSocket-соединения.
Наконец, мы добавляем метку в журнале, специфичном для соединения, с именем текущего пользователя, чтобы легко различать их сообщения в журнале.
Довольно просто, не так ли?
Атрибуты
Публичные методы класса
# File actioncable/lib/action_cable/connection/base.rb, line 55 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
Публичные методы экземпляра
# File actioncable/lib/action_cable/connection/base.rb, line 125 def beat transmit type: ActionCable::INTERNAL[:message_types][:ping], message: Time.now.to_i end
# File actioncable/lib/action_cable/connection/base.rb, line 100
def close(reason: nil, reconnect: true)
transmit(
type: ActionCable::INTERNAL[:message_types][:disconnect],
reason: reason,
reconnect: reconnect
)
websocket.close
end Закрыть WebSocket-соединение.
# File actioncable/lib/action_cable/connection/base.rb, line 110 def send_async(method, *arguments) worker_pool.async_invoke(self, method, *arguments) end
Вызвать метод на соединении асинхронно через пул потоковых рабочих процессов.
# File actioncable/lib/action_cable/connection/base.rb, line 116
def statistics
{
identifier: connection_identifier,
started_at: @started_at,
subscriptions: subscriptions.identifiers,
request_id: @env["action_dispatch.request_id"]
}
end Возвращает базовый хеш статистики соединения, ключи которого identifier, started_at, subscriptions, и request_id. Это может быть возвращено в результате проверки работоспособности соединения.
Приватные методы экземпляра
# File actioncable/lib/action_cable/connection/base.rb, line 159 def cookies # :doc: request.cookie_jar end
Куки запроса, который инициировал WebSocket-соединение. Полезно для выполнения проверок авторизации.
# File actioncable/lib/action_cable/connection/base.rb, line 151
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 Здесь доступен запрос, который инициировал WebSocket-соединение. Это дает доступ к среде, кукисам и т. д.
© 2004–2020 David Heinemeier Hansson
Licensed under the MIT License.