开发者

gin自定义中间件解决requestBody不可重读(请求体取值)

开发者 https://www.devze.com 2023-11-21 12:26 出处:网络 作者: goper
目录使用中间件问题复现其他方式解决方案方法一:使用context.ShouldBindBodyWith() (推荐) 方法二:使用context.Set()/Get()方法三:读取body内容参考总结方式使用js中间件
目录
  • 使用中间件
  • 问题复现
  • 其他方式解决方案
    • 方法一:使用context.ShouldBindBodyWith() (推荐)
    •  方法二:使用context.Set()/Get()
    • 方法三:读取body内容
  • 参考总结方式

    使用js中间件

    注意,这个中间件,需要在第一个执行。

    问题复现

    type Test struct {
        Test string `json:"test"`
    }
    func main() {
        ginServer := gin.Default()
        ginServer.POST("/test", func(ctx *gin.Context) {
            //中间件取值
            var test Test
            ctx.BindJSON(&test)
            fmt.Printf("inteceptor %v\n", test)
            ctx.Next()
        }, func(ctx *gin.Context) {
            //controller取值
            var test Test
            ctx.BindJSON(&test)
            fmt.Printf("controller %v\n", test)
        })
    }

    结果

    【中间件】从request.body里取值后,【controller】会取不到值 

    其他方式解决方案

    方法一:使用context.ShouldBindBodyWith() (推荐)

    个人推荐这个方法,更简单

    官网详细文档:将 request bodjavascripty 绑定到不同的结构体中 | 示例 |《Gin 框架中文文档 1.7》| Go 技术论坛 (learnku.com)

    用例:

    ctx.ShouldBindBodyWith(&test,binding.JSON)

    测试完整代码:

    type Test struct {
        Test string `json:"test"`
    }
    func main() {
        ginServer := gin.Default()
        ginServer.POST("/test", func(ctx *gin.Context) {
            //中间件取值
            var test Test
            //修改此处
            ctx.ShouldBindBodyWith(&test, binding.JSON)
            fmt.Printf("inteceptor %v\n", test)
            ctx.Next()
        }, func(ctx *gin.Context) {
            //controller取值
            var test Test
            //修改此处
            ctx.ShouldBindBodyWith(&test, binding.JSON)
            fmt.Printf("controller %v\n", test)
        })
    }
           

     方法二:使用context.Set()/Get()

    也可以使用【Session】或者其他方式完成,思路就是取完又存

    具体详看: 

    Gin:Session

    //中间件存值
    func(ctx *gin.Context) {
            var test Test
            ctx.BindJSON(&test)
            ctx.Set("test", test)
            ctx.Next()
    }
    //controller取值
    func(ctx *gin.Context) {
            var test Test
            value, _ := ctx.Get("test")
            test=value.(Test)
            fmt.Printf("controller %v\n", test)
    }
        

    方法三:读取body内容

     思路同样是取完又存

    读取:

    data, _ := ioutil.ReadAll(c.Request.Body)

    bind对象:var data model.Post

    c.BindJSON(&data)

    写入:

    c.Request.Body = ioutil.NopCloser(bytes.NewBuffer(data))

    参考总结方式

    r := gin.Default()
        // 注册中间件,使body可以重复读取
        r.Use(func(context *gin.Context) {
            all, err := context.GetRawData() // 读取body的内容
            if err != nil {
                log.Fatal(err)
            }
            // 重写 GetBody 方法,以便后续的其他操作
            context.Request.GetBody = func() (io.ReadCloser, error) {
                context.Request.Body = io.NopCloser(bytes.NewBuffer(all))
                buffer := bytes.NewBuffer(all)
                closer := io.NjavascriptopCloser(buffer)
                return closer, nil
            }
            body, _ := context.Request.GetBody()python  // 每次调用GetBody方法,都会新生成一个io.ReadCloser,但是底层的byte数据,都是all变量缓存的。
            context.Request.Body = body
            context.Next()
        })

    以上就是gin自定义中间件解决requestBody不可重读(请求体取值)的详细内容,更多关于gin requestBody请求体取值的资料请关注编程客栈(www.devze.com)其编程客栈它相关文章!

    0

    精彩评论

    暂无评论...
    验证码 换一张
    取 消