Подключение ActionCable к другому хосту

#ruby-on-rails #ember.js #actioncable

#ruby-on-rails #ember.js #actioncable

Вопрос:

Я использую приложение rails 5 в качестве внутреннего сервера и приложение ember для интерфейсного приложения. Это два отдельных приложения, размещенных в двух разных доменах — скажем, backend.dev и frontend.dev

Приложение rails имеет простой класс подключения, найденный по адресу app/channels/application_cable/connection.rb , который выглядит следующим образом:

 module ApplicationCable
  class Connection < ActionCable::Connection::Base
    def connect
      Rails.logger.debug("env: #{env.inspect}")
      Rails.logger.info("cookies.signed: #{cookies.signed.inspect}")
    end
  end
end
  

У меня есть простой базовый класс канала в app/channels/application_cable/channel.rb со следующим:

 module ApplicationCable
  class Channel < ActionCable::Channel::Base
  end
end
  

И единственная реализация этого класса в app/channels/events_channel.rb :

 class EventsChannel < ApplicationCable::Channel
  def subscribed
    Rails.logger.debug("env: #{env.inspect}")
    Rails.logger.info("cookies.signed: #{cookies.signed.inspect}")
    stream_from 'events'
  end
end
  

Что касается ember, я использую пакет ember-cable. Я настроил своего потребителя в своем интерфейсе, расширив класс контроллера следующим:

 cableService: Ember.inject.service('cable'),

setupConsumer: Ember.on('init', function() {
  let service = this.get('cableService');
  let consumer = service.createConsumer(`ws://backend.dev`);
  let channel = 'EventsChannel';

  consumer.subscriptions.create(channel, {
    disconnected() {
      Ember.debug(`${channel}#disconnected`);
    },

    connected() {
      Ember.debug(`${channel}#connected`);
    },
  

Я вполне уверен, что мой потребитель настроен правильно, поскольку я вижу некоторые выходные данные отладки, когда я получаю следующий вывод на свою консоль js:

 DEBUG: EventsChannel#disconnected
  

Однако я также вижу странную ошибку в консоли:

 WebSocket connection to 'ws://backend.dev/' failed: Error during WebSocket handshake: Unexpected response code: 200
  

Я не уверен, что делать с ошибкой кода ответа здесь, и в моем приложении rails абсолютно ничего не регистрируется. Есть ли что-нибудь дополнительное, что мне нужно настроить, чтобы actioncable работал в разных доменах? Есть идеи о том, что здесь означает код ответа 200?

Комментарии:

1. Что в вашем config / routes.rb? Где вы монтируете ActionCable ( /cable ?) Возможно, вам просто нужно добавить свою точку монтирования к вашему service.createConsumer вызову — вы ищете что-то подобное mount ActionCable.server => '/cable' в routes.rb

2. Вы забыли включить contentSecurityPolicy в config/environment.js для connect-src атрибута, подобного этому 'connect-src': "'self' ws://backend.dev/ backend.dev",

3. спасибо @Undo и @kumkanillam — я монтирую сервер ActionCable, используя mount ActionCable.server => '/cable' запросы, чтобы backend.dev вернуть ошибку «неожиданный ответ 200», в то время как запросы backend.dev/cable выдают только 404 секунды. У меня также есть connect-src настройка конфигурации, аналогичная комментарию выше.

Ответ №1:

Попробуйте это:

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

Затем в вашем приложении:

 let consumer = service.createConsumer(`ws://backend.dev/cable`);
  

Если вы столкнулись с проблемами рукопожатия, существует несколько решений:

  1. Проверьте, совместимо ли ваше интерфейсное приложение с protocol 07 или новее.

  2. Проверьте, находится ли ваш веб-сайт в config.action_cable.allowed_request_origins

  3. Добавьте config.web_socket_server_url = 'ws://backend.dev/cable' в свой файл ENV cofig.

  4. Вы можете использовать быстрый «грязный» взлом. Просто добавьте следующее в свой файл ENV cofig:

     config.action_cable.disable_request_forgery_protection = true