Golang

关注公众号 jb51net

关闭
首页 > 脚本专栏 > Golang > gin requestBody请求体取值

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

作者:goper

这篇文章主要介绍了gin自定义中间件解决requestBody不可重读,确保控制器能够获取请求体值,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

使用中间件

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

问题复现

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 body 绑定到不同的结构体中 | 示例 |《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.NopCloser(buffer)
            return closer, nil
        }
        body, _ := context.Request.GetBody()  // 每次调用GetBody方法,都会新生成一个io.ReadCloser,但是底层的byte数据,都是all变量缓存的。
        context.Request.Body = body
        context.Next()
    })

以上就是gin自定义中间件解决requestBody不可重读(请求体取值)的详细内容,更多关于gin requestBody请求体取值的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文