猿问

如何使用 RoundTrip 跟踪请求大小?

为潜在的新手问题道歉,但我正在改编别人的代码并且不熟悉 Go 语言。


在代理 http 请求的代码中,我有以下部分


func handleHTTP(w http.ResponseWriter, req *http.Request) {

    resp, err := http.DefaultTransport.RoundTrip(req)

..

我知道 req 包括一个流式主体,因此没有立即可用的长度,因为我希望 RoundTrip 读取这样的流。我的问题是如何调整这样的代码,以便在流完全消耗后获得请求正文的最终大小......


谢谢


斯蒂芬大帝
浏览 125回答 2
2回答

摇曳的蔷薇

Request有 aContentLength作为可用属性,在某些情况下您可能只能使用它。虽然如果请求使用传输编码,我认为这个值设置为 -1(可能为 0)。否则我认为你可以用你自己的 io.ReadCloser 实现包装 req.Body 。像这样:type RecordLengthReadCloser struct {    io.ReadCloser    length     int}func (rc *RecordLengthReadCloser) Read(p []byte) (int, error) {    n, err := rc.ReadCloser.Read(p)    rc.length += n    return n, err}func handleHTTP(w http.ResponseWriter, req *http.Request) {    rc := &RecordLengthReadCloser{ReadCloser: req.Body}    req.Body = rc    resp, err := http.DefaultTransport.RoundTrip(req)    fmt.Println(rc.length)    _, _ = resp, err}这可能有我不知道的问题,我不确定你是否可以自由地重新分配 req.Body 没有问题。

人到中年有点甜

http.Request.Body是类型io.ReadCloser。它是一个interface,您可以利用它来用您自己的实现来包装 Body 值,io.ReadCloser该实现计算从中读取的字节数。package main_testimport (    "fmt"    "io"    "io/ioutil"    "log"    "net/http"    "net/http/httptest"    "strings"    "testing")func TestRequestLen(t *testing.T) {    reqBody := "Hello world!"    resBody := "Hello, client"    ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {        fmt.Fprint(w, resBody)    }))    defer ts.Close()    req, err := http.NewRequest(http.MethodGet, ts.URL, strings.NewReader(reqBody))    if err != nil {        log.Fatal(err)    }    req.Body = &bytesRead{ReadCloser: req.Body}    res, err := http.DefaultClient.Do(req)    if err != nil {        log.Fatal(err)    }    greeting, err := ioutil.ReadAll(res.Body)    res.Body.Close()    if err != nil {        log.Fatal(err)    }    if want := resBody; string(greeting) != want {        t.Fatalf("invalid response body %q want %q", string(greeting), want)    }    if want := len(reqBody); req.Body.(*bytesRead).total != want {        t.Fatalf("invalid request length %v want %v", req.Body.(*bytesRead).total, want)    }}type bytesRead struct {    io.ReadCloser    total int}func (c *bytesRead) Read(p []byte) (n int, err error) {    n, err = c.ReadCloser.Read(p)    c.total += n    return}
随时随地看视频慕课网APP

相关分类

Go
我要回答