Possible to mount multiple ActionCable cables?

人盡茶涼 提交于 2019-12-23 18:20:55

问题


Is it possible to mount multiple ActionCable cables in the same Rails application? For example as such:

#routes.rb
Rails.application.routes.draw do
  ...
  mount ActionCable.server => '/cable'
  mount ActionCable.server => '/cable2'
end

I am aware I can have multiple channels using the same cable, but I require to use different authentication methods for my channels. From my understanding, this is not possible using the same cable.

Thanks for your help.


回答1:


As elaborated in Using ActionCable with multiple identification methods, one approach to use different authentication methods in the same Rails app can be:

# app/channels/application_cable/connection.rb

module ApplicationCable
  class Connection < ActionCable::Connection::Base
    identified_by :current_user, :uuid

    def connect
      self.uuid = SecureRandom.urlsafe_base64
      if env['warden'].user
        self.current_user = find_verified_user
      end
    end

    protected

    def find_verified_user
      return User.find_by(id: cookies.signed['user.id'])
    end
  end
end

Authenticated channel:

class AuthenticatedChannel < ApplicationCable::Channel
  def subscribed
    reject and return if current_user.blank?
    stream_for current_user
  end
  ...

Anonymous channel:

class AnonymousChannel < ApplicationCable::Channel
  def subscribed
    stream_from "channel_#{self.uuid}"
  end
  ...



回答2:


No it's not possible out-of-the-box because you can configure only one server in Rails.

In the config/environments/development.rb file (or what ever else environnement) you have only one action_cable configuration point :

  # Mount Action Cable outside main process or domain
  config.action_cable.mount_path = nil
  config.action_cable.url = 'wss://example.com/cable'
  config.action_cable.allowed_request_origins = [ 'http://example.com', /http:\/\/example.*/ ]

Also in your layout file you can have only one action_cable_meta_tag :

<!DOCTYPE html>
<html>
  <head>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    ...

    <%= action_cable_meta_tag %>
  </head>
  <body>
    ...
  </body>
</html>

In order to have many cable servers, you would have to be able to configure many of them like within a Hash like that:

  # Mount Action Cable outside main process or domain
  config.action_cable = [
    {
       mount_path: nil
       url: 'wss://example.com/cable'
       allowed_request_origins: [ 'http://example.com', /http:\/\/example.*/ ]
    },
    {
       mount_path: nil
       url: 'wss://example.com/cable2'
       allowed_request_origins: [ 'http://example.com', /http:\/\/example.*/ ]
    }
  ]

And be able to set them with a action_cable_meta_tags (notice the plural version) helper.

But

But Rails allows you to run your server is standalone mode, that what we are doing at my company.

So we are running a cable server with puma/unicorn and then we aren't using the action_cable_meta_tag tag, but we are forcing the URL to the ActionCable.createConsumer :

  const cable = ActionCable.createConsumer('wss://cable1.domain.co/cable')
  const channel = cable.subscriptions.create(...)

Knowing that, you can run many cable servers on many hosts or ports, and then create many ActionCable.createConsumer instances for each servers.

That way you have many cable servers.

I hope this would help anyone looking for running many cable servers.



来源:https://stackoverflow.com/questions/46793361/possible-to-mount-multiple-actioncable-cables

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!