http2 实现中的 PRI 方法导致问题

Sam*_*Sam 1 http go http2

我正在尝试使用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请求。

Bar*_*ard 5

HTTP/2 客户端应该发送的第一条消息就是这条 PRI 消息。从HTTP/2 规范

在 HTTP/2 中,每个端点都需要发送一个连接序言作为对所用协议的最终确认,并为 HTTP/2 连接建立初始设置。客户端和服务器各自发送不同的连接序言。

客户端连接序言以 24 个八位字节的序列开头,十六进制表示为:

0x505249202a20485454502f322e300d0a0d0a534d0d0a0d0a
Run Code Online (Sandbox Code Playgroud)

也就是说,连接前言以字符串 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。