Socket.io with nginx

2020-01-26 08:45发布

问题:

I'm trying to serve static files by nginx 1.6 and to proxy socket traffic coming from Node.js web server with socket.io .

This is the relevant part of nginx.conf:

location /socket.io/ {
            proxy_pass http://localhost:3000;       
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "Upgrade";
            proxy_set_header Host $host;
        }

It works perfectly directly between the browser and Node.js, but socket.io takes too long when proxied with nginx 1.6. A handshaking protocol takes too much time, but if left uninterrupted it eventually starts to work after a couple of minutes.

Static files delivery by nginx works perfectly.

What could be the problem?

UPDATE:

I analysed a bit the network traffic and determined that the following request lasts around a minute (it's exactly when the upgrade is requested):

Sec-WebSocket-Key: LhZ1frRdl+myuwyR/T03lQ==
Cookie: io=1-A7tpvwmoGbrSvTAAA5
Connection: keep-alive, Upgrade
Upgrade: websocket
....

The expected response is code 101 and:

Connection: upgrade
Sec-WebSocket-Accept: HXx3KKJadQYjDa11lpK5y1nENMM=
Upgrade: websocket
...

instead, the browser receives 400 and:

Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: http://localhost:8888
Connection: keep-alive
Content-Type: application/json
Server: nginx/1.6.2
Transfer-Encoding: chunked

UPDATE 2:

I determined that the same configuration works perfectly on my office computer, meaning that it's my home computer issue. Anyway, would be very nice to determine what exactly is going wrong.

回答1:

In a running server, the nginx's configuration being used here is:

  # Requests for socket.io are passed on to Node on port 3000
  location ~* \.io {
      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 false;

      proxy_pass http://localhost:3000;
      proxy_redirect off;

      proxy_http_version 1.1;
      proxy_set_header Upgrade $http_upgrade;
      proxy_set_header Connection "upgrade";
    }


回答2:

Every example I have seen (Nginx docs, Nginx blog) uses:

proxy_set_header Connection "upgrade";

Note all lowercase "upgrade". Your example has a capital "U". Maybe worth trying.



回答3:

You might forgot about proxy_redirect off;

location / {
            proxy_pass http://localhost:3000/;
            include proxy_params;
            proxy_redirect off;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "Upgrade";
    }