我正在尝试编写一个Go客户端来测试我们的http/2基础架构.我想发一个http请求,https://mydomain.tld/somePage并希望收到一个html响应,以及几个推送资源.我想确保那些推动成功,如果不成功则失败.
我不清楚标准库的任何部分是否暴露了我需要的这个功能.
我可以查看响应并检查协议版本以检测http2.
我可以看到Link像https://http2-push.appspot.com/这样发送推送的网站的响应中的标题,但我不太清楚链接标头和实际推送承诺框架之间的关系.你可以通过http 1.1获得链接头,所以我不确定是否只能确保推送会发生.
该http2包具有较低级别Framer的接口,我可能能够利用验证原始帧,但说实话,我不知道如何设置一个,并向其发出的初始请求.
是否有任何示例说明go客户端如何验证http2推送资源的正确配置?
如果我们可以获得 http.Client 自然读取的字节的副本,那么使用 golang.org/x/net/http2 中的 Framer 并不难。我们可以通过实现我们自己的 net.Conn 来做到这一点。
我在下面的程序中取得了一些进展,但是我没有看到预期的 PUSH_PROMISE 帧。经过一番挖掘后,我发现Go 客户端明确禁用了 Push。在这种情况下,服务器不允许发送这些帧。我没有看到改变该设置的明显方法(除了破解 stdlib 之外)。
我以为我仍然分享我的代码。也许我终究错过了一些简单的事情来让它发挥作用。
package main
import (
"bytes"
"crypto/tls"
"io"
"io/ioutil"
"log"
"net"
"net/http"
"os"
"golang.org/x/net/http2"
)
func main() {
buf := &bytes.Buffer{}
transport := &http2.Transport{DialTLS: dialT(buf)}
client := &http.Client{Transport: transport}
res, err := client.Get("https://http2-push.appspot.com/")
if err != nil {
log.Fatal(err)
}
res.Body.Close()
res.Write(os.Stdout)
framer := http2.NewFramer(ioutil.Discard, buf)
for {
f, err := framer.ReadFrame()
if err == io.EOF || err == io.ErrUnexpectedEOF {
break
}
switch err.(type) {
case nil:
log.Println(f)
case http2.ConnectionError:
// Ignore. There will be many errors of type "PROTOCOL_ERROR, DATA
// frame with stream ID 0". Presumably we are abusing the framer.
default:
log.Println(err, framer.ErrorDetail())
}
}
}
// dialT returns a connection that writes everything that is read to w.
func dialT(w io.Writer) func(network, addr string, cfg *tls.Config) (net.Conn, error) {
return func(network, addr string, cfg *tls.Config) (net.Conn, error) {
conn, err := tls.Dial(network, addr, cfg)
return &tConn{conn, w}, err
}
}
type tConn struct {
net.Conn
T io.Writer // receives everything that is read from Conn
}
func (w *tConn) Read(b []byte) (n int, err error) {
n, err = w.Conn.Read(b)
w.T.Write(b)
return
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1132 次 |
| 最近记录: |