杜松子酒 - Go lang如何使用Context.Request.Body并保留它?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (27)

我正在尝试编写一个中间件,我将对请求体进行json模式验证。验证后,我需要再次使用请求体。但我无法弄清楚如何做到这一点。我在这篇文章中提到 了一种进入身体的方法。但是一旦使用了请求体,我需要可用于我的下一个功能。

以下是示例代码:

package main
import (
        "fmt"
        "io/ioutil"
        "net/http"
        "github.com/gin-gonic/gin"
        //"github.com/xeipuuv/gojsonschema"
)

func middleware() gin.HandlerFunc {
 return func(c *gin.Context) {

    //Will be doing json schema validation here

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

    fmt.Printf("%s \n", string(x))

    fmt.Println("I am a middleware for json schema validation")

    c.Next()
    return
 }
}    

type E struct {
 Email    string
 Password string
}

func test(c *gin.Context) {

 //data := &E{}
 //c.Bind(data)
 //fmt.Println(data)   //prints empty as json body is already used

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

 fmt.Printf("body is: %s \n", string(x))
 c.JSON(http.StatusOK, c)

}

func main() {

 router := gin.Default()

 router.Use(middleware())

 router.POST("/test", test)

 //Listen and serve
 router.Run("127.0.0.1:8080")

}

当前输出:

{“email”:“test@test.com”,“password”:“123”}我是json架构验证机构的中间件:

预期产量:

{“email”:“test@test.com”,“password”:“123”}我是json架构验证机构的中间件:{“email”:“test@test.com”,“password”:“ 123“}

提问于
用户回答回答于

如果你想多次使用身体内容并且你也使用gin-gonic,我认为这个ShouldBindBodyWith功能就是你想要的。

ShouldBindBodyWith与ShouldBindWith类似,但它将请求主体存储到上下文中,并在再次调用时重用。 注意:此方法在绑定之前读取正文。因此,如果您只需要调用一次,则应该使用ShouldBindWith以获得更好的性能。

参考文献:

用户回答回答于

您可以在中间件中复制req.Body。查看io.TeeReader + bytes.Buffer

据我所知,您无法直接复制io.Reader,因此您必须在阅读时复制它,然后将复制的一个复制回来以便c.Request.Body能够将其用于c.Bind

我不确定,但也许可以让事情变得更容易。

扫码关注云+社区

领取腾讯云代金券