英文:
How do I adjust Go's http Client (or Transport) to mimic curls --http2-prior-knowledge flag?
问题
我正在与一个我无法控制的服务器进行交互,该服务器在请求包含内容(带有有效负载的POST、PUT、PATCH请求)时不执行协议升级。目前还不清楚服务器的问题是什么,但我注意到当我使用--http2-prior-knowledge
查询时,协议会升级:
❯ curl -i -PUT --http2-prior-knowledge http://localhost:8081/document/v1/foo -d '{\"fields\": {\"docid\": \"123\"}}'
HTTP/2 200
date: Tue, 08 Nov 2022 13:26:50 GMT
content-type: application/json;charset=utf-8
vary: Accept-Encoding
content-length: 78
而没有使用--http2-prior-knowledge
的相同请求会停留在HTTP/1.1。这似乎更接近Go的HTTP客户端的默认行为:
❯ curl -i -PUT --http2 http://localhost:8081/document/v1/foo -d '{\"fields\": {\"docid\": \"123\"}}'
HTTP/1.1 200 OK
Date: Tue, 08 Nov 2022 01:37:17 GMT
Content-Type: application/json;charset=utf-8
Vary: Accept-Encoding
Content-Length: 78
当我使用Go的默认客户端调用相同的API时,协议不会升级。我尝试在传输中设置ForceAttemptHTTP2: true
,但每个http.Response
的.Proto
都是HTTP/1.1
。
我认为我需要了解的是如何在Go中模拟curl的prior-knowledge标志。这可能吗?
英文:
I'm interacting with a server (that is out of my control) in which protocol upgrade is not performed by the server if a request contains content (POST, PUT, PATCH with payload). It's unclear exactly what the issue with the server is, but I noticed that when I query with --http2-prior-knowledge
, the protocol is upgraded:
❯ curl -i -PUT --http2-prior-knowledge http://localhost:8081/document/v1/foo -d '{"fields": {"docid": "123"}}'
HTTP/2 200
date: Tue, 08 Nov 2022 13:26:50 GMT
content-type: application/json;charset=utf-8
vary: Accept-Encoding
content-length: 78
The same request without --http2-prior-knowledge
is stuck at HTTP/1.1. This seems closer to the default behaviour of Go's HTTP client
❯ curl -i -PUT --http2 http://localhost:8081/document/v1/foo -d '{"fields": {"docid": "123"}}'
HTTP/1.1 200 OK
Date: Tue, 08 Nov 2022 01:37:17 GMT
Content-Type: application/json;charset=utf-8
Vary: Accept-Encoding
Content-Length: 78
When I call this same API using Go's default client, the protocol is not upgraded. I've tried setting ForceAttemptHTTP2: true
on the transport, but each http.Response
contains a .Proto
of HTTP/1.1
I think what I need to understand is how I can mimic curl's prior-knowledge flag in Go. Is this possible?
答案1
得分: 1
我通过指定一个自定义的http2.Transport
来解决了这个问题,跳过了TLS拨号。回顾起来,理想的解决方案是使用一个SSL证书(自签名即可),这样可以更好地保证使用HTTP2。以下是一些相关链接:
c := &http.Client{
// 跳过TLS拨号
Transport: &http2.Transport{
AllowHTTP: true,
DialTLS: func(netw, addr string, cfg *tls.Config) (net.Conn, error) {
return net.Dial(netw, addr)
},
},
}
链接:
- https://stackoverflow.com/questions/46788904/why-do-web-browsers-not-support-h2c-http-2-without-tls
- https://github.com/golang/go/issues/14141
英文:
I solved this issue by specifying a custom http2.Transport
which skipped TLS dial. The ideal solution, in retrospect, is to use an SSL certificate (self-signed is sufficient) which would better guarantee the use of HTTP2. Leaving some links for posterity
c := &http.Client{
// Skip TLS Dial
Transport: &http2.Transport{
AllowHTTP: true,
DialTLS: func(netw, addr string, cfg *tls.Config) (net.Conn, error) {
return net.Dial(netw, addr)
},
},
}
And links:
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论