Всем, кто следует, надеюсь, это поможет.
На момент написания этой статьи (октябрь 2018 г.), похоже, что вы вообще не можете использовать ActionCable за Cloudfront.CF откажется от заголовка обновления, что предотвратит установление безопасного сокета.
Наша установка была CF -> Application Load Balancer (ALB) -> EC2.Что касается AWS, мы начали с создания поддоменов (socket.example.com
), которые указывали бы прямо на тот же ALB и полностью обходили CF.Обратите внимание, что классические балансировщики нагрузки абсолютно не будут работать.Вы можете использовать только ALB.
Это само по себе не решило проблему.В вашей конфигурации Rails вы должны добавить следующие строки в production.rb
:
config.action_cable.url = 'wss://socket.example.com:28080/cable'
config.action_cable.allowed_request_origins = ['https://example.com'] # Not the subdomain
Возможно, вам также потребуется обновить CSP, включив wss://socket.example.com/cable
для connect_src
.
Если в этот момент вы получаете сообщение о невозможности обновления, вам необходимо убедиться, что ваша конфигурация NGINX верна. Этот ответ может помочь .
Вам также необходимо отразить это изменение в вашем cable.js
.Этот следующий фрагмент работает для меня как с локальной разработкой, так и с производством, но вам, возможно, придется изменить его.Я написал это с пред-ES6, потому что этот файл никогда не попадал в Babel в нашей конфигурации.
(function() {
this.App || (this.App = {})
var wsUrl
if(location.host.indexOf('localhost') != -1) {
wsUrl = '/cable'
} else {
var host = location.host
var protocol = location.protocol
wsUrl = protocol + '//socket.' + host + '/cable'
}
App.cable = ActionCable.createConsumer(wsUrl)
}).call(this)
Это может быть все, что вам нужно, в зависимости от вашей схемы аутентификации.Тем не менее, я использовал файлы cookie, общие для основного приложения и ActionCable, и это вызвало сложную ошибку.Казалось бы, соединение установлено правильно, но на самом деле произойдет сбой, и ActionCable будет повторять каждые 10 секунд.Последний шаг состоял в том, чтобы гарантировать, что устанавливаемые файлы cookie авторизации будут работать через поддомен сокета.Я обновил свой файл cookie следующим образом:
cookies.signed[:cookie_name] = {
value: payload,
domain: ['.socket.example.com', '.example.com']
# Some people have to specify tld_length, but I was fine without it
}