LoginSignup
11
3

More than 5 years have passed since last update.

Ginのリクエストボディはストリーム

Last updated at Posted at 2018-11-28

Ginで受け取れるリクエストボディはストリームなので、一度Readメソッドなどで読み出してしまうと空っぽになってしまう。従って、BindJSONなどのメソッドを読み出した後に使用するとEOFエラーが発生することがある。たとえば以下。

package main

import (
    "fmt"
    "github.com/gin-gonic/gin"
)

func main() {
    router := gin.New()

    router.POST("hoge", func(c *gin.Context) {
        buf := make([]byte, 2048)
        n, _ := c.Request.Body.Read(buf) // ここでRequest.Bodyを読み切ってしまっている
        b := string(buf[0:n])
        fmt.Println(b)

        var params RequestParams

        // BindJSONは内部でRequest.Bodyを再び読み出そうとするが
        // Request.Bodyはすでに読み出されて空になっているため、ここでEOFエラーになる
        if err := c.BindJSON(&params); err != nil {
            uc.Warningf("Failed binding request parameters: %s", err.Error())
            c.Status(http.StatusBadRequest)
            return
        }

        c.JSON(200, params)
    })

    router.Run()
}

対策としては、ioutil.NopCloserメソッドを使って読み出してしまったリクエストボディを書き戻すなど。

 buf := make([]byte, 2048)
 n, _ := c.Request.Body.Read(buf)
 b := string(buf[0:n])
 c.Request.Body = ioutil.NopCloser(bytes.NewBuffer([]byte(s)))
 fmt.Println(b)

11
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
3