Node.js and nginx

This took me some time to figure out, and I didn’t see any detailed posts or bug reports on how to fix this. Nginx doesn’t support HTTP 1.1 on proxy pass, meaning, when you place Node.JS behind a proxy (for load balancing purposes, or you just have multiple endpoints on port 80), websockets will not work properly, since HTTP 1.1 is a core requirement. You’ll know, when you get errors similar to this:
Error during WebSocket handshake: 'Connection' header value is not 'Upgrade'
XMLHttpRequest cannot load ***. Origin *** is not allowed by Access-Control-Allow-Origin.
I’m running nginx 0.6.8, with nginx 1.0.11. To fix this, you need to upgrade to a later version of nginx (a development version), which supports HTTP 1.1 (albeit, experimentally), and then enable the proxy_http_version 1.1 parameter in your vhost configuration.
I’m doing this on Ubuntu.
First, let’s compile nginx:
cd /usr/src
wget http://nginx.org/download/nginx-1.1.13.tar.gz
sudo tar xzvf nginx-1.1.13.tar.gz
cd nginx-1.1.13
sudo ./configure --prefix=/etc/nginx --sbin-path=/usr/sbin --with-http_ssl_module
sudo make; sudo make install
/usr/sbin/nginx -V

# Something like this should show:
nginx version: nginx/1.1.13
built by gcc 4.6.1 (Ubuntu/Linaro 4.6.1-9ubuntu3)
TLS SNI support enabled
configure arguments: --prefix=/etc/nginx --sbin-path=/usr/sbin --with-http_ssl_module
Next, we setup our vhost:
server {
listen 80;
server_name node.domain.com;
location / {
proxy_pass http://localhost:8000;
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;
proxy_redirect off;
proxy_http_version 1.1;
}
}
And now no more errors, and nodejs is working properly. Do note that this is a “bleeding edge” version of nginx, and could come with its own share of issues – so keep an eye out and test thoroughly!
Edit: If you’re still running into some problems, you can enable only xhr-polling/jsonp-polling in your Node.JS/socket.io configuration:
io.set('transports', [
'xhr-polling',
'jsonp-polling'
]);