老青菜

HTTP/2.0 协议协商

2019-06-13

HTTP/2本身并不强制使用SSL/TLS,和HTTP/1.1一样,兼容“http”、“https”的两种URL模式,支持以下两种标识(具体可以看这里):

  1. h2(over TLS),建立在TLS之上的HTTP/2.0,HTTPS模式。
  2. h2c(over TCP),建立在明文TCP之上的HTTP/2.0,HTTP模式。

Protocol Negotiation

如果Client只支持HTTP/1.1,或者Server只支持HTTP/1.1,或者Server只支持h2c,那么Client和Server如何选择合适的协议呢?
那么我们来看一下这Client和Server是如何进行协议协商的。

h2c

针对h2c的协商机制,Client使用了HTTP/1.1的Upgrade(rfc7230#section-6.7)机制,发起了HTTP/1.1的协议升级,Upgrade字段指定了希望升级到的协议和版本号,比如下面这段:

GET / HTTP/1.1
Host: server.example.com
Connection: Upgrade, HTTP2-Settings
Upgrade: h2c
HTTP2-Settings: <base64url encoding of HTTP/2 SETTINGS payload>

如果Server不支持Upgrade列出的协议,可以直接以HTTP/1.1方式直接响应,比如下面这段:

HTTP/1.1 200 OK
Content-Length: 243
Content-Type: text/html
...

如果Server支持该协议,必须响应101的状态码,并且在Upgrade空行响应结束之后,可以以新的格式响应请求,比如说HTTP/2.0二进制帧的格式。

HTTP/1.1 101 Switching Protocols
Connection: Upgrade
Upgrade: h2c

[ HTTP/2 connection ...

h2协商

由于h2是依赖SSL/TLS的,基于h2的协议协商则依赖于ALPN(Application Layer Protocol Negotiation,应用层协议协商)。也就是在TLS握手阶段,通信双方原本就要进行加密套件等的协商,ALPN作为起拓展字段加入握手协商过程中,对通信不会增添性能影响。具体协商过程如下:

  1. 在TLS握手过程中,Client在Client Hello中指定拓展参数ALPN Protocol,即希望升级到的协议列表。
  2. Server收到Client Hello,从展参数ALPN Protocol列表里选择支持的协议。在Server Hello中,回复拓展参数ALPN Protocol,值为选择的协议。
  3. 至此就完成了协议协商,双方按照协商的协议进行通信。

下面是针对TLSv1.2的Wireshark抓包图:

总结

尽管HTTP/2.0支持h2c模式,但是可能是考虑到安全问题,基本上主流的浏览器都要求HTTP/2.0部署在SSL/TLS上,所以现在HTTP2.0基本都是基于h2标识,基于HTTPS模式部署。

参考链接

rfc7230 Upgrade
rfc7540

Tags: HTTP
使用支付宝打赏
使用微信打赏

若你觉得我的文章对你有帮助,欢迎点击上方按钮对我打赏

扫描二维码,分享此文章