问题
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