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

Go HTTP中间件使用http.Client导致原HttpRequest.Body关闭的问题排查

问题原因分析与解决方案

问题核心

你遇到的http: invalid Read on closed Body错误,本质是原请求的r.Body在中间件执行c.Do(hReq)后被意外关闭,导致后续Handler无法读取请求体。结合代码和场景,可能的原因及解决方式如下:

可能原因

  1. 调试器干扰:GoLand调试时,查看r.Body的状态(如在Watch面板中观察)可能会触发隐式的读取或关闭操作,导致后续无法正常读取。
  2. 未正确处理HTTP客户端响应:虽然看似和原请求Body无关,但c.Do(hReq)后未关闭响应Body会导致连接池异常,间接影响当前请求的资源状态(概率较低,但属于最佳实践缺失)。
  3. 请求体的一次性读取特性:http.Request.Body是io.ReadCloser,本身只能被读取一次,若中间件或调试过程中存在隐式读取操作,会导致后续Handler无法再次读取(但你的代码中中间件未显式读取Body,更可能是调试器或库的隐式行为)。

解决方案

最可靠的解决方式是提前保存原请求体内容,重新创建可重复读取的Body对象,确保后续Handler能正常解析。同时修复HTTP客户端的响应处理逻辑,避免连接泄漏:

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

func (m *AuthorizeHandlerMiddleware) Handle(next http.HandlerFunc) http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request) {
        token := r.Header.Get("Authorization")
        if token == "" {
            res := types.Base{
                Code:    401,
                Message: "error",
            }
            logc.Error(r.Context(), "token is empty")
            httpx.OkJsonCtx(r.Context(), w, res)
            return
        }

        // 1. 保存原请求Body内容,重新创建可读取的Body
        var bodyBytes []byte
        if r.Body != nil {
            bodyBytes, _ = io.ReadAll(r.Body)
            r.Body.Close()
            // 用保存的字节重新生成一个可重复读取的ReadCloser
            r.Body = io.NopCloser(bytes.NewBuffer(bodyBytes))
        }

        hReq, err := http.NewRequest("GET", "http://localhost:801/admin/member/info", nil)
        if err != nil {
            logc.Error(r.Context(), err)
            return
        }
        // 2. 正确处理HTTP客户端响应,避免连接泄漏
        resp, err := http.DefaultClient.Do(hReq)
        if err != nil {
            logc.Error(r.Context(), err)
            return
        }
        defer resp.Body.Close()
        // 必须读取响应Body,否则连接无法被连接池复用
        _, _ = io.ReadAll(resp.Body)

        next(w, r)
    }
}

额外验证步骤

  • 关闭GoLand调试,直接运行程序,若错误消失,说明是调试器的隐式操作导致Body被关闭。
  • 检查httpx.Parse的实现,确认它不会在未读取的情况下提前关闭请求Body。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 18:15:03