简体   繁体   English

ActionCable - WebSocket 握手期间出错:意外响应代码:404

[英]ActionCable - Error during WebSocket handshake: Unexpected response code: 404

Have deployed my Rails 5.2 app via Capistrano, and am having problems with ActionCable.已通过 Capistrano 部署了我的 Rails 5.2 应用程序,但 ActionCable 出现问题。 I am using Nginx, Puma and Lets Encrypt.我正在使用 Nginx、Puma 和 Lets Encrypt。

I have tried many combinations of configuration, but each time am receiving the same error.我尝试了许多配置组合,但每次都收到相同的错误。 I am not sure how to debug this issue, and suggestions as well and any tips on re-arranging my ngnx.conf would be well-appreciated.我不确定如何调试此问题,以及有关重新安排我的 ngnx.conf 的建议以及任何提示都将受到好评。

Have changed the real website to website.com已经把真实网站改成website.com

nginx.conf nginx.conf

upstream puma {
  server unix:///home/deploy/apps/website/shared/tmp/sockets/website-puma.sock;
}

server {
  server_name website.com www.website.com;
  root /home/deploy/apps/website/current/public;
  index index.html;

  location ^~ /assets/ {
    gzip_static on;
    expires max;
    add_header Cache-Control public;
  }

  try_files $uri/index.html $uri @puma;
  location @puma {
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_redirect off;
    proxy_pass http://puma;
  }

  location /cable {
    proxy_pass http://puma;
    proxy_http_version 1.1;
    proxy_set_header Upgrade websocket;
    proxy_set_header Connection Upgrade;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  }

  error_page 500 502 503 504 /500.html;
  client_max_body_size 10M;
  keepalive_timeout 10;

    listen [::]:443 ssl ipv6only=on; # managed by Certbot
    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/website.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/website.com/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}

server {
    if ($host = www.website.com) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


    if ($host = website.com) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


  listen 80 default_server;
  listen [::]:80 default_server ipv6only=on;

  server_name website.com www.website.com;
    return 404; # managed by Certbot
}

config/production.rb配置/生产.rb

  config.action_cable.mount_path = '/cable'
  config.action_cable.url = 'wss://website.com/cable'
  config.action_cable.allowed_request_origins = [ 'https://website.com', 'http://website.com' ]

Error Message错误信息

在此处输入图像描述

Reviewed posts已审核的帖子

UPDATE更新

Updated nginx.conf更新了 nginx.conf

upstream puma {
  server unix:///home/deploy/apps/immersive/shared/tmp/sockets/immersive-puma.sock;
}


  server {
    if ($host = www.immersive.ch) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


    if ($host = immersive.ch) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


    listen 80 default_server;
    listen [::]:80 default_server ipv6only=on;

    server_name immersive.ch www.immersive.ch;
    return 404; # managed by Certbot
  }

  server {
    server_name immersive.ch www.immersive.ch;
    root /home/deploy/apps/immersive/current/public;
    index index.html;

    location ^~ /assets/ {
      gzip_static on;
      expires max;
      add_header Cache-Control public;
    }

    try_files $uri/index.html $uri @puma;
    location @puma {
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header Host $http_host;
      proxy_redirect off;
      proxy_pass http://puma;
    }

    location /cable {
      proxy_pass http://puma;
      proxy_http_version 1.1;
      proxy_set_header Upgrade $http_upgrade;
      proxy_set_header Connection "upgrade";
      proxy_set_header Host $host;
      proxy_set_header X-Forwarded-Proto $scheme;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_pass_request_headers on;

      proxy_buffering off;
      proxy_redirect off;
      break;
    }

    error_page 500 502 503 504 /500.html;
    client_max_body_size 10M;
    keepalive_timeout 10;

    listen [::]:443 ssl ipv6only=on; # managed by Certbot
    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/immersive.ch/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/immersive.ch/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
  }

production.rb生产.rb

config.action_cable.mount_path = '/cable'
config.action_cable.url = 'wss://immersive.ch/cable'
config.action_cable.allow_same_origin_as_host = true
config.action_cable.allowed_request_origins = [ '*' ]
#config.action_cable.allowed_request_origins = [ 'https://immersive.ch', 'http://immersive.ch' ]

Partial output of curl curl 的部分 output

> GET /cable HTTP/1.1
> Host: immersive.ch
> User-Agent: curl/7.54.0
> Accept: */*
> Origin: https://immersive.ch
> Sec-WebSocket-Key: MIN4DsiwEAutsE11kgG5rg==
> Upgrade: websocket
> Connection: Upgrade
> Sec-WebSocket-Version: 13
>
< HTTP/1.1 404 Not Found
< Server: nginx/1.15.5 (Ubuntu)
< Date: Tue, 16 Apr 2019 20:10:43 GMT
< Content-Type: text/plain
< Transfer-Encoding: chunked
< Connection: keep-alive
< Cache-Control: no-cache
< X-Request-Id: 7a9aa8f1-676d-419b-9e4f-0c1bb38bcaa2
< X-Runtime: 0.004730
<
* Connection #0 to host immersive.ch left intact
Page not found%

puma.rb puma.rb

threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 }.to_i
threads threads_count, threads_count
port        ENV.fetch("PORT") { 3000 }
environment ENV.fetch("RAILS_ENV") { "development" }
workers 2
daemonize true
plugin :tmp_restart

EDIT 2编辑 2

/var/logs/nginx/access.log /var/logs/nginx/access.log

HTTP/1.1" 200 4447 "https://immersive.ch/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36"
xxx.xxx.xxx.xxx - - [16/Apr/2019:22:33:58 +0200] "GET /cable HTTP/1.1" 404 24 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36"
xxx.xxx.xxx.xxx - - [16/Apr/2019:22:33:59 +0200] "GET /cable HTTP/1.1" 404 24 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36"

puma.error.log puma.error.log

I, [2019-04-16T22:39:06.100106 #21136]  INFO -- : [80dc2a43-13e1-499e-a8f6-9fd54d48270b] Started GET "/cable" for xxx.xxx.xxx.xxx at 2019-04-16 22:39:06 +0200
I, [2019-04-16T22:39:06.103811 #21136]  INFO -- : [80dc2a43-13e1-499e-a8f6-9fd54d48270b] Started GET "/cable/"[non-WebSocket] for xxx.xxx.xxx.xxx at 2019-04-16 22:39
E, [2019-04-16T22:39:06.103943 #21136] ERROR -- : [80dc2a43-13e1-499e-a8f6-9fd54d48270b] Failed to upgrade to WebSocket (REQUEST_METHOD: GET, HTTP_CONNECTION: close, HTTP_UPGRADE: )
I, [2019-04-16T22:39:06.104062 #21136]  INFO -- : [80dc2a43-13e1-499e-a8f6-9fd54d48270b] Finished "/cable/"[non-WebSocket] for xxx.xxx.xxx.xxx at 2019-04-16 22:39

puma.access.log puma.access.log

2019-04-16 20:58: HTTP parse error, malformed request (127.0.0.1): #<Puma::HttpParserError: Invalid HTTP format, parsing fails.>

ActionCable answers 404 when Origin header is missing or does not match/invalid.Origin标头丢失或不匹配/无效时,ActionCable 会回答 404。

Check that it's not you regular 404:检查这不是您的常规 404:

curl -v 'https://your_site.com/cable' -H 'Origin: https://your_site.com' -H 'Sec-WebSocket-Key: MIN4DsiwEAutsE11kgG5rg=='  -H 'Upgrade: websocket' -H 'Connection: Upgrade' -H 'Sec-WebSocket-Version: 13'

When everything is fine there'll be HTTP/1.1 101 Switching Protocols , on origin mismatch - just Page not found body, or your regular 404 page if there's some other routing trouble.当一切正常时,会出现HTTP/1.1 101 Switching Protocols ,来源不匹配 - 只是Page not found正文,或者您的常规 404 页面(如果有其他路由问题)。

Make sure allowed_request_origins in settings is correct.确保设置中的allowed_request_origins正确。 Note that it includes port, if it's non-standard.请注意,它包括端口,如果它是非标准的。 Check which Origin browser sends in devtools检查哪个Origin浏览器在 devtools 中发送

Also there's config.action_cable.allow_same_origin_as_host = true (the default, needs correct Host and X-Forwarded-Proto headers)还有config.action_cable.allow_same_origin_as_host = true (默认情况下,需要正确的HostX-Forwarded-Proto标头)

Then we need nginx to pass all the headers that are being used to reconstruct origin:然后我们需要 nginx 传递所有用于重建原点的标头:

  location /cable {
    proxy_pass http://puma;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-Proto $scheme; # <- most probably this one is missing
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_pass_request_headers on; # this is default, but just to be sure

    proxy_buffering off;
    proxy_redirect off;
    break;
  }

Update:更新:

Remaining two cases when activecable responds with this is failed connection authentication and missing websocket driver(should not be the case for puma)剩下的两种情况是 activecable 响应失败的连接身份验证和缺少 websocket 驱动程序(不应该是 puma 的情况)

can you help me to check this?, i also got 404你能帮我检查一下吗?我也有404

upstream rails_app {  
   server app:3000;
} 
server {  
   # define your domain  
   listen 80;
   server_name portal.comp-moto.com;
   server_tokens off;

   location /.well-known/acme-challenge/ {
      root /var/www/certbot;
   }
}

server {
  listen 443 ssl;
  server_name portal.comp-moto.com;
  server_tokens off;

  proxy_read_timeout 1800;
  proxy_connect_timeout 1800;
  proxy_send_timeout 1800; 
  
  client_max_body_size 20M;
  client_body_buffer_size 20M;
  client_body_timeout 1800;
  client_header_timeout 1800;
  keepalive_timeout 1800;
  send_timeout 1800;

  # define the public application root
  root   /app/public;
  index  index.html;

  # serve static (compiled) assets directly if they exist (for rails production)
  location ~ ^/(assets|images|javascripts|stylesheets|swfs|system)/ {
    try_files $uri @rails;

    access_log off;
    gzip_static on; # to serve pre-gzipped version

    expires max;
    add_header Cache-Control public;

    # Some browsers still send conditional-GET requests if there's a
    # Last-Modified header or an ETag header even if they haven't
    # reached the expiry date sent in the Expires header.
    add_header Last-Modified "";
    add_header ETag "";
    break;
  }

  # send non-static file requests to the app server
  location / {
    try_files $uri @rails;
  }

  ssl_certificate /etc/letsencrypt/live/portal.comp-moto.com/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/portal.comp-moto.com/privkey.pem;

  location @rails {
    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_set_header  X-Forwarded-Ssl on;
    proxy_set_header  X-Forwarded-Port $server_port;
    proxy_set_header  X-Forwarded-Host $host;
    proxy_redirect off;
    proxy_pass http://rails_app;
  }

  location /cable {
    proxy_pass http://rails_app;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-Proto $scheme; 
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_pass_request_headers on; 

    proxy_buffering off;
    proxy_redirect off;
    break;
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 ActionCable Rails 5(Passenger) - 失败:WebSocket握手期间出错:意外响应代码:404 - ActionCable Rails 5 (Passenger) - failed: Error during WebSocket handshake: Unexpected response code: 404 Rails 5 Actioncable-失败:WebSocket握手期间出错:意外的响应代码:502 - Rails 5 Actioncable - failed: Error during WebSocket handshake: Unexpected response code: 502 WebSocket握手期间出错:意外的响应代码:503 - Error during WebSocket handshake: Unexpected response code: 503 WebSocket握手期间出错:意外的响应代码:502 - Error during WebSocket handshake: Unexpected response code: 502 WebSocket 握手期间的 Rails 5 错误:意外响应代码:502 - Rails 5 Error during WebSocket handshake: Unexpected response code: 502 Actioncable Nginx和Puma WebSocket握手:意外响应 - Actioncable Nginx and Puma WebSocket handshake: Unexpected response 在 WebSocket 握手期间 Rails 6 Production ActionCable 错误 - Rails 6 Production ActionCable Error during WebSocket handshake 在websocket握手期间Rails ActionCable错误 - Rails ActionCable error during websocket handshake 带Rails(Puma)的Websockets-WebSocket握手期间出错:意外的响应代码:200 - Websockets with Rails(Puma) - Error during WebSocket handshake: Unexpected response code: 200 ActionCable Websocket 升级和 404 错误 - ActionCable Websocket Upgrade and 404 Error
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM