Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

gin/golang - Empty Req Body

Tags:

go

go-gin

I'm new to Go and Gin, and am having trouble printing out the full request body.

I want to be able to read the request body from third party POST, but I'm getting empty request body

curl -u dumbuser:dumbuserpassword -H "Content-Type: application/json" -X POST --data '{"events": "3"}' http://localhost:8080/events

My entire code is as below. Any pointer is appreciated!

package main

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

func main() {
  router := gin.Default()
  authorized := router.Group("/", gin.BasicAuth(gin.Accounts{
     "dumbuser": "dumbuserpassword",
  }))
  authorized.POST("/events", events)
  router.Run(":8080")
}

func events(c *gin.Context) {
  fmt.Printf("%s", c.Request.Body)
  c.JSON(http.StatusOK, c)
}
like image 308
Leon Hu Avatar asked Aug 10 '15 04:08

Leon Hu


1 Answers

The problem here is that you're printing out the string value of c.Request.Body, which is of interface type ReadCloser.

What you can do to satisfy yourself that it does in fact contain the body you want is to read the value out of c.Request.Body to a string, and then print that out. This is for your learning process only!

Learning code:

func events(c *gin.Context) {
        x, _ := ioutil.ReadAll(c.Request.Body)
        fmt.Printf("%s", string(x))
        c.JSON(http.StatusOK, c)
}

However, this is not the way you should access the body of the request. Let gin do the parsing of the body for you, by using a binding.

More correct code:

type E struct {
        Events string
}

func events(c *gin.Context) {
        data := &E{}
        c.Bind(data)
        fmt.Println(data)
        c.JSON(http.StatusOK, c)
}

This is a more correct way to access the data in the body, since it will be already parsed out for you. Note that if you read the body first, as we did above in the learning step, the c.Request.Body will have been emptied, and so there will be nothing left in the body for Gin to read.

Broken code:

func events(c *gin.Context) {
    x, _ := ioutil.ReadAll(c.Request.Body)
    fmt.Printf("%s", string(x))
    data := &E{}
    c.Bind(data) // data is left unchanged because c.Request.Body has been used up.
    fmt.Println(data)
    c.JSON(http.StatusOK, c)
}

You're probably also curious why the JSON returned from this endpoint shows and empty Request.Body. This is for the same reason. The JSON Marshalling method cannot serialize a ReadCloser, and so it shows up as empty.

like image 183
Danver Braganza Avatar answered Nov 13 '22 09:11

Danver Braganza