协议升级机制

协议升级

HTTP协议 提供了一种特殊的机制,这一机制允许将一个已建立的连接升级成新的、不相容的协议。这篇指南涵盖了其工作原理和使用场景。

通常来说这一机制总是由客户端发起的 (不过也有例外,比如说可以由服务端发起升级到传输层安全协议(TLS)), 服务端可以选择是否要升级到新协议。借助这一技术,连接可以以常用的协议启动(如HTTP/1.1),随后再升级到HTTP2甚至是WebSockets.

注意:HTTP/2 明确禁止使用此机制,这个机制只属于HTTP/1.1

原理

协议升级请求总是由客户端发起的;暂时没有服务端请求协议更改的机制。当客户端试图升级到一个新的协议时,可以先发送一个普通的请求(GET,POST等),不过这个请求需要进行特殊配置以包含升级请求。

特别这个请求需要添加两项额外的header:

Connection: Upgrade
设置 Connection 头的值为 “Upgrade” 来指示这是一个升级请求.
Upgrade: protocols
Upgrade 头指定一项或多项协议名,按优先级排序,以逗号分隔。
一个典型的包含升级请求的例子差不多是这样的:

1
2
3
4
GET /index.html HTTP/1.1
Host: www.example.com
Connection: upgrade
Upgrade: example/1, foo/2

如果服务器决定升级这次连接,就会返回一个 101 Switching Protocols 响应状态码,和一个要切换到的协议的头部字段Upgrade。 如果服务器没有(或者不能)升级这次连接,它会忽略客户端发送的 “Upgrade 头部字段,返回一个常规的响应:例如一个200 OK).

服务在发送 101 状态码之后,就可以使用新的协议,并可以根据需要执行任何其他协议指定的握手。实际上,一旦这次升级完成了,连接就变成了双向管道。并且可以通过新协议完成启动升级的请求。

由HTTP/1.1请求建立的连接可以升级为HTTP/2协议的连接,但是反过来不可以。事实上HTTP/2已经不再支持101状态码了,也不再支持任何连接升级机制。

升级到WebSocket协议的连接

至今为止最经常会需要升级一个HTTP连接的场合就是使用WebSocket。当你用 WebSocket API 以及其他大部分实现WebSockets的库去建立WebSocket连接时,基本上都不用操心升级的过程,因为这些API已经实现了这一步。比如,用如下API打开一个WebSocket连接:

1
webSocket = new WebSocket("ws://destination.server.ext", "optionalProtocol");

WebSocket() 构造函数已经自动完成了发送初始 HTTP/1.1 请求,处理握手及升级过程。

你也可以用 “wss://“ 地址格式来打开安全的WebSocket连接。

如果想要自己重头实现WebSocket 连接,就必须要处理握手和升级过程。在创建初始HTTP/1.1会话之后你需要发送另一个HTTP标准请求,但在headers中要带上Upgrade and Connection,也就是:

1
2
Connection: Upgrade
Upgrade: websocket
------ 本文结束------

本文标题:协议升级机制

文章作者:Perkins

发布时间:2020年08月31日

原始链接:https://perkins4j2.github.io/posts/254331/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。