nginx reverse proxy websockets

2020-05-20 04:05发布

问题:

nginx now supports proxying websockets, but I was unable to find any information on how to do this without having a separate location block that applies to URIs on which websockets are used.

I've seen some folks recommending some variations of this approach:

location / {
    proxy_http_version 1.1;

    proxy_set_header    Upgrade     $http_upgrade;
    proxy_set_header    Connection  "upgrade";

    proxy_pass  http://host:port;
}

Would that be the correct way to proxy standard HTTP as well as websockets?

I don't want the Upgrade header or Connection being set to upgrade unless that's what the browser sent, but these proxy_set_header lines are required for websockets to work.

Why doesn't nginx just forward the original Upgrade/Connection headers?

I've experimented with this and found that nginx does not proxy the Upgrade header and changes the Connection header to close from upgrade if running without the two proxy_set_header lines. With them, Connection is upgrade for non-websocket requests, which is also bad.

回答1:

Why doesn't nginx just forward the original Upgrade/Connection headers?

From the official documentation: since the “Upgrade” is a hop-by-hop header, it is not passed from a client to proxied server

See RFC 2616.


I don't want the Upgrade header or Connection being set to "upgrade" unless that's what the browser sent,

There is also an example:

map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}

server {
    ...

    location /chat/ {
        proxy_pass http://backend;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
    }
}

Connection is 'upgrade' for non-websocket requests, which is also bad.

Do you actually know what the Connection header means? Just a quote from RFC: for each connection-token in this field, remove any header field(s) from the message with the same name as the connection-token.

How it can be bad?