Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Gin Gonic array of values from PostForm

Tags:

go

go-gin

I'm trying to capture an array of Post values from HTML form using Go / Gin Gonic -- in PHP I would use something like:

<form method="POST" enctype="multipart/form-data" action="mygo">
 <input type=hidden name="emails[]" value="[email protected]">
 <input type=hidden name="emails[]" value="[email protected]">
 <input type=hidden name="emails[]" value="[email protected]">
</form>

However this doesn't seem to work with Gin Gonic (or Go for that matter).

I've also tried:

<form method="POST" enctype="multipart/form-data" action="mygo">
 <input type=hidden name="emails" value="[email protected]">
 <input type=hidden name="emails" value="[email protected]">
 <input type=hidden name="emails" value="[email protected]">
</form>

As elsewhere it is suggested that doing this would cause c.PostForm("emails") to return a slice. However in practice it seems that this instead returns the last value as a string instead :(

Interestingly, c.Request.PostForm returns an empty map, even if c.Request.ParseForm() is called first. What am I doing wrong?

Go Form:

func main() {
// ...
    router.POST("mygo",parseFunc)
}

func mygo(c *gin.Context) {
  c.Request.ParseForm()
  log.Printf("%v",c.Request.PostForm["emails"]) // ""
  log.Printf("%v",c.PostForm("emails") // "[email protected]"
}
like image 900
BadPirate Avatar asked Oct 11 '16 18:10

BadPirate


3 Answers

In order to make it works you have two ways here

<form method="POST" enctype="multipart/form-data" action="mygo">
 <input type=hidden name="emails" value="[email protected]">
 <input type=hidden name="emails" value="[email protected]">
 <input type=hidden name="emails" value="[email protected]">
</form>

r.POST("/", func(c *gin.Context) {
        c.Request.ParseMultipartForm(1000)
        for key, value := range c.Request.PostForm {
            fmt.Println(key,value)
        }
    })

either

    <form method="POST" action="mygo">
     <input type=hidden name="emails" value="[email protected]">
     <input type=hidden name="emails" value="[email protected]">
     <input type=hidden name="emails" value="[email protected]">
    </form>

 r.POST("/", func(c *gin.Context) {
            c.Request.ParseForm()
            for key, value := range c.Request.PostForm {
                fmt.Println(key,value)
            }
        })

Both gives the same result

emails [[email protected] [email protected] [email protected]]
like image 115
Marsel Novy Avatar answered Nov 07 '22 15:11

Marsel Novy


With the latest version of gin-gonic (v1.2) you can just:

emails := c.PostFormArray("emails")

Then emails will be a []string.

Parse and iterate isn't more necessary.

like image 28
algorix Avatar answered Nov 07 '22 13:11

algorix


Issue with this code is two fold. Posting my answer in case someone else has either of these problems.

  1. c.Request.PostForm returns empty in this case because the form is multipart and ParseForm only parses non-multipart forms. In order to get the data here either change the form type to non-multipart or call ParseMultipartForm before accessing post values.
  2. c.PostForm() only returns the first value because thats what the wrapper in Gin Gonic does. In order to access all the values, it is necessary to access the original c.Request.PostForm data, and then AFTER you parse it properly.

Thanks @JimB for the assist.

like image 20
BadPirate Avatar answered Nov 07 '22 14:11

BadPirate