Nginx/Puma/Rails - WebSocket connection to '<URL>' failed: WebSocket is closed before the connection is established

Viewed 336

I'm trying to set up a websocket connection using Rails 6 and actioncable on AWS with Nginx and Puma.

Through the console, I receive the errror WebSocket connection to '' failed: WebSocket is closed before the connection is established.

Using wscat, I get a 408 timeout.

The interesting thing is it hits my connection.rb, goes through the entire connect method then just stops, never hitting my channel's subscribe method at all.

Nginx Config:

  location /cable {
    proxy_pass http://my_site/cable;
    proxy_http_version 1.1;
    proxy_set_header Upgrade websocket;
    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_set_header Origin "";
    proxy_buffering off;
    proxy_redirect off;
    break;
}

Log Output

Mar 19 17:07:03 ip-10-0-2-227 my_site[21840]: [2df21399-25e0-4500-ad62-c1a40ae34cdc] Started GET "/cable/" [WebSocket] for 3.220.129.76 at 2021-03-19 17:07:03 -0400
Mar 19 17:07:03 ip-10-0-2-227 my_site[21840]: [2df21399-25e0-4500-ad62-c1a40ae34cdc] Successfully upgraded to WebSocket (REQUEST_METHOD: GET, HTTP_CONNECTION: upgrade, HTTP_UPGRADE: websocket)
Mar 19 17:07:03 ip-10-0-2-227 my_site[21840]: User Load (0.5ms)  SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2  [["id", 117], ["LIMIT", 1]]
Mar 19 17:07:03 ip-10-0-2-227 my_site[21840]: Registered connection (Z2lkOi8vZWxvY2FsLWNhbGwtY2VudGVyL1VzZXIvMTE3)

Additional log output

10.0.51.76 - - [19/Mar/2021:17:18:33 -0400] "GET /cable HTTP/1.1" 101 69 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.146 Safari/537.36"
10.0.51.76 - - [19/Mar/2021:17:19:04 -0400] "GET /cable HTTP/1.1" 101 69 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.146 Safari/537.36"
10.0.51.76 - - [19/Mar/2021:17:19:35 -0400] "GET /cable HTTP/1.1" 101 69 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.146 Safari/537.36"

stage.rb configuration

  config.action_cable.url = "ws://my-site.com/cable"
  config.action_cable.allowed_request_origins = [/http:\/\/*/, /https:\/\/*/]
  config.action_cable.disable_request_forgery_protection = true

What I've tried

Literally everything I could find. Change my action_cable.url from ws to wss and back again, commenting out allowed_request_origins, a dozen different copy and pasted websocket configs for nginx. I've also upgraded puma, change my AWS load balancer from an ELB to ALB, and tried running puma as a separate instance. I can make things worse (404s instead of 101s, 503s if I do something very wrong), but no luck getting it working.

Note: It works fine locally through non-SSL nginx, it's only when I try to deploy to my staging environment that everything goes wrong.

0 Answers
Related