nginx-8 WebSocket代理

使用HTTP/1.1协议中的protocol_switch机制,可以将客户端与服务器的连接协议由HTTP/1.1升级为WebSocket。

HTTP协议中的 hop-by-hop 头部

  • Connection
  • Keep-Alive
  • Proxy-Authenticate
  • Proxy-Authorization
  • TE
  • Trailers
  • Transfer-Encoding
  • Upgrade

只对单个传输级连接有效,不存储于缓存,可以由代理服务器转发。

HTTP method 之 CONNECT

CONNECT https://www.baidu.com HTTP/1.1
客户端告诉代理服务器,替我访问https://www.baidu.com,并将结果返回给我。


因为Upgrade是一个hop-by-hop头部,所以不能直接从客户端传递给被代理的服务器。使用正向代理时,客户端可以CONNECT方法回避这个问题。对于反向代理却回避不了,因为客户端并不知道代理服务器的存在,更不知道请求需要在代理服务器上特殊处理。

版本1.3.13之后,nginx实现了一种特殊操作模式:如果被代理的服务器返回带有101状态码的响应,并且客户端通过请求中的Upgrade请求protocol_switch,则允许在客户机和被代理的服务器之间设置隧道。

正如上面所说,作为hop-by-hop头部,UpgradeConnection不能从客户端直接传递给被代理的服务器。为了让被代理的服务器可以接收到这两个头部,知道客户端想要切换到WebSocket协议,必须由代理服务器显示地转发。

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

在一个更复杂的例子中,向代理服务器发出的请求中Connection头字段的值取决于客户端请求报头中是否存在Upgrade字段:

http {
    # 若http_upgrade存在,Connection值为upgrade,升级协议
    # 若http_upgrade不存在,Connection值为close,关闭连接
    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;
        }
    }

默认情况下,如果被代理的服务器在60s内未传输任何数据,连接就会被关闭。这个时间可由proxy_read_timeout指令修改。或者,可以配置被代理的服务器定期发送 WebSocket ping帧 来重置超时并检查连接是否仍然有效。

你可能感兴趣的:(nginx-8 WebSocket代理)