You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Golang中HTTP Client RoundTripper为Payload添加多余外层对象求助

问题解决:Go HTTP Client自定义RoundTripper中Payload看似被多包裹一层的问题

问题现象

使用Go的HTTP Client时,传入http.NewRequest的Payload是{"message":"Hello, world!"},但在自定义RoundTripper里打印Payload时,显示为{{"message":"Hello, world!"}},误以为Payload被多包裹了一层。

原因分析

问题出在错误的打印方式:代码中直接用%s格式化req.Body,而req.Body是io.ReadCloser类型(此处实际为*bytes.Buffer),*bytes.Buffer的String()方法返回格式为{buf},其中buf是实际的JSON内容,所以打印出来会呈现{{...}}的样子。实际发送的请求Payload并没有被多包裹,只是打印显示错误。

正确解决方案

要正确获取并打印请求Body的内容,需要先读取req.Body的字节数据,读取完成后要重新设置Body(因为读取后Body的读取指针会移到末尾,后续的RoundTripper无法再读取)。

修改后的代码

package main

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

type Object struct {
    Message string `json:"message"`
}

type myRoundTripper struct {
    roundTripper http.RoundTripper
}

func (rt *myRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
    // 读取Body内容
    bodyBytes, err := io.ReadAll(req.Body)
    if err != nil {
        return nil, err
    }
    // 重新设置Body,确保后续RoundTripper能正常读取
    req.Body = io.NopCloser(bytes.NewBuffer(bodyBytes))
    
    fmt.Printf("2. Payload in RoundTrip: %s\n", string(bodyBytes))
    return rt.roundTripper.RoundTrip(req)
}

func main() {
    object := Object{
        Message: "Hello, world!",
    }

    payload, err := json.Marshal(object)
    if err != nil {
        panic(err)
    }

    fmt.Printf("1. Original Payload: %s\n", string(payload))

    client := &http.Client{
        Transport: &myRoundTripper{
            roundTripper: http.DefaultTransport,
        },
    }

    req, err := http.NewRequest(http.MethodPost, "http://localhost:8080/", bytes.NewBuffer(payload))
    if err != nil {
        panic(err)
    }
    req.Header.Add("Content-Type", "application/json")

    res, err := client.Do(req)
    if err != nil {
        panic(err)
    }

    fmt.Printf("Response: %v\n", res)
}

验证输出

运行修改后的代码,输出会显示正确的Payload:

$ go run main.go
1. Original Payload: {"message":"Hello, world!"}
2. Payload in RoundTrip: {"message":"Hello, world!"}
Response: &{200 OK 200 HTTP/1.1 1 1 map[Content-Length:[240] Content-Type:[text/plain; charset=utf-8] Date:[Sun, 27 Oct 2024 16:24:31 GMT] Status:[200 OK]] 0xc000034140 240 [] false false map[] 0xc0000de360 <nil>}

注意事项

  • 读取req.Body后必须重新设置,否则后续的HTTP传输会因为Body已被读取完毕而无法发送正确的请求内容。
  • 使用io.NopCloser包装bytes.Buffer,因为http.Request.Body要求是io.ReadCloser类型,bytes.Buffer只有io.Reader,NopCloser会给它添加一个空的Close()方法。

内容的提问来源于stack exchange,提问作者Yasuhiro Yamazaki

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 22:13:22