mirror of https://github.com/gofiber/fiber.git
🩹 Fix: improper query/body parsing with embedded structs (#2906)
* added fix for embedded struct field query parsing * updated ctx parser tests to test embedded struct field parsing --------- Co-authored-by: Juan Calderon-Perez <835733+gaby@users.noreply.github.com>pull/2923/head
parent
df1f877cc0
commit
e25a31b731
|
@ -182,6 +182,24 @@ func equalFieldType(out any, kind reflect.Kind, key string) bool {
|
|||
structFieldKind := structField.Kind()
|
||||
// Does the field type equals input?
|
||||
if structFieldKind != kind {
|
||||
// Is the field an embedded struct?
|
||||
if structFieldKind == reflect.Struct {
|
||||
// Loop over embedded struct fields
|
||||
for j := 0; j < structField.NumField(); j++ {
|
||||
structFieldField := structField.Field(j)
|
||||
|
||||
// Can this embedded field be changed?
|
||||
if !structFieldField.CanSet() {
|
||||
continue
|
||||
}
|
||||
|
||||
// Is the embedded struct field type equal to the input?
|
||||
if structFieldField.Kind() == kind {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
// Get tag from field if exist
|
||||
|
|
19
ctx_test.go
19
ctx_test.go
|
@ -1358,7 +1358,12 @@ func Test_Ctx_Parsers(t *testing.T) {
|
|||
// setup
|
||||
app := New()
|
||||
|
||||
type TestEmbeddedStruct struct {
|
||||
Names []string `query:"names"`
|
||||
}
|
||||
|
||||
type TestStruct struct {
|
||||
TestEmbeddedStruct
|
||||
Name string
|
||||
Class int
|
||||
NameWithDefault string `json:"name2" xml:"Name2" form:"name2" cookie:"name2" query:"name2" params:"name2" header:"Name2"`
|
||||
|
@ -1377,13 +1382,14 @@ func Test_Ctx_Parsers(t *testing.T) {
|
|||
require.Equal(t, 111, testStruct.Class)
|
||||
require.Equal(t, "bar", testStruct.NameWithDefault)
|
||||
require.Equal(t, 222, testStruct.ClassWithDefault)
|
||||
require.Equal(t, []string{"foo", "bar", "test"}, testStruct.TestEmbeddedStruct.Names)
|
||||
}
|
||||
|
||||
t.Run("BodyParser:xml", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
withValues(t, func(c Ctx, testStruct *TestStruct) error {
|
||||
c.Request().Header.SetContentType(MIMEApplicationXML)
|
||||
c.Request().SetBody([]byte(`<TestStruct><Name>foo</Name><Class>111</Class><Name2>bar</Name2><Class2>222</Class2></TestStruct>`))
|
||||
c.Request().SetBody([]byte(`<TestStruct><Name>foo</Name><Class>111</Class><Name2>bar</Name2><Class2>222</Class2><Names>foo</Names><Names>bar</Names><Names>test</Names></TestStruct>`))
|
||||
return c.Bind().Body(testStruct)
|
||||
})
|
||||
})
|
||||
|
@ -1391,7 +1397,7 @@ func Test_Ctx_Parsers(t *testing.T) {
|
|||
t.Parallel()
|
||||
withValues(t, func(c Ctx, testStruct *TestStruct) error {
|
||||
c.Request().Header.SetContentType(MIMEApplicationForm)
|
||||
c.Request().SetBody([]byte(`name=foo&class=111&name2=bar&class2=222`))
|
||||
c.Request().SetBody([]byte(`name=foo&class=111&name2=bar&class2=222&names=foo,bar,test`))
|
||||
return c.Bind().Body(testStruct)
|
||||
})
|
||||
})
|
||||
|
@ -1399,14 +1405,14 @@ func Test_Ctx_Parsers(t *testing.T) {
|
|||
t.Parallel()
|
||||
withValues(t, func(c Ctx, testStruct *TestStruct) error {
|
||||
c.Request().Header.SetContentType(MIMEApplicationJSON)
|
||||
c.Request().SetBody([]byte(`{"name":"foo","class":111,"name2":"bar","class2":222}`))
|
||||
c.Request().SetBody([]byte(`{"name":"foo","class":111,"name2":"bar","class2":222,"names":["foo","bar","test"]}`))
|
||||
return c.Bind().Body(testStruct)
|
||||
})
|
||||
})
|
||||
t.Run("BodyParser:multiform", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
withValues(t, func(c Ctx, testStruct *TestStruct) error {
|
||||
body := []byte("--b\r\nContent-Disposition: form-data; name=\"name\"\r\n\r\nfoo\r\n--b\r\nContent-Disposition: form-data; name=\"class\"\r\n\r\n111\r\n--b\r\nContent-Disposition: form-data; name=\"name2\"\r\n\r\nbar\r\n--b\r\nContent-Disposition: form-data; name=\"class2\"\r\n\r\n222\r\n--b--")
|
||||
body := []byte("--b\r\nContent-Disposition: form-data; name=\"name\"\r\n\r\nfoo\r\n--b\r\nContent-Disposition: form-data; name=\"class\"\r\n\r\n111\r\n--b\r\nContent-Disposition: form-data; name=\"name2\"\r\n\r\nbar\r\n--b\r\nContent-Disposition: form-data; name=\"class2\"\r\n\r\n222\r\n--b\r\nContent-Disposition: form-data; name=\"names\"\r\n\r\nfoo\r\n--b\r\nContent-Disposition: form-data; name=\"names\"\r\n\r\nbar\r\n--b\r\nContent-Disposition: form-data; name=\"names\"\r\n\r\ntest\r\n--b--")
|
||||
c.Request().SetBody(body)
|
||||
c.Request().Header.SetContentType(MIMEMultipartForm + `;boundary="b"`)
|
||||
c.Request().Header.SetContentLength(len(body))
|
||||
|
@ -1416,14 +1422,14 @@ func Test_Ctx_Parsers(t *testing.T) {
|
|||
t.Run("CookieParser", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
withValues(t, func(c Ctx, testStruct *TestStruct) error {
|
||||
c.Request().Header.Set("Cookie", "name=foo;name2=bar;class=111;class2=222")
|
||||
c.Request().Header.Set("Cookie", "name=foo;name2=bar;class=111;class2=222;names=foo,bar,test")
|
||||
return c.Bind().Cookie(testStruct)
|
||||
})
|
||||
})
|
||||
t.Run("QueryParser", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
withValues(t, func(c Ctx, testStruct *TestStruct) error {
|
||||
c.Request().URI().SetQueryString("name=foo&name2=bar&class=111&class2=222")
|
||||
c.Request().URI().SetQueryString("name=foo&name2=bar&class=111&class2=222&names=foo,bar,test")
|
||||
return c.Bind().Query(testStruct)
|
||||
})
|
||||
})
|
||||
|
@ -1443,6 +1449,7 @@ func Test_Ctx_Parsers(t *testing.T) {
|
|||
c.Request().Header.Add("name2", "bar")
|
||||
c.Request().Header.Add("class", "111")
|
||||
c.Request().Header.Add("class2", "222")
|
||||
c.Request().Header.Add("names", "foo,bar,test")
|
||||
return c.Bind().Header(testStruct)
|
||||
})
|
||||
})
|
||||
|
|
Loading…
Reference in New Issue