Подключение 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?


person matt    schedule 23.10.2016    source источник
comment
Что у вас в config/routes.rb? Где вы монтируете ActionCable (/cable?) Возможно, вам просто нужно добавить точку монтирования к вашему вызову service.createConsumer — вы ищете что-то вроде mount ActionCable.server => '/cable' в route.rb   -  person Undo    schedule 26.10.2016
comment
Вы забыли включить contentSecurityPolicy в config/environment.js для атрибута connect-src вот так 'connect-src': "'self' ws://backend.dev/ backend.dev",   -  person Ember Freak    schedule 26.10.2016
comment
спасибо @Undo и @kumkanillam - я монтирую сервер ActionCable с помощью mount ActionCable.server => '/cable' - запросы к backend.dev возвращают неожиданную ошибку ответа 200, а запросы к backend.dev/cable просто выдают 404. У меня также есть настройка конфигурации connect-src, аналогичная комментарию выше.   -  person matt    schedule 26.10.2016


Ответы (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.

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

    config.action_cable.disable_request_forgery_protection = true
    
person Viktor    schedule 27.10.2016