Go-Gin многократно читает тело запроса

Я пытаюсь восстановить контекст с его данными после выполнения проверки его данных. Мне нужно, чтобы данные продолжали двигаться по мере необходимости позже в следующей функции.

Я новичок в 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()

}

маршрут

auth.POST("login", gin.Logger(), validations.SignupValidator, func(ctx *gin.Context) {
            ctx.JSON(200, videoController.Save(ctx))
        })

person bihire boris    schedule 05.07.2020    source источник
comment
Что вы подразумеваете под восстановлением контекста?   -  person Зелёный    schedule 05.07.2020
comment
хорошо, когда я читаю контекст один раз во время проверки, я не могу снова прочитать эти данные, и мне нужно выполнить другие действия после этого промежуточного программного обеспечения проверки @Зелёный   -  person bihire boris    schedule 05.07.2020
comment
Вы можете читать body много раз, c.ShouldBindJSON как раз об этом. Покажите ошибку, которая у вас есть.   -  person Зелёный    schedule 05.07.2020
comment
ошибка возникает после c.ShouldBindJSON, если вы попытаетесь получить доступ к данным в контексте, они будут пустыми. из этого тот же вопрос @Зелёный   -  person bihire boris    schedule 05.07.2020
comment
Пожалуйста, покажите полное сообщение об ошибке.   -  person Зелёный    schedule 05.07.2020
comment
Я отредактировал код, попытался записать данные контекста. зацени @Зеленый   -  person bihire boris    schedule 05.07.2020


Ответы (2)


Вот пример двойного чтения тела с ShouldBindBodyWith, отметьте Это:

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}
person Зелёный    schedule 05.07.2020
comment
то, что я пытаюсь сказать, не сработает. потому что вы не можете прочитать буфер дважды, и вы уже прочитали его с помощью ShouldBindJSON. попробуйте запустить это, если возможно, чтобы увидеть, печатает ли он что-то, потому что это не на моей стороне. - person bihire boris; 05.07.2020
comment
Для других читателей: ShouldBindJSON и ShouldBindBodyWith ведут себя по-разному. Вы не можете позвонить ShouldBindJSON дважды, но ShouldBindBodyWith не столкнется с одной и той же проблемой. Если вам действительно нужно вручную прочитать тело дважды, ответ @spehlivan ниже должен помочь. - person Mic Fok; 25.03.2021

Вы можете попробовать это.

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

Затем вы можете использовать ByteBody, как хотите, без побочных эффектов на c.Request.Body

person spehlivan    schedule 21.01.2021