英文:
How to trace http.Client with httptrace in Go
问题
根据您提供的代码,您想要将httptrace
应用于NewWithClient
的http.Client
参数以进行HTTP跟踪。然而,您尝试的代码无法跟踪http.Client
,GotConn
没有输出。您希望有人帮助您找出上述代码的问题所在。
根据您提供的代码,问题可能出在以下几个地方:
-
TraceTransport
结构体的RoundTrip
方法没有实现对http.DefaultTransport.RoundTrip
的调用,这可能导致请求没有被正确处理。您可以尝试在RoundTrip
方法中添加对http.DefaultTransport.RoundTrip
的调用,以确保请求被正确处理。 -
ClientWrapper
结构体的Do
方法中,您将clientWrapperTrace
作为httptrace.WithClientTrace
的参数传递给了req.Context()
,但是在代码中并没有使用req
进行实际的HTTP请求。您需要确保在Do
方法中使用req
进行实际的HTTP请求,例如使用c.defaultClient.Do(req)
。
请尝试对上述问题进行修复,并检查是否能够成功跟踪http.Client
。如果问题仍然存在,请提供更多关于问题的详细信息,以便我们能够更好地帮助您解决问题。
英文:
Per this doc, we can trace http.Client
with httptrace
in this way
t := &transport{}
req, _ := http.NewRequest("GET", "https://google.com", nil)
trace := &httptrace.ClientTrace{
GotConn: t.GotConn,
}
req = req.WithContext(httptrace.WithClientTrace(req.Context(), trace))
client := &http.Client{Transport: t}
For google API client, here are the one wrapper codes
func NewWithClient(jsonKey []byte, cli *http.Client) (*Client, error) {
if cli == nil {
return nil, fmt.Errorf("client is nil")
}
ctx := context.WithValue(context.Background(), oauth2.HTTPClient, cli)
conf, err := google.JWTConfigFromJSON(jsonKey, androidpublisher.AndroidpublisherScope)
if err != nil {
return nil, err
}
service, err := androidpublisher.NewService(ctx, option.WithHTTPClient(conf.Client(ctx)))
if err != nil {
return nil, err
}
return &Client{service}, err
}
We want to apply httptrace
to the http.Client
argument of NewWithClient
to do HTTP trace.
What we have tried
type TraceTransport struct {
}
var traceTransport = &TraceTransport{}
var trace = &httptrace.ClientTrace{
GotConn: traceTransport.GotConn,
}
func (t *TraceTransport) RoundTrip(req *http.Request) (*http.Response, error) {
return http.DefaultTransport.RoundTrip(req)
}
func (t *TraceTransport) GotConn(info httptrace.GotConnInfo) {
fmt.Printf("Connection reused for %v \n", info.Reused)
}
type ClientWrapper struct {
defaultClient *http.Client
}
var clientWrapperTrace = &httptrace.ClientTrace{GotConn: traceTransport.GotConn}
func (c *ClientWrapper) Do(req *http.Request) (*http.Response, error) {
req = req.WithContext(httptrace.WithClientTrace(req.Context(), clientWrapperTrace))
return c.defaultClient.Do(req)
}
func NewClientTrace(jsonKey []byte) (*Client, error) {
cli := &http.Client{
Transport: traceTransport,
Timeout: time.Duration(10) * time.Second,
}
cliWrapper := &ClientWrapper{defaultClient: cli}
ctx := context.WithValue(context.Background(), oauth2.HTTPClient, cliWrapper)
conf, err := google.JWTConfigFromJSON(jsonKey, androidpublisher.AndroidpublisherScope)
if err != nil {
return nil, err
}
service, err := androidpublisher.NewService(ctx, option.WithHTTPClient(conf.Client(ctx)))
if err != nil {
return nil, err
}
return &Client{service}, err
}
type Client struct {
service *androidpublisher.Service
}
func (c *Client) VerifyProduct(
ctx context.Context,
packageName string,
productID string,
token string,
) (*androidpublisher.ProductPurchase, error) {
ps := androidpublisher.NewPurchasesProductsService(c.service)
result, err := ps.Get(packageName, productID, token).Context(ctx).Do()
return result, err
}
// test codes
c, err := NewClientTrace([]byte(privateKey))
if err != nil {
return
}
packageName := "package.name"
productID := "product_id"
token := "xxxxx"
r, err := c.VerifyProduct(context.Background(), packageName, productID, token)
However, it is failed to trace http.Client
, There is no output of GotConn
. Could someone help us to figure out the issue of the above codes?
答案1
得分: 2
-
google/oauth2
的请求无法通过httptrace
进行跟踪。你在ClientWrapper
中使用context.WithValue
传递的内容将被忽略这里,oauth2有自己的http.Client,它只是使用了来自context.Value的*http.Client
的Transport
方法。 -
使用httptrace可以跟踪来自androidpublisher的请求,示例如下:
ctx := httptrace.WithClientTrace(context.Background(), clientWrapperTrace)
r, err := c.VerifyProduct(ctx, packageName, productID, token)
- 如果你只想计算请求的数量,我认为覆盖
http.Client.Transport
是一种简单的方法。
type TraceTransport struct {
}
func (t *TraceTransport) RoundTrip(req *http.Request) (*http.Response, error) {
fmt.Printf("RoundTrip hook %v\n", req.URL)
return http.DefaultTransport.RoundTrip(req)
}
func NewClientTrace(jsonKey []byte) (*Client, error) {
cli := &http.Client{Transport: &TraceTransport{}}
ctx := context.WithValue(context.Background(), oauth2.HTTPClient, cli)
// ...
service, err := androidpublisher.NewService(ctx, option.WithHTTPClient(conf.Client(ctx)))
// ....
}
英文:
-
Requests from
google/oauth2
are not traceable byhttptrace
. yourClientWrapper
passed withcontext.WithValue
will be ignored here, and oauth2 has it's own http.Client, it just use theTransport
method of*http.Client
from context.Value. -
Requests from androidpublisher can be traced by httptrace like this:
ctx := httptrace.WithClientTrace(context.Background(), clientWrapperTrace)
r, err := c.VerifyProduct(ctx, packageName, productID, token)
- If you just want to count the requests, i think overwrite the
http.Client.Transport
is a easy way.
type TraceTransport struct {
}
func (t *TraceTransport) RoundTrip(req *http.Request) (*http.Response, error) {
fmt.Printf("RoundTrip hook %v\n", req.URL)
return http.DefaultTransport.RoundTrip(req)
}
func NewClientTrace(jsonKey []byte) (*Client, error) {
cli := &http.Client{Transport: &TraceTransport{}}
ctx := context.WithValue(context.Background(), oauth2.HTTPClient, cli)
// ...
service, err := androidpublisher.NewService(ctx, option.WithHTTPClient(conf.Client(ctx)))
// ....
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论