Skip to content

Commit

Permalink
🔥 add config to enable splitting by comma in parsers (#2560)
Browse files Browse the repository at this point in the history
* 🔥 add config to enable splitting by comma in parsers

🔥 add config to enable splitting by comma in parsers

* optimize if statements, remove escape char support

optimize if statements, remove escape char support

* update
  • Loading branch information
efectn authored Aug 21, 2023
1 parent e2f7457 commit 1dea615
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 10 deletions.
7 changes: 7 additions & 0 deletions app.go
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,13 @@ type Config struct {
//
// Optional. Default: DefaultMethods
RequestMethods []string

// EnableSplittingOnParsers splits the query/body/header parameters by comma when it's true.
// For example, you can use it to parse multiple values from a query parameter like this:
// /api?foo=bar,baz == foo[]=bar&foo[]=baz
//
// Optional. Default: false
EnableSplittingOnParsers bool `json:"enable_splitting_on_parsers"`
}

// Static defines configuration options when defining static assets.
Expand Down
6 changes: 3 additions & 3 deletions ctx.go
Original file line number Diff line number Diff line change
Expand Up @@ -396,7 +396,7 @@ func (c *Ctx) BodyParser(out interface{}) error {
k, err = parseParamSquareBrackets(k)
}

if strings.Contains(v, ",") && equalFieldType(out, reflect.Slice, k) {
if c.app.config.EnableSplittingOnParsers && 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])
Expand Down Expand Up @@ -1220,7 +1220,7 @@ func (c *Ctx) QueryParser(out interface{}) error {
k, err = parseParamSquareBrackets(k)
}

if strings.Contains(v, ",") && equalFieldType(out, reflect.Slice, k) {
if c.app.config.EnableSplittingOnParsers && 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])
Expand Down Expand Up @@ -1269,7 +1269,7 @@ func (c *Ctx) ReqHeaderParser(out interface{}) error {
k := c.app.getString(key)
v := c.app.getString(val)

if strings.Contains(v, ",") && equalFieldType(out, reflect.Slice, k) {
if c.app.config.EnableSplittingOnParsers && 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])
Expand Down
59 changes: 55 additions & 4 deletions ctx_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4082,7 +4082,7 @@ func Benchmark_Ctx_Queries(b *testing.B) {
// go test -run Test_Ctx_QueryParser -v
func Test_Ctx_QueryParser(t *testing.T) {
t.Parallel()
app := New()
app := New(Config{EnableSplittingOnParsers: true})
c := app.AcquireCtx(&fasthttp.RequestCtx{})
defer app.ReleaseCtx(c)
type Query struct {
Expand Down Expand Up @@ -4153,6 +4153,29 @@ func Test_Ctx_QueryParser(t *testing.T) {
utils.AssertEqual(t, 2, len(aq.Data))
}

// go test -run Test_Ctx_QueryParser -v
func Test_Ctx_QueryParser_WithoutSplitting(t *testing.T) {
t.Parallel()
app := New()
c := app.AcquireCtx(&fasthttp.RequestCtx{})
defer app.ReleaseCtx(c)
type Query struct {
ID int
Name string
Hobby []string
}

c.Request().URI().SetQueryString("id=1&name=tom&hobby=basketball,football")
q := new(Query)
utils.AssertEqual(t, nil, c.QueryParser(q))
utils.AssertEqual(t, 1, len(q.Hobby))

c.Request().URI().SetQueryString("id=1&name=tom&hobby=scoccer&hobby=basketball,football")
q = new(Query)
utils.AssertEqual(t, nil, c.QueryParser(q))
utils.AssertEqual(t, 2, len(q.Hobby))
}

// go test -run Test_Ctx_QueryParser_WithSetParserDecoder -v
func Test_Ctx_QueryParser_WithSetParserDecoder(t *testing.T) {
t.Parallel()
Expand Down Expand Up @@ -4311,7 +4334,7 @@ func Test_Ctx_QueryParser_Schema(t *testing.T) {
// go test -run Test_Ctx_ReqHeaderParser -v
func Test_Ctx_ReqHeaderParser(t *testing.T) {
t.Parallel()
app := New()
app := New(Config{EnableSplittingOnParsers: true})
c := app.AcquireCtx(&fasthttp.RequestCtx{})
defer app.ReleaseCtx(c)
type Header struct {
Expand Down Expand Up @@ -4380,6 +4403,34 @@ func Test_Ctx_ReqHeaderParser(t *testing.T) {
utils.AssertEqual(t, "failed to decode: name is empty", c.ReqHeaderParser(rh).Error())
}

// go test -run Test_Ctx_ReqHeaderParser -v
func Test_Ctx_ReqHeaderParser_WithoutSplitting(t *testing.T) {
t.Parallel()
app := New()
c := app.AcquireCtx(&fasthttp.RequestCtx{})
defer app.ReleaseCtx(c)
type Header struct {
ID int
Name string
Hobby []string
}
c.Request().SetBody([]byte(``))
c.Request().Header.SetContentType("")

c.Request().Header.Add("id", "1")
c.Request().Header.Add("Name", "John Doe")
c.Request().Header.Add("Hobby", "golang,fiber")
q := new(Header)
utils.AssertEqual(t, nil, c.ReqHeaderParser(q))
utils.AssertEqual(t, 1, len(q.Hobby))

c.Request().Header.Del("hobby")
c.Request().Header.Add("Hobby", "golang,fiber,go")
q = new(Header)
utils.AssertEqual(t, nil, c.ReqHeaderParser(q))
utils.AssertEqual(t, 1, len(q.Hobby))
}

// go test -run Test_Ctx_ReqHeaderParser_WithSetParserDecoder -v
func Test_Ctx_ReqHeaderParser_WithSetParserDecoder(t *testing.T) {
t.Parallel()
Expand Down Expand Up @@ -4604,7 +4655,7 @@ func Benchmark_Ctx_parseQuery(b *testing.B) {

// go test -v -run=^$ -bench=Benchmark_Ctx_QueryParser_Comma -benchmem -count=4
func Benchmark_Ctx_QueryParser_Comma(b *testing.B) {
app := New()
app := New(Config{EnableSplittingOnParsers: true})
c := app.AcquireCtx(&fasthttp.RequestCtx{})
defer app.ReleaseCtx(c)
type Query struct {
Expand All @@ -4630,7 +4681,7 @@ func Benchmark_Ctx_QueryParser_Comma(b *testing.B) {

// go test -v -run=^$ -bench=Benchmark_Ctx_ReqHeaderParser -benchmem -count=4
func Benchmark_Ctx_ReqHeaderParser(b *testing.B) {
app := New()
app := New(Config{EnableSplittingOnParsers: true})
c := app.AcquireCtx(&fasthttp.RequestCtx{})
defer app.ReleaseCtx(c)
type ReqHeader struct {
Expand Down
Loading

0 comments on commit 1dea615

Please sign in to comment.