Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
3 tasks done
ngocchien opened this issue Oct 8, 2024 · 4 comments · May be fixed by #3231
Open
3 tasks done

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

ngocchien opened this issue Oct 8, 2024 · 4 comments · May be fixed by #3231
Assignees
Milestone

Comments

@ngocchien
Copy link

ngocchien commented Oct 8, 2024

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:

  • I agree to follow Fiber's Code of Conduct.
  • I have checked for existing issues that describe my questions prior to opening this one.
  • I understand that improperly formatted questions may be closed without explanation.
Copy link

welcome bot commented Oct 8, 2024

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
Copy link

@gaby

Look at this regarding to #3203

@michal-laskowski
Copy link

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)
}

@efectn
Copy link
Member

efectn commented Dec 4, 2024

It seems like EnableSplittingOnParsers has lost its functionality during the migration of the codebase from v2 to v3. We have to add app.config.EnableSplittingOnParsers condition again.

v2:

if c.app.config.EnableSplittingOnParsers && strings.Contains(v, ",") && equalFieldType(out, reflect.Slice, k, bodyTag) {
	values := strings.Split(v, ",")
	for i := 0; i < len(values); i++ {
		data[k] = append(data[k], values[i])
	}
} else {
	data[k] = append(data[k], v)
}

v3:

if strings.Contains(v, ",") && equalFieldType(out, reflect.Slice, k) {
	values := strings.Split(v, ",")
	for i := 0; i < len(values); i++ {
		data[k] = append(data[k], values[i])
	}
} else {
	data[k] = append(data[k], v)
}

Will work on the fix. Thanks for the bug report.

@efectn efectn added this to the v3 milestone Dec 5, 2024
@efectn efectn added this to v3 Dec 5, 2024
@efectn efectn self-assigned this Dec 5, 2024
@efectn efectn moved this to In Progress in v3 Dec 5, 2024
@efectn efectn linked a pull request Dec 5, 2024 that will close this issue
20 tasks
@efectn efectn linked a pull request Dec 5, 2024 that will close this issue
20 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: In Progress
Development

Successfully merging a pull request may close this issue.

3 participants