How to rewrite the response body and empty the original content in the middleware?

huangapple go评论101阅读模式
英文:

How to rewrite the response body and empty the original content in the middleware?

问题

希望输出替换数据,但是尝试后输出的是原始数据+替换数据或者没有输出。

我想在中间件中重写响应体,只想输出替换数据,参考如何在中间件中重写响应体?,我修改了我的代码如下:

请求被路由到:

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

中间件是:

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("替换数据"))
		//c.Data(http.StatusOK, "text/plain", []byte("替换数据"))
	}
}

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

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

当上述代码被修改后,所有的[]bytes都无法输出。
但是当注释掉以下部分时,参考被更改为如何在路由器中间件之后获取响应体?

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

将同时输出原始数据+替换数据。但是要求只输出替换数据

英文:

Hope to output replace data, but output origin data+replace data or no output after trying

I want to rewrite response body in middleware,Only want to output replace data,Refer to How to rewrite response body in middleware?, modify my code as
Requests are routed to

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

Middleware is

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)
}

When the above code is modified, all [] bytes cannot be output.
But the reference is changed to how do i get response body in after router middleware?
when commenting:

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

Will output origin data+replace data at the same time. But the requirement is to output replace data

答案1

得分: 1

你不能撤销对r.ResponseWriter的写入。在确定要发送给客户端的内容之前,不要调用ResponseWriter.Write。

ToolsGroupPermission应该从缓冲区复制到c.Writer,或者调用c.Data。如果你计划替换响应,其他处理程序不应该访问原始的ResponseWriter:

func ToolsGroupPermission() gin.HandlerFunc {
    return func(c *gin.Context) {
        buf := &bytes.Buffer{}
        rw := c.Writer        
        c.Writer = buf

        c.Next()

        var replaceResponse bool

        if replaceResponse {
            c.Data(http.StatusOK, "text/plain", []byte("replace data"))
        } else {
            // TODO: Copy header and status code somehow. I'm not familiar enough with gin to know how to do that nicely.
            io.Copy(rw, buf)
        }
    }
}
英文:

You cannot take back what you have written to r.ResponseWriter. Don't call ResponseWriter.Write before you know what you want to send to the client.

ToolsGroupPermission should either copy from the buffer to c.Writer, or call c.Data. There is no reason to even have the toolBodyWriter type; other handlers shouldn't have access to the original ResponseWriter if you plan to replace the response:

func ToolsGroupPermission() gin.HandlerFunc {
    return func(c *gin.Context) {
        buf := &bytes.Buffer{}
        rw := c.Writer        
        c.Writer = buf

        c.Next()

        var replaceResponse bool

        if replaceResponse {
            c.Data(http.StatusOK, "text/plain", []byte("replace data"))
        } else {
            // TODO: Copy header and status code somehow. I'm not familiar enough with gin to know how to do that nicely.
            io.Copy(rw, buf)
        }
    }
}

答案2

得分: 0

package middleware

import (
	"bytes"
	"fmt"
	"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()

		originBytes := wb.body
		fmt.Printf("%s", originBytes)
		// clear Origin Buffer
		wb.body = &bytes.Buffer{}
		wb.Write([]byte("替换的数据"))
		wb.ResponseWriter.Write(wb.body.Bytes())
		//c.Data(http.StatusOK, "text/plain", []byte("替换的数据"))
	}
}

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

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

或者

package middleware

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

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

		c.Next()
		wb.status = Replace
		originBytes := wb.body
		fmt.Printf("%s", originBytes)
		// clear Origin Buffer
		wb.body = &bytes.Buffer{}
		wb.Write([]byte("替换的数据"))
		//c.Data(http.StatusOK, "text/plain", []byte("替换的数据"))
	}
}

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

const (
	Origin  byte = 0x0
	Replace      = 0x1
)

func (r toolBodyWriter) Write(b []byte) (int, error) {
	if r.status == 0x1 {
		r.body.Write(b)
		return r.ResponseWriter.Write(b)
	} else {
		return r.body.Write(b) //r.ResponseWriter.Write(b)
	}
}
英文:
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()

        originBytes := wb.body
		fmt.Printf("%s", originBytes)
        // clear Origin Buffer
		wb.body = &bytes.Buffer{}
		wb.Write([]byte("replace data"))
        wb.ResponseWriter.Write(wb.body.Bytes())
        //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)
}

Or

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,
            status:         Origin,
        }
        c.Writer = wb

        c.Next()
        wb.status = Replace
        originBytes := wb.body
		fmt.Printf("%s", originBytes)
        // clear Origin Buffer
		wb.body = &bytes.Buffer{}
		wb.Write([]byte("replace data"))
        //c.Data(http.StatusOK, "text/plain", []byte("replace data"))
    }
}

type toolBodyWriter struct {
    gin.ResponseWriter
    body *bytes.Buffer
    status byte
}
const (
	Origin  byte = 0x0
	Replace      = 0x1
)

func (r toolBodyWriter) Write(b []byte) (int, error) {
    if r.status == 0x1 {
	    r.body.Write(b)
	 	return r.ResponseWriter.Write(b)
	} else {
		return r.body.Write(b) //r.ResponseWriter.Write(b)
	}
}

huangapple
  • 本文由 发表于 2022年12月5日 23:03:32
  • 转载请务必保留本文链接:https://go.coder-hub.com/74690226.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定