在websocket实现中,客户端和服务端在建立连接时使用了协商升级协议,由http协议转为websocket协议,其中用到了HTTP/1.1中的新属性Upgrade。
下面摘取了该属性的部分描述,原文请参考 RFC 7230: Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing (rfc-editor.org)
Upgrade字段
HTTP Header中的"Upgrade"字段提供了一种简单的机制在相同连接中将HTTP/1.1协议转换为其他协议。
客户端可以在请求头中加入值为协议列表的"Upgrade"字段,以请求服务端根据从前往后的优先级选择一个协议来转换。服务端如果不希望进行协议转换可以忽略掉该请求字段。
协商不能用于强制转换协议。
Upgrade = 1#protocol
protocol = protocol-name ["/" protocol-version]
protocol-name = token
protocol-version = token
如果协商成功,服务端接着会返回101(转换协议)状态,并在返回头中携带协商后的新协议到"Upgrade"字段。服务端不能返回客户端未指定的协议。服务端可能不会按照客户端指定的优先级来返回需要转换的协议。
服务端可以返回426(升级请求)状态,并带上可转换的协议,要求客户端升级协议。服务端可能随时在响应中返回协商升级协议。
下面是一个客户端请求例子:
GET /hello.txt HTTP/1.1
Host: www.example.com
Connection: upgrade
Upgrade: HTTP/2.0, SHTTP/1.3, IRC/6.9, RTA/x11
对上面例子请求的返回值:
HTTP/1.1 101 Switching Protocols
Connection: upgrade
Upgrade: HTTP/2.0
[... data stream switches to HTTP/2.0 with an appropriate response
(as defined by new protocol) to the "GET /hello.txt" request ...]
当发送了协商升级,发送者必须同时在header中带上Connection字段(Section 6.1),且值为"upgrade",为了防止中间代理不支持更换的协议。