在 Gin 中间件中使用 io.NopCloser 覆盖 c.Request.Body 是否会导致潜在的数据泄漏?

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

我正在 Gin 中编写一个中间件来记录请求正文以进行调试。为了多次读取正文,我需要使用 io.NopCloser 重新分配 c.Request.Body。这是我当前的实现:

return func(c *gin.Context) {
    bodyBytes, _ := io.ReadAll(c.Request.Body)
    _ = c.Request.Body.Close()
    
    // Override the Close method of c.Request.Body
    c.Request.Body = io.NopCloser(bytes.NewBuffer(bodyBytes))

    var bodyJSON map[string]interface{}
    err := json.Unmarshal(bodyBytes, &bodyJSON)
    if err != nil {
        c.Next()
        return
    }

    logrus.WithFields(logrus.Fields{
        "method": c.Request.Method + "-request",
        "path":   c.Request.URL.Path,
        "query":  c.Request.URL.RawQuery,
        "body":   bodyJSON,
    }).Info()

    c.Next() 
}

我担心 io.NopCloser 的使用,它会覆盖请求正文的

Close()
方法。这是否会导致数据泄漏,因为原始
Close()
方法被无操作
Close()
方法覆盖,并且在我将请求正文传递给另一个中间件后不执行任何操作来“关闭”请求正文?

我对 Golang 中的 IO 工作还比较陌生,所以我很感激任何关于更好方法的见解或建议。

go http io go-gin
1个回答
0
投票

对于服务器请求,您不需要关闭正文

服务器将关闭请求正文。 HTTP 服务 处理程序不需要。

对于客户端请求,由于 HTTP 实现的特殊性,您需要关闭正文。当您需要副本时,应在可用时使用

Request.GetBody

您的代码与Gin中间件示例代码非常相似

    body, err := ioutil.ReadAll(r.Body)
    if err != nil {
        return "", err
    }
    r.Body = ioutil.NopCloser(bytes.NewBuffer(body))

所以我认为没问题。 “数据泄漏”主要是资源泄漏,因为垃圾收集器可以防止内存泄漏。您可能泄漏的是不必要的使用资源,例如您不再需要的数据库连接或不会终止的 goroutine。这里不存在这样的问题。

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