12

我正在尝试使用 rails 5.0.0beta3 和 websockets 运行应用程序。我的一切都在本地进行开发,但在生产中,我在浏览器的控制台中得到了这个响应:

“WebSocket 连接失败:WebSocket 握手期间出错:意外响应 301”

这是我的 nginx 配置文件。

upstream app {
  server unix:/home/dev/workspace/my_app/tmp/sockets/thin.0.sock max_fails=1 fail_timeout=15s;
  server unix:/home/dev/workspace/my_app/tmp/sockets/thin.1.sock max_fails=1 fail_timeout=15s;
}

server {
  listen 443 ssl;
  server_name www.my_app.co;

  root /home/dev/workspace/my_app/public;
  try_files $uri/index.html $uri @app;

  location @app {
    proxy_next_upstream error timeout http_502 http_503;
    proxy_read_timeout 60s;

    proxy_pass http://app;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_set_header X-FORWARDED-PROTO $scheme;
    proxy_redirect off;
  }

  location /websocket/ {
    proxy_pass http://localhost:28080/;
    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;

  ssl on;
  ssl_certificate /ssl/www.my_app.co.crt;
  ssl_certificate_key /ssl/www.my_app.co.key;

  ssl_session_timeout 5m;

  ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
  ssl_ciphers "HIGH:!aNULL:!MD5 or HIGH:!aNULL:!MD5:!3DES";
  ssl_prefer_server_ciphers on;
}

我正在为我的应用服务器运行瘦身,并在本地运行 websockets 服务器和 redis 的 puma。我正在尝试在此处遵循动作电缆示例应用程序:https ://github.com/rails/actioncable-examples 。

我正在像这样启动我的 puma 服务器:bundle exec puma -p 28080 cable/config.ru

有了puma.rb这个config

workers 1
threads 1, 10

app_dir = File.expand_path("../..", __FILE__)
shared_dir = "#{app_dir}/shared"

rails_env = ENV['RAILS_ENV'] || "production"
environment rails_env

stdout_redirect "#{shared_dir}/log/puma.stdout.log", "#{shared_dir}/log/puma.stderr.log", true

pidfile "#{shared_dir}/pids/puma.pid"
state_path "#{shared_dir}/pids/puma.state"

这是我的production.rb配置的相关部分:

config.action_cable.allowed_request_origins = ['https://www.chatben.co', 'https://45.55.192.195']
config.action_cable.url = "wss://www.chatben.co/websocket"
config.force_ssl = false

这是我的development.rb配置:

config.action_cable.url = "ws://localhost:28080"
config.action_cable.allowed_request_origins = ['http://localhost:3000']
config.action_cable.disable_request_forgery_protection = true

在我的应用程序中,我像这样启动电缆:

@App = {}
App.cable = ActionCable.createConsumer()

任何建议都会很棒。我注意到这里有人:RoR 5.0.0 ActionCable wss WebSocket 握手:意外的响应代码:301 能够通过使用单独的域来解决这个问题。这就是我接下来可能会尝试的,但我希望它不会变成那样。

提前感谢您的帮助!对此,我真的非常感激。

4

4 回答 4

36

问题很可能是 Rails 强制您连接到 ssl。由于 nginx 终止了 ssl 连接,因此您需要设置X-Forwarded-Proto标头让 Rails 知道一切正常。这是一个适合我的完整配置:

  location /cable {
    proxy_pass http://app;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "Upgrade";

    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-Proto https;
    proxy_redirect off;
  }
于 2016-03-14T08:50:09.687 回答
1

我基本上更新了我的答案,这对我来说很容易,我之前无法意识到。在 nginx conf 文件中以正常方式配置 SSL 后,我只是在我的 production.rb 文件中执行此操作。

config.action_cable.allowed_request_origins = [#domains]

它只是做了所有事情并正确连接。

于 2017-04-09T11:46:41.650 回答
1

我无法弄清楚我之前的问题,所以我最终改为与乘客一起部署。我仍然想知道为什么每个请求都有一个 301,但是,嘿,至少我现在有 websockets 在生产中!

编辑:在阅读了上面 troelskn 的回答后,我能够部署 Puma 服务器而不需要Passenger。

于 2016-03-14T02:07:34.697 回答
0

对于 websocket-rails,我必须在 NGINX 中执行此操作:

location /websocket{
    proxy_pass http://localhost:3001/websocket;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "Upgrade";    
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-Proto https;
    proxy_redirect off;
  }

并在 javascript 上传递 false 以使用 http:// 而不是 ws://

var websocket = new WebSocketRails(window.location.hostname + '/websocket', false);
于 2016-07-12T21:08:55.087 回答