如何使用 Context.Request.Body 并保留它?

我正在尝试编写一个中间件,我将对请求正文进行 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"


I am a middleware for json schema validation

body is: 

预期输出:


{

    "email": "test@test.com",

    "password": "123"

I am a middleware for json schema validation

body is: {

    "email": "test@test.com",

    "password": "123"

}


慕森王
浏览 181回答 3
3回答

天涯尽头无女友

Thellimist 所说的,不过是更多的话。你需要“抓住并恢复”身体。Body 是一个缓冲区,这意味着一旦你阅读它,它就消失了。所以,如果你抓住它并“把它放回去”,你就可以再次访问它。

眼眸繁星

您可以在中间件中复制 req.Body。查看io.TeeReader + bytes.Buffer。据我所知,您不能直接复制 io.Reader,因此您必须在阅读时复制它,然后将复制的副本分配回以便c.Request.Body能够将其用于c.Bind我不确定,但也许这可以让事情变得更容易。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go