diff --git a/ctx.go b/ctx.go index 4b54a8c3..230cf95f 100644 --- a/ctx.go +++ b/ctx.go @@ -341,10 +341,20 @@ func (c *Ctx) BodyParser(out interface{}) error { } if strings.HasPrefix(ctype, MIMEApplicationForm) { data := make(map[string][]string) + var err error + c.fasthttp.PostArgs().VisitAll(func(key, val []byte) { + if err != nil { + return + } + k := utils.UnsafeString(key) v := utils.UnsafeString(val) + if strings.Contains(k, "[") { + k, err = parseParamSquareBrackets(k) + } + if strings.Contains(v, ",") && equalFieldType(out, reflect.Slice, k) { values := strings.Split(v, ",") for i := 0; i < len(values); i++ { @@ -929,7 +939,7 @@ func (c *Ctx) QueryParser(out interface{}) error { v := utils.UnsafeString(val) if strings.Contains(k, "[") { - k, err = parseQuery(k) + k, err = parseParamSquareBrackets(k) } if strings.Contains(v, ",") && equalFieldType(out, reflect.Slice, k) { @@ -950,7 +960,7 @@ func (c *Ctx) QueryParser(out interface{}) error { return c.parseToStruct(queryTag, out, data) } -func parseQuery(k string) (string, error) { +func parseParamSquareBrackets(k string) (string, error) { bb := bytebufferpool.Get() defer bytebufferpool.Put(bb) diff --git a/ctx_test.go b/ctx_test.go index 0c1b3162..4c9d75ab 100644 --- a/ctx_test.go +++ b/ctx_test.go @@ -399,6 +399,30 @@ func Test_Ctx_BodyParser(t *testing.T) { testDecodeParserError("invalid-content-type", "") testDecodeParserError(MIMEMultipartForm+`;boundary="b"`, "--b") + + type CollectionQuery struct { + Data []Demo `query:"data"` + } + + c.Request().Reset() + c.Request().Header.SetContentType(MIMEApplicationForm) + c.Request().SetBody([]byte("data[0][name]=john&data[1][name]=doe")) + c.Request().Header.SetContentLength(len(c.Body())) + cq := new(CollectionQuery) + utils.AssertEqual(t, nil, c.BodyParser(cq)) + utils.AssertEqual(t, 2, len(cq.Data)) + utils.AssertEqual(t, "john", cq.Data[0].Name) + utils.AssertEqual(t, "doe", cq.Data[1].Name) + + c.Request().Reset() + c.Request().Header.SetContentType(MIMEApplicationForm) + c.Request().SetBody([]byte("data.0.name=john&data.1.name=doe")) + c.Request().Header.SetContentLength(len(c.Body())) + cq = new(CollectionQuery) + utils.AssertEqual(t, nil, c.BodyParser(cq)) + utils.AssertEqual(t, 2, len(cq.Data)) + utils.AssertEqual(t, "john", cq.Data[0].Name) + utils.AssertEqual(t, "doe", cq.Data[1].Name) } // go test -run Test_Ctx_BodyParser_WithSetParserDecoder