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

如何在Gin中间件中重写响应体并清空原有内容?

Gin中间件重写响应体:仅输出替换内容的解决方案

问题场景

在Gin框架中使用中间件重写响应体时,遇到两种异常情况:

  • 若自定义Writer的Write方法仅写入缓存buffer,最终无任何内容输出
  • 若Write方法同时写入buffer和原始ResponseWriter,会同时输出原始内容origin data和替换内容replace data

原始路由配置:

ToolsGroup := Router.Group("")
ToolsGroup.Use(middleware.ToolsGroupPermission())
{
    ToolsGroup.GET("/ptr", func(c *gin.Context) {
        c.Data(http.StatusOK, "text/plain", []byte("origin data"))
    })
}

原始中间件代码(无输出版本):

package middleware

import (
    "bytes"
    "github.com/gin-gonic/gin"
)

func ToolsGroupPermission() gin.HandlerFunc {
    return func(c *gin.Context) {
        wb := &toolBodyWriter{
            body:           &bytes.Buffer{},
            ResponseWriter: c.Writer,
        }
        c.Writer = wb

        c.Next()

        wb.body.Reset()
        wb.Write([]byte("replace data"))
        //c.Data(http.StatusOK, "text/plain", []byte("replace data"))
    }
}

type toolBodyWriter struct {
    gin.ResponseWriter
    body *bytes.Buffer
}

func (r toolBodyWriter) Write(b []byte) (int, error) {
    return r.body.Write(b)
}

解决方案

核心思路:拦截原始响应到buffer(不直接输出客户端),执行完业务逻辑后恢复原始ResponseWriter,再写入替换内容。

修正后的中间件代码:

package middleware

import (
    "bytes"
    "github.com/gin-gonic/gin"
)

func ToolsGroupPermission() gin.HandlerFunc {
    return func(c *gin.Context) {
        wb := &toolBodyWriter{
            body:           &bytes.Buffer{},
            ResponseWriter: c.Writer,
        }
        c.Writer = wb

        // 执行后续业务逻辑,原始响应会被写入buffer而非客户端
        c.Next()

        // 恢复原始ResponseWriter,确保内容直接输出到客户端
        c.Writer = wb.ResponseWriter
        // 清空未发送的响应头部,避免原始配置干扰
        c.Writer.WriteHeaderNow()
        // 设置正确的响应类型
        c.Writer.Header().Set("Content-Type", "text/plain")
        
        // 写入替换后的内容
        _, _ = c.Writer.Write([]byte("replace data"))
    }
}

type toolBodyWriter struct {
    gin.ResponseWriter
    body *bytes.Buffer
}

// 仅将内容写入buffer,不直接输出到客户端
func (r toolBodyWriter) Write(b []byte) (int, error) {
    return r.body.Write(b)
}

原理说明

  1. 自定义toolBodyWriter的Write方法只把原始响应存到buffer,不会直接发给客户端,避免原始内容泄露
  2. c.Next()完成业务逻辑后,恢复c.Writer为原始对象,保证后续写入直接输出到客户端
  3. 重置响应头部并写入替换内容,确保最终仅输出目标内容

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 22:31:12