Кабель действия не может подключиться (не удалось обновить до WebSocket)

У меня возникла проблема с подключением к веб-сокету в средах, не связанных с разработкой, с этими сообщениями журнала.

Failed to upgrade to WebSocket (REQUEST_METHOD: GET, HTTP_CONNECTION: close, HTTP_UPGRADE: )

Finished "/cable/"[non-WebSocket] for 127.0.0.1 at 2016-07-06 09:44:29 +1000

Я немного отладил и понял, что запрос, отправленный браузером/javascript, не совсем совпадает с запросом, полученным единорогом (работающим с nginx).

Заголовок запроса браузера

GET ws://cc-uat.com.au/cable HTTP/1.1
Host: cc-uat.com.au
Connection: Upgrade
Pragma: no-cache
Cache-Control: no-cache
Upgrade: websocket
Origin: http://cc-uat.com.au
Sec-WebSocket-Version: 13
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.87 Safari/537.36
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-GB,en-US;q=0.8,en;q=0.6
Cookie: <Lot of cookies>
Sec-WebSocket-Key: QGdJkYIA2u7vtmMVXfHKtQ==
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
Sec-WebSocket-Protocol: actioncable-v1-json, actioncable-unsupported

Соединение здесь «обновление», но запрос веб-сокета имеет «закрытое» соединение (возможно, nginx его испортил?)

И этот фрагмент кода в драйвере веб-сокета не работает

def self.websocket?(env)
      connection = env['HTTP_CONNECTION'] || ''
      upgrade    = env['HTTP_UPGRADE']    || ''

      env['REQUEST_METHOD'] == 'GET' and
      connection.downcase.split(/ *, */).include?('upgrade') and
      upgrade.downcase == 'websocket'
end

Обновления

Это моя конфигурация nginx

upstream app {
    server unix:/home/osboxes/sites/actioncable-examples/shared/sockets/unicorn.sock fail_timeout=0;
}

server {
    listen 80;
    server_name localhost;

    root /home/osboxes/sites/actioncable-example/public;

    try_files $uri/index.html $uri @app;

    location @app {
        proxy_pass http://app;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_redirect off;
        proxy_http_version 1.1;
     proxy_set_header Upgrade $http_upgrade;
     proxy_set_header Connection "upgrade";
    }


    error_page 500 502 503 504 /500.html;
    client_max_body_size 4G;
    keepalive_timeout 10;
}

Я смонтировал сервер actioncable в /cable

mount ActionCable.server => "/cable"

С изменениями nginx я могу успешно выполнить рукопожатие, но сервер не может отправлять сердечные сокращения, и соединение продолжает разрываться.

Started GET "/cable" for 127.0.0.1 at 2016-07-07 05:48:06 +0100
Started GET "/cable/" [WebSocket] for 127.0.0.1 at 2016-07-07 05:48:06 +0100
Successfully upgraded to WebSocket (REQUEST_METHOD: GET, HTTP_CONNECTION: upgrade, HTTP_UPGRADE: websocket)

person sethi    schedule 05.07.2016    source источник
comment
Какую версию Nginx вы используете? Я думаю, что WebSockets поддерживаются с версии 1.3. Вы установили заголовки Upgrade и Connection как nginx.com/blog/websocket-nginx предлагает?   -  person Juliusz Gonera    schedule 07.07.2016
comment
обновленный вопрос!! @JuliuszGonera   -  person sethi    schedule 07.07.2016
comment
Это работает для меня с Nginx 1.7.12:   -  person Juliusz Gonera    schedule 07.07.2016
comment
Спасибо @JuliuszGonera, моя конфигурация nginx работает ... но все еще не с единорогом, она работает с пумой .. Какая у вас версия единорога?   -  person sethi    schedule 09.07.2016
comment
Подтвердил, что нужно сделать 2 вещи. Как упоминалось в ответе ниже, вам нужно установить config.action_cable.allowed_request_origins. Кроме того, если ваше приложение работает за прокси-сервером nginx, вам необходимо использовать proxy_set_header, как указано @juliuszGonera. См. также nginx.org/en/docs/http/websocket.html.   -  person pinglamb    schedule 29.07.2016
comment
@sethi При использовании Unicorn соединение не обновляется до WebSocket или это другая проблема?   -  person Juliusz Gonera    schedule 12.08.2016
comment
Если у вас все еще есть проблемы с Unicorn (в разработке), это может быть причиной: github.com/rails /rails/issues/26179   -  person Juliusz Gonera    schedule 16.08.2016


Ответы (3)


Вы установили config.action_cable.allowed_request_origins в production.rb, чтобы разрешить подключения из вашего рабочего домена? В моем nginx.conf также есть

proxy_set_header X-Real-IP $remote_addr;  
proxy_set_header X-Forwarded-Proto http;

Я не совсем уверен, действительно ли они необходимы, но это работает для меня.

person Marc Doerflinger    schedule 11.07.2016

Кабель действия Rails 5 CORS:

создайте файл ruby, т. е. action_cable.rb в my_rails_project/config/initializers, и добавьте следующий код.

if Rails.env.development?
  Rails.application.config.action_cable.allowed_request_origins =  ['http://localhost:3001', 'http://127.0.0.1:3001']
end

вы сделали.

person Kaleem Ullah    schedule 09.06.2017

Благодаря ответу выше я получил аналогичную ошибку. Проблема заключалась в том, что я сохранил внутренний URL-адрес в config.action_cable.allowed_request_origins при изменении его на внешний URL-адрес. Проблема была решена. Чтобы быть более ясным, у меня есть font-end, backend в совершенно разных доменах.

person Jose Kj    schedule 14.02.2020