Go 多次阅读请求正文

Go 多次阅读请求正文,go,go-gin,Go,Go Gin,在对其数据执行验证后,我正在尝试使用其数据还原上下文。我需要数据在下一个函数中继续移动 我是刚来golang的新手,下面的代码是我能做到的。我们非常感谢任何帮助和更好的方法 提前谢谢 验证中间件 func SignupValidator(c *gin.Context) { // Read the Body content // var bodyBytes []byte // if c.Request.Body != nil { // bodyBytes, _ =

在对其数据执行验证后,我正在尝试使用其数据还原上下文。我需要数据在下一个函数中继续移动

我是刚来golang的新手,下面的代码是我能做到的。我们非常感谢任何帮助和更好的方法

提前谢谢

验证中间件

func SignupValidator(c *gin.Context) {
    // Read the Body content
    // var bodyBytes []byte
    // if c.Request.Body != nil {
    //  bodyBytes, _ = ioutil.ReadAll(c.Request.Body)
    // }
    var user entity.User
    if err := c.ShouldBindJSON(&user); err != nil {
         validate := validator.New()
         if err := validate.Struct(&user); err != nil {
              c.JSON(http.StatusBadRequest, gin.H{
                 "error": err.Error(),
          })
          c.Abort()
          return
        }
        // c.Request.Body = ioutil.NopCloser(bytes.NewBuffer(bodyBytes))
    }
    // Read the Body content
    var bodyBytes []byte
    if c.Request.Body != nil {
        bodyBytes, _ = ioutil.ReadAll(c.Request.Body)
    }
    fmt.Println(string(bodyBytes)) // this empty
    c.Next()

}
路线


下面是一个使用两次读取正文的示例,请检查:

package main

import (
    "log"
    "net/http"

    "github.com/gin-gonic/gin"
    "github.com/gin-gonic/gin/binding"
)

type ParamsOne struct {
    Username string `json:"username"`
}

type ParamsTwo struct {
    Username string `json:"username"`
}

func main() {
    r := gin.New()
    r.POST("/", func(c *gin.Context) {
        var f ParamsOne
        // Read ones
        if err := c.ShouldBindBodyWith(&f, binding.JSON); err != nil {
            log.Printf("%+v", err)
        }
        log.Printf("%+v", f)
        var ff ParamsTwo
        
        if err := c.ShouldBindBodyWith(&ff, binding.JSON); err != nil {
            log.Printf("%+v", err)
        }
        log.Printf("%+v", ff)
        c.IndentedJSON(http.StatusOK, f)
    })
    r.Run(":4000")
}
输出:

$example: ./example
[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
 - using env:   export GIN_MODE=release
 - using code:  gin.SetMode(gin.ReleaseMode)

[GIN-debug] POST   /                         --> main.main.func1 (1 handlers)
[GIN-debug] Listening and serving HTTP on :4000
2020/07/05 10:47:03 {Username:somename}
2020/07/05 10:47:03 {Username:somename}
你可以试试这个

ByteBody, _ := ioutil.ReadAll(c.Request.Body)
c.Request.Body = ioutil.NopCloser(bytes.NewBuffer(ByteBody))

然后,您可以随心所欲地使用ByteBody,而不会对
c.Request.Body

恢复上下文是什么意思?当我在执行验证时读取一次上下文时,我无法再次读取该数据,我需要在该验证中间件之后执行其他操作@你可以多次读取正文,c.ShouldBindJSON就是这样。显示您的错误。错误在c.ShouldBindJSON之后。如果您尝试访问上下文中的数据,它将为空。从这里,请显示完整的错误信息。我想说的是,它不起作用。因为您不能读取缓冲区两次,而且您已经使用
ShouldBindJSON
读取了缓冲区。如果可能的话,试着运行它,看看它是否打印了什么,因为它不在我这边。对于其他读者:
ShouldBindJSON
ShouldBindBodyWith
的行为不同。您不能调用
ShouldBindJSON
两次,但是
ShouldBindBodyWith
不会遇到相同的问题。如果你真的需要手动读取正文两次,@spehlivan下面的回答应该可以做到这一点。
ByteBody, _ := ioutil.ReadAll(c.Request.Body)
c.Request.Body = ioutil.NopCloser(bytes.NewBuffer(ByteBody))