场景
业务服务提供了 websocket 服务,基于 websocket 来实现报表数据的推送,客户在浏览器上查看报表,经过 http 代理将请求传递给后端服务。
问题
客户在浏览器上查看报表数据时,报表功能异常,浏览器开发工具查看到 websocket 握手在服务端拒绝掉,返回 400 bad request。
分析
400 一般是由于客户端,所以应该是客户端请求参数或者路出现问题。通过对比正常和异常的websocket 请求报文,得到,异常的报文缺少了 Upgrade:websocket 的 http 头部。
Upgrade 属于 hop-to-hop 类型的 http cache ,与 end-to-end 不同,后者在两个客户端请求至最终后端服务时都不会变,如 User-Agent,而前者则会在经过代理时被处理掉,需要 proxy 的能力再将这类 hop-to-hop header 处理下。
解决方案
nginx 有如下解决方案,在 http 请求头里把 Upgrade 补上去,前提是在代理到后端之前的报文有 Upgrade。
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
参考
关于Nginx+websocket 400问题 https://www.jianshu.com/p/d5b136a27bdf
End-to-end and Hop-by-hop Headers https://tools.ietf.org/html/rfc2616#section-13.5.1