#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.rb2. Вы забыли включить
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`);
Если вы столкнулись с проблемами рукопожатия, существует несколько решений:
-
Проверьте, совместимо ли ваше интерфейсное приложение с
protocol 07
или новее. -
Проверьте, находится ли ваш веб-сайт в
config.action_cable.allowed_request_origins
-
Добавьте
config.web_socket_server_url = 'ws://backend.dev/cable'
в свой файл ENV cofig. -
Вы можете использовать быстрый «грязный» взлом. Просто добавьте следующее в свой файл ENV cofig:
config.action_cable.disable_request_forgery_protection = true