英文:
Go http request falls back to http2 even when force attempt is set to false
问题
有一个奇怪的问题,每隔几个请求,Go的http
包会抛出以下错误:
http2: server sent GOAWAY and closed the connection; LastStreamID=19999, ErrCode=NO_ERROR, debug=""
我发现默认的传输设置了ForceAttemptHTTP2
为true
(https://golang.org/src/net/http/transport.go 第48行),所以我手动将其设置为false,如下所示:
transport := &http.Transport{
ForceAttemptHTTP2: false,
}
httpClient := &http.Client{Transport: transport}
但是即使这样做了,我仍然得到相同的http2错误,而不是http1,这对我来说没有意义。
我对网络不太了解,所以我觉得我可能漏掉了一些显而易见的东西?
我想问的问题是如何强制http
包只使用http
而不是http2
。
英文:
There this weird thing that keeps happening every few requests where Go's http
package throws the following error:
http2: server sent GOAWAY and closed the connection; LastStreamID=19999, ErrCode=NO_ERROR, debug=""
And so I realised that the default transport has ForceAttemptHTTP2
set to true
(https://golang.org/src/net/http/transport.go line 48), so I manually set that to false like below:
transport := &http.Transport{
ForceAttemptHTTP2: false,
}
httpClient := &http.Client{Transport: transport}
But even after doing that, I still get the same http2 error instead of http1, which is not making sense to me?
I'm new to networking so I have a feeling I'm missing something that should be obvious here?
I guess the question would be how do I force the http
package to only use http
and not http2
答案1
得分: 5
这似乎可以实现:
package main
import (
"crypto/tls"
"net/http"
)
func main() {
client := &http.Client{
Transport: &http.Transport{
TLSNextProto: map[string]func(string, *tls.Conn)http.RoundTripper{},
},
}
req, e := http.NewRequest("HEAD", "https://stackoverflow.com", nil)
if e != nil {
panic(e)
}
res, e := client.Do(req)
if e != nil {
panic(e)
}
println(res.Proto == "HTTP/1.1")
}
> 必须禁用HTTP/2的程序可以通过将Transport.TLSNextProto
(对于客户端)或Server.TLSNextProto
(对于服务器)设置为非nil的空映射来实现。
https://golang.org/pkg/net/http#pkg-overview
诚然,这种语法相当笨拙,所以你可能更喜欢下面这种方式:
package main
import (
"net/http"
"os"
)
func main() {
os.Setenv("GODEBUG", "http2client=0")
req, e := http.NewRequest("HEAD", "https://stackoverflow.com", nil)
if e != nil {
panic(e)
}
res, e := new(http.Client).Do(req)
if e != nil {
panic(e)
}
println(res.Proto == "HTTP/1.1")
}
英文:
This seems to do it:
package main
import (
"crypto/tls"
"net/http"
)
func main() {
client := &http.Client{
Transport: &http.Transport{
TLSNextProto: map[string]func(string, *tls.Conn)http.RoundTripper{},
},
}
req, e := http.NewRequest("HEAD", "https://stackoverflow.com", nil)
if e != nil {
panic(e)
}
res, e := client.Do(req)
if e != nil {
panic(e)
}
println(res.Proto == "HTTP/1.1")
}
> Programs that must disable HTTP/2 can do so by setting Transport.TLSNextProto
> (for clients) or Server.TLSNextProto
(for servers) to a non-nil, empty map.
https://golang.org/pkg/net/http#pkg-overview
Admittedly, this is pretty awkward syntax, so you might prefer something like
this instead:
package main
import (
"net/http"
"os"
)
func main() {
os.Setenv("GODEBUG", "http2client=0")
req, e := http.NewRequest("HEAD", "https://stackoverflow.com", nil)
if e != nil {
panic(e)
}
res, e := new(http.Client).Do(req)
if e != nil {
panic(e)
}
println(res.Proto == "HTTP/1.1")
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论