我正在尝试使用HTTP/2扩展服务器,该服务器已经支持带有TLS v1.2 的HTTP/1.1。我在Go中编写它,我像这样定义了 tls 配置 -
tlsConfig := &tls.Config{
Certificates: []tls.Certificate{cert},
ServerName: "mysrvr",
NextProtos: []string{"h2", "http/1.1", "http/1.0"},
Time: time.Now,
Rand: rand.Reader,
}
Run Code Online (Sandbox Code Playgroud)
很明显,我使用了“ h2 ”字符串来设置 ALPN 握手。
现在,当我通过 curl 提出请求时,我收到了这个请求 -
$ curl -v https://127.0.0.1:8000 -k --http2
Run Code Online (Sandbox Code Playgroud)
当我解析请求时,它显示首先发送的是PRI方法而不是GET -
HTTP/2.0
PRI
Run Code Online (Sandbox Code Playgroud)
我从https://tools.ietf.org/html/rfc7540#page-78得到了一些关于PRI方法的想法,其中说明如下 -
This method is never used by an actual client.
This method will appear to be used when an HTTP/1.1 server or
intermediary attempts to parse an HTTP/2 connection preface.
Run Code Online (Sandbox Code Playgroud)
我现在的问题是为什么要发送PRI请求,而服务器显然支持HTTP/2?我是否需要根据 HTTP/2 规范解析它并使用空的SETTINGS帧进行响应,还是 Go http2 运行时应该处理它?
我正在使用http.ReadRequest解析客户端请求,但即使我忽略PRI请求(如下所示),这似乎也不适用于HTTP/2请求。
HTTP/2 客户端应该发送的第一条消息就是这条 PRI 消息。从HTTP/2 规范:
在 HTTP/2 中,每个端点都需要发送一个连接序言作为对所用协议的最终确认,并为 HTTP/2 连接建立初始设置。客户端和服务器各自发送不同的连接序言。
客户端连接序言以 24 个八位字节的序列开头,十六进制表示为:
Run Code Online (Sandbox Code Playgroud)0x505249202a20485454502f322e300d0a0d0a534d0d0a0d0a也就是说,连接前言以字符串 PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n 开始。这个序列必须跟随一个设置帧(第 6.5 节),它可以是空的。
...
注意:选择客户端连接前言是为了让大部分 HTTP/1.1 或 HTTP/1.0 服务器和中介不尝试处理更多的帧。
这条消息的重点是它是一个虚假的类似 HTTP/1 的消息,所以任何不知道 HTTP/2 的服务器都应该响应一个错误。
任何 HTTP/2 服务器都应该期望发送此消息,然后应该忽略它,并继续使用 HTTP/2。
事实上,如果这条消息没有被发送,那么服务器应该把它当作一个错误而不是继续:
客户端和服务器必须将无效的连接序言视为 PROTOCOL_ERROR 类型的连接错误(第 5.4.1 节)。在这种情况下可以省略 GOAWAY 帧(第 6.8 节),因为无效的前言表明对等方未使用 HTTP/2。
| 归档时间: |
|
| 查看次数: |
4253 次 |
| 最近记录: |