gofiber / fiber

⚡️ Express inspired web framework written in Go
https://gofiber.io
MIT License
34.05k stars 1.68k forks source link

🤗 [Question]: How do we get multiple values for a key in form submission? #3159

Open ngocchien opened 1 month ago

ngocchien commented 1 month ago

Question Description

I have a field in my form, its name is the description

Example:

<input name="item" value="item1">
<input name="description" value="description1, this is a description for item one, the first item is very nice, bla bla bla">
<input name="item" value="item2">
<input name="description" value="description2">
<input name="item" value="item3">
<input name="description" value="description3">

On my server side, I define a struct with the information:

FormCreate struct {
        Item    []string                   `json:"item" form:"item"`
        Description  []string         `json:"description" form:"description"`
    }
formData = new(FormCreate)
c.Bind().Body(formData)

I have a problem with binding data from the form to my formData. My expectation data for formData.Description is []string{"description, this is a description for item one, the first item is very nice, bla bla bla", "description2", "description3"} (This has 3 values for the slice). But currently, I received for formData.Description after binding data is []string{"description1", "this is a description for item one", "the first item is very nice", "bla bla bla", "description2", "description3"} (This has 6 values for the slice).

It seems that the Bind() function has split the value of the description field of the first item into a slice by the "," , so I received the data for formData.Description is []string{"description1", "this is a description for item one", "the first item is very nice", "bla bla bla", "description2", "description3"}.

Who can resolve my problem? Thank you so much!

Code Snippet (optional)

package main

import "github.com/gofiber/fiber/v3"
import "log"

func main() {
  app := fiber.New()

  // An example to describe the question
  app.Post("/create-post", handleCreate) 
  log.Fatal(app.Listen(":3000"))
}

function handleCreate(c fiber.Ctx) error{
   FormCreate struct {
        Item    []string                   `json:"item" form:"item"`
        Description  []string         `json:"description" form:"description"`
    }
  var (
    formData = new(FormCreate)
  )
   if c.Method() == http.MethodPost {
    err = c.Bind().Body(formData)
   }

   return c.Render("index", fiber.Map{
        "formData": formData,
    })
}

Checklist:

welcome[bot] commented 1 month ago

Thanks for opening your first issue here! 🎉 Be sure to follow the issue template! If you need help or want to chat with us, join us on Discord https://gofiber.io/discord

michal-laskowski commented 1 week ago

@gaby

Look at this regarding to #3203

michal-laskowski commented 1 week ago

For JSON it will work

JSON test ``` // go test -v -run=^$ -bench=Test_Bind_Body_JSON_WithArray func Test_Bind_Body_JSON_WithArray(b *testing.T) { var err error app := New() c := app.AcquireCtx(&fasthttp.RequestCtx{}) type Demo struct { Item []string `json:"item" form:"item"` Description []string `json:"description" form:"description"` } body := []byte(`{"item":["item1","item2","item3" ], "description":["description1, with coma.","description2","description3" ] }`) c.Request().SetBody(body) c.Request().Header.SetContentType(MIMEApplicationJSON) c.Request().Header.SetContentLength(len(body)) d := new(Demo) err = c.Bind().Body(d) require.NoError(b, err) require.Equal(b, []string{"item1", "item2", "item3"}, d.Item) require.Equal(b, []string{"description1, with coma.", "description2", "description3"}, d.Description) } ```

For forms it will not work if you allow comma (,) in value.

Form test ``` // go test -v -run=^$ -bench=Test_Bind_Body_Form_WithArray func Test_Bind_Body_Form_WithArray(b *testing.T) { var err error app := New() c := app.AcquireCtx(&fasthttp.RequestCtx{}) type Demo struct { Item []string `json:"item" form:"item"` Description []string `json:"description" form:"description"` } body := []byte("item=item1&item=item2&item=item3&description=description1%2C%20with coma.&description=description2&description=description3&q=%2C") c.Request().SetBody(body) c.Request().Header.SetContentType(MIMEApplicationForm) c.Request().Header.SetContentLength(len(body)) d := new(Demo) err = c.Bind().Body(d) require.NoError(b, err) require.Equal(b, []string{"item1", "item2", "item3"}, d.Item) require.Equal(b, []string{"description1, with coma.", "description2", "description3"}, d.Description) } ```