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

如何在Go中流式读取请求Body并写入新请求Body?

如何在Golang中流式转发HTTP请求Body而不全部读入内存?

看你现在是把请求Body一次性全读进内存再转发,代码是这样的:

// read all bytes from body
bytes, err := ioutil.ReadAll(request.Body)
// set the bytes as NewReader to new request.body
request, err := http.NewRequest(http.MethodPut, url, bytes.NewReader(bytes))

这种做法在处理大文件上传或者大请求体的时候,很容易吃满内存,其实流式转发的实现非常直接,核心就是直接复用原始请求的Body(它本身就是io.Reader接口),不过有几个细节得留意,我给你拆解一下:

核心实现:直接流式转发

// 直接把原始请求的Body传给新请求,不用读进内存
newReq, err := http.NewRequest(http.MethodPut, targetURL, request.Body)
if err != nil {
    // 出错时记得先关闭原始Body,避免资源泄漏
    request.Body.Close()
    return err
}

// 复制原始请求的所有请求头,尤其是Content-Length这类和Body相关的头
newReq.Header = request.Header.Clone()

// 发送请求
client := &http.Client{}
resp, err := client.Do(newReq)
if err != nil {
    // 请求发送失败的话,同样要手动关闭原始Body
    request.Body.Close()
    return err
}
// 后续处理响应...

特殊场景:需要保留原始请求Body的情况

如果你的业务逻辑中,在转发之后还需要读取原始请求的Body内容,那直接传原始Body就不行了(因为io.Reader是一次性的,读完就没了),这时候可以用io.TeeReader来同时实现流式转发和内容缓存:

// 创建一个buffer用来缓存原始Body内容
bodyBuf := &bytes.Buffer{}
// TeeReader会在读取原始Body的同时,把内容写入bodyBuf
teeReader := io.TeeReader(request.Body, bodyBuf)

// 用teeReader作为新请求的Body,实现流式转发
newReq, err := http.NewRequest(http.MethodPut, targetURL, teeReader)
if err != nil {
    request.Body.Close()
    return err
}
newReq.Header = request.Header.Clone()

// 发送请求
client := &http.Client{}
resp, err := client.Do(newReq)
if err != nil {
    request.Body.Close()
    return err
}

// 现在bodyBuf里就保存了原始请求的Body内容,可以后续使用
originalBodyBytes := bodyBuf.Bytes()

// 最后别忘了关闭原始Body
request.Body.Close()

几个关键注意点

  • 资源泄漏问题:不管请求成功还是失败,都要确保原始请求的Body被关闭,否则会占用连接资源
  • 请求头复制:一定要复制原始请求的Header,特别是Content-Length、Content-Type这些和Body相关的头,不然新请求可能无法正确解析Body
  • 分块编码兼容:如果原始请求没有设置Content-Length,HTTP客户端会自动使用分块编码(Transfer-Encoding: chunked)来流式发送,不需要额外处理

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 09:28:21