获取http.Request的大小

问题描述 投票:0回答:1

在我的应用程序中,我想注册 HTTP 客户端沿线路传输了多少字节,以控制该指标。

我找不到轻松完成此任务的方法。

http.Request
对象有一个方便的方法
Write
,它用将通过网络传输的HTTP数据包填充缓冲区,但如果我调用它,那么主体就会关闭,并且在此请求上调用
http.Client.Do
不会发送正确的数据包。克隆请求没有帮助。

所以这是我的问题:如何获取我要发送(或刚刚发送)的请求的大小(以字节为单位)?对于 HTTPS 连接也可以这样做吗?

go http https metrics telemetry
1个回答
0
投票

要监视正在发送或已发送的请求的大小,您可以创建

http.RoundTripper
的自定义实现,以拦截请求和响应并计算大小。请检查示例代码:

import (
    "bytes"
    "fmt"
    "io"
    "net/http"
)

type SizeTrackingTransport struct {
    Transport http.RoundTripper
}

func (t *SizeTrackingTransport) RoundTrip(req *http.Request) (*http.Response, error) {
    // Capture request body
    var requestBody bytes.Buffer
    if req.Body != nil {
        _, err := io.Copy(&requestBody, req.Body)
        if err != nil {
            return nil, err
        }
    }

    // Create a clone of the request to send it later
    clonedReq := req.Clone(req.Context())
    clonedReq.Body = io.NopCloser(&requestBody)

    // Send the cloned request using the provided Transport
    resp, err := t.Transport.RoundTrip(clonedReq)
    if err != nil {
        return nil, err
    }

    // Capture response body
    var responseBody bytes.Buffer
    if resp.Body != nil {
        _, err := io.Copy(&responseBody, resp.Body)
        if err != nil {
            return nil, err
        }
    }

    // Calculate and print request and response sizes
    fmt.Printf("Request size: %d bytes\n", requestBody.Len())
    fmt.Printf("Response size: %d bytes\n", responseBody.Len())

    // Replace the original response body with the captured one
    resp.Body = io.NopCloser(&responseBody)

    return resp, nil
}

func main() {
    // Create a custom HTTP client with the SizeTrackingTransport
    client := &http.Client{
        Transport: &SizeTrackingTransport{
            Transport: http.DefaultTransport,
        },
    }

    // Example request
    req, _ := http.NewRequest("GET", "https://example.com", nil)

    // Send the request using the custom client
    _, err := client.Do(req)
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
}

此代码仅提供基本实现。根据您的需求,您可能需要对其进行改进。我希望这会有所帮助

© www.soinside.com 2019 - 2024. All rights reserved.