杜松子酒如果`request body`绑定在中间件中,则c.Request.Body变为0

问题描述 投票:0回答:1

我的API服务器有中间件,它从请求头获取令牌。如果访问权限正确,则进入下一个功能。

但请求转到中间件并转到下一个功能,qazxsw poi成为qazxsw poi。

中间件

c.Request.Body

下一个功能

0

func getUserIdFromBody(c *gin.Context) (int) { var jsonBody User length, _ := strconv.Atoi(c.Request.Header.Get("Content-Length")) body := make([]byte, length) length, _ = c.Request.Body.Read(body) json.Unmarshal(body[:length], &jsonBody) return jsonBody.Id } func CheckToken() (gin.HandlerFunc) { return func(c *gin.Context) { var userId int config := model.NewConfig() reqToken := c.Request.Header.Get("token") _, resBool := c.GetQuery("user_id") if resBool == false { userId = getUserIdFromBody(c) } else { userIdStr := c.Query("user_id") userId, _ = strconv.Atoi(userIdStr) } ... if ok { c.Nex() return } } func bindOneDay(c *gin.Context) (model.Oneday, error) { var oneday model.Oneday if err := c.BindJSON(&oneday); err != nil { return oneday, err } return oneday, nil } 返回错误。因为也许bindOneDayEOF

我想从中间件的请求体获得c.Request.Body。如何做到没有问题,0成为0

go middleware gin
1个回答
3
投票

您只能从客户端读取一次Body。数据来自用户,他们不会再发送。如果你想多次阅读它,你将不得不在内存中缓冲整个事情,如下所示:

user_id

请注意,将整个请求缓冲到内存意味着用户可以让您分配无限内存 - 您应该在前端代理处阻止此操作,或使用c.Request.Body来限制您将缓冲的数据量。

你也必须在Unmarshal开始工作之前阅读整个身体 - 这可能没什么大不了的,但如果你这么倾向你可以用bodyCopy := new(bytes.Buffer) // Read the whole body _, err := io.Copy(bodyCopy, req.Body) if err != nil { return err } bodyData := bodyCopy.Bytes() // Replace the body with a reader that reads from the buffer req.Body = ioutil.NopCloser(bytes.NewReader(bodyData)) // Now you can do something with the contents of bodyData, // like passing it to json.Unmarshal io.LimitedReader做得更好。

当然,更好的方法是找出一种重构代码的方法,这样就不需要缓冲主体并对其进行两次解码。

© www.soinside.com 2019 - 2024. All rights reserved.