WebSocket 代理
要將客戶端和伺服器之間的連線從 HTTP/1.1 轉換為 WebSocket,會使用 HTTP/1.1 中提供的協定切換機制。
然而,這裡有一個細微之處:由於 "Upgrade" 是一個逐跳 (hop-by-hop)標頭,它不會從客戶端傳遞到代理伺服器。對於正向代理,客戶端可以使用 CONNECT
方法來規避此問題。然而,這不適用於反向代理,因為客戶端不知道任何代理伺服器,因此需要在代理伺服器上進行特殊處理。
從 1.3.13 版本開始,nginx 實作了一種特殊的操作模式,如果代理伺服器返回代碼為 101 (Switching Protocols) 的回應,並且客戶端透過請求中的 "Upgrade" 標頭要求進行協定切換,則允許在客戶端和代理伺服器之間建立通道。
如上所述,包括 "Upgrade" 和 "Connection" 在內的逐跳標頭不會從客戶端傳遞到代理伺服器,因此為了使代理伺服器知道客戶端要將協定切換到 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 { 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; } }
預設情況下,如果代理伺服器在 60 秒內沒有傳輸任何資料,連線將會關閉。可以使用 proxy_read_timeout 指令增加此逾時時間。或者,可以將代理伺服器設定為定期傳送 WebSocket ping 幀,以重設逾時時間並檢查連線是否仍然有效。