Search code examples
node.jsnginxmeteor

Meteor WebSocket handshake error 400 with nginx


I managed to deploy meteor on my infrastructure (Webfactions). The application seems to work fine but I get the following error in the browser console when my application starts:

WebSocket connection to 'ws://.../websocket' failed: Error during WebSocket handshake: Unexpected response code: 400


Solution

  • WebSockets are fast and you don't have to (and shouldn't) disable them.

    The real cause of this error is that Webfactions uses nginx, and nginx was improperly configured. Here's how to correctly configure nginx to proxy WebSocket requests, by setting proxy_set_header Upgrade $http_upgrade; and proxy_set_header Connection $connection_upgrade;:

    # we're in the http context here
    map $http_upgrade $connection_upgrade {
      default upgrade;
      ''      close;
    }
    
    # the Meteor / Node.js app server
    server {
      server_name yourdomain.com;
    
      access_log /etc/nginx/logs/yourapp.access;
      error_log /etc/nginx/logs/yourapp.error error;
    
      location / {
        proxy_pass http://localhost:3000;
    
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $host;  # pass the host header - http://wiki.nginx.org/HttpProxyModule#proxy_pass
    
        proxy_http_version 1.1;  # recommended with keepalive connections - http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_http_version
    
        # WebSocket proxying - from http://nginx.org/en/docs/http/websocket.html
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
      }
    
    }
    

    This is an improved nginx configuration based on David Weldon's nginx config. Andrew Mao has reached a very similar configuration.

    Remember to also set the HTTP_FORWARDED_COUNT environment variable to the number of proxies in front of the app (usually 1).