Websocket rails (Faye-websocket) 握手错误代码 200 - AWS ElasticBeanstalk、nginx、puma
Posted
技术标签:
【中文标题】Websocket rails (Faye-websocket) 握手错误代码 200 - AWS ElasticBeanstalk、nginx、puma【英文标题】:Websocket rails (Faye-websocket) handshake error code 200 - AWS ElasticBeanstalk, nginx, puma 【发布时间】:2016-09-20 14:16:44 【问题描述】:我正在尝试让启用了 websockets 的应用程序正常工作,但在尝试连接时遇到了错误:
WebSocket connection to 'ws://[domain.com]/' failed: Error during WebSocket handshake: Unexpected response code: 200
我正在学习使用 gem faye-websocket 的教程 (https://devcenter.heroku.com/articles/ruby-websockets)。它在本地运行良好(使用 puma),但是当我尝试将其部署到运行 nginx + puma 的 AWS ElasticBeanstalk 时,websocket 请求无法连接。
我正在使用以下 javascript(使用我自己的域)创建一个新的 WebSocket 连接:
var ws = new WebSocket("ws://[domain.com]/");
按照教程,我创建了一个中间件类来检查传入的 websocket 请求,并相应地处理它。在我的本地服务器上,请求环境哈希如下所示:
"rack.errors"=>#>, "rack.multithread"=>true, "rack.multiprocess"=>false, "rack.run_once"=>false, "SCRIPT_NAME"=>"", "CONTENT_TYPE "=>"text/plain", "QUERY_STRING"=>"", "SERVER_PROTOCOL"=>"HTTP/1.1", "SERVER_SOFTWARE"=>"2.11.1", "GATEWAY_INTERFACE"=>"CGI/1.2", "REQUEST_METHOD"=>"GET", "REQUEST_PATH"=>"/", "REQUEST_URI"=>"/", "HTTP_VERSION"=>"HTTP/1.1", "HTTP_HOST"=>"localhost:3000", " HTTP_CONNECTION"=>"升级", "HTTP_PRAGMA"=>"无缓存", "HTTP_CACHE_CONTROL"=>"无缓存", "HTTP_UPGRADE"=>"websocket", "HTTP_ORIGIN"=>"http://localhost:3000", "HTTP_SEC_WEBSOCKET_VERSION"=>"13", "HTTP_USER_AGENT"=>"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (Khtml, like Gecko) Chrome/50.0.2661.102 Safari/537.36", "HTTP_ACCEPT_ENCODING"= >"gzip, deflate, sdch", "HTTP_ACCEPT_LANGUAGE"=>"en-US,en;q=0.8",
而在 AWS 上它看起来像这样:
"rack.version"=>[1, 3], "rack.errors"=>#, "rack.multithread"=>true, "rack.multiprocess"=>false, "rack.run_once"= >false, "SCRIPT_NAME"=>"", "CONTENT_TYPE"=>"text/plain", "QUERY_STRING"=>"", "SERVER_PROTOCOL"=>"HTTP/1.1", "SERVER_SOFTWARE"=>"2.11.1 ", "GATEWAY_INTERFACE"=>"CGI/1.2", "REMOTE_ADDR"=>"127.0.0.1", "REQUEST_METHOD"=>"GET", "REQUEST_PATH"=>"/", "REQUEST_URI"=>"/" , "HTTP_VERSION"=>"HTTP/1.0", "HTTP_HOST"=>"[domain.com]", "HTTP_X_FORWARDED_FOR"=>"194.80.196.162", "HTTP_CONNECTION"=>"close", "HTTP_PRAGMA"=> "无缓存", "HTTP_CACHE_CONTROL"=>"无缓存", "HTTP_ORIGIN"=>"http://[domain.com]", "HTTP_SEC_WEBSOCKET_VERSION"=>"13", "HTTP_USER_AGENT"=>"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36", "HTTP_ACCEPT_ENCODING"=>"gzip, deflate, sdch", "HTTP_ACCEPT_LANGUAGE"=>"en-US,en;q =0.8",
所以我可以看到,在 AWS 上,请求标头 HTTP_CONNECTION 和 HTTP_UPGRADE 没有被切换到 websockets。
但是,我尝试设置我的 nginx 配置,但我无法弄清楚它是如何工作的(例如 https://gist.github.com/KeithP/f8534c04d20c2b4e4b1d)
files:
"/etc/nginx/conf.d/websockets.conf" :
content: |
upstream backend
server unix:///var/run/puma/my_app.sock;
server
listen 80;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
server_name env1.t3tiiauce6.us-west-2.elasticbeanstalk.com
# prevents 502 bad gateway error
large_client_header_buffers 8 32k;
location /
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
# prevents 502 bad gateway error
proxy_buffers 8 32k;
proxy_buffer_size 64k;
proxy_pass http://backend;
proxy_redirect off;
location /assets
root /var/app/current/public;
# enables WS support
location /cable
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
据我了解,这会将发往 /cable 的请求路由到后端 rails 应用程序,并升级到 websockets 的连接。但是,当我尝试 /cable 时,出现 404 错误(因为没有匹配的路由)。
那么我怎样才能让我的 rails 应用程序与 websockets 正确握手呢?任何帮助将非常感激!!我也尝试过使用 websocket-rails gem 并得到握手错误代码 500
【问题讨论】:
【参考方案1】:终于成功了!最后,将以下文件放入 .ebextensions 文件夹中:
server
listen 80;
server_name localhost; # need to listen to localhost for worker tier
location /
proxy_pass http://my_app; # match the name of upstream directive which is defined in another file
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
location /websocket
proxy_pass http://my_app/websocket;
proxy_set_header Host $host;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection Upgrade;
location /assets
alias /var/app/current/public/assets;
gzip_static on;
gzip on;
expires max;
add_header Cache-Control public;
location /public
alias /var/app/current/public;
gzip_static on;
gzip on;
expires max;
add_header Cache-Control public;
我的 Javascript 更改为:
var ws = new WebSocket("ws://[domain.com]/websocket");
希望对遇到类似问题的人有所帮助!
【讨论】:
以上是关于Websocket rails (Faye-websocket) 握手错误代码 200 - AWS ElasticBeanstalk、nginx、puma的主要内容,如果未能解决你的问题,请参考以下文章
从 rails runner 内部触发/订阅 websocket-rails 事件
Rails 4 + Websocket-rails + Passenger + Nginx + 负载均衡器