HTTP Upgrade 协商升级

217 阅读2分钟

在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",为了防止中间代理不支持更换的协议。