diff --git a/app.go b/app.go index 47a01dd08a..2ce88704c5 100644 --- a/app.go +++ b/app.go @@ -30,7 +30,7 @@ import ( ) // Version of current fiber package -const Version = "2.51.0" +const Version = "2.52.0" // Handler defines a function to serve HTTP requests. type Handler = func(*Ctx) error diff --git a/ctx_test.go b/ctx_test.go index ea9dfa8485..a278d2f250 100644 --- a/ctx_test.go +++ b/ctx_test.go @@ -1372,6 +1372,100 @@ func Benchmark_Ctx_Fresh_WithNoCache(b *testing.B) { } } +// go test -run Test_Ctx_Parsers -v +func Test_Ctx_Parsers(t *testing.T) { + t.Parallel() + // setup + app := New() + + type TestStruct struct { + Name string + Class int + NameWithDefault string `json:"name2" xml:"Name2" form:"name2" cookie:"name2" query:"name2" params:"name2" reqHeader:"name2"` + ClassWithDefault int `json:"class2" xml:"Class2" form:"class2" cookie:"class2" query:"class2" params:"class2" reqHeader:"class2"` + } + + withValues := func(t *testing.T, actionFn func(c *Ctx, testStruct *TestStruct) error) { + t.Helper() + c := app.AcquireCtx(&fasthttp.RequestCtx{}) + defer app.ReleaseCtx(c) + testStruct := new(TestStruct) + + utils.AssertEqual(t, nil, actionFn(c, testStruct)) + utils.AssertEqual(t, "foo", testStruct.Name) + utils.AssertEqual(t, 111, testStruct.Class) + utils.AssertEqual(t, "bar", testStruct.NameWithDefault) + utils.AssertEqual(t, 222, testStruct.ClassWithDefault) + } + + 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(`foo111bar222`)) + return c.BodyParser(testStruct) + }) + }) + t.Run("BodyParser:form", func(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`)) + return c.BodyParser(testStruct) + }) + }) + t.Run("BodyParser:json", func(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}`)) + return c.BodyParser(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--") + c.Request().SetBody(body) + c.Request().Header.SetContentType(MIMEMultipartForm + `;boundary="b"`) + c.Request().Header.SetContentLength(len(body)) + return c.BodyParser(testStruct) + }) + }) + 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") + return c.CookieParser(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") + return c.QueryParser(testStruct) + }) + }) + t.Run("ParamsParser", func(t *testing.T) { + t.Parallel() + withValues(t, func(c *Ctx, testStruct *TestStruct) error { + c.route = &Route{Params: []string{"name", "name2", "class", "class2"}} + c.values = [30]string{"foo", "bar", "111", "222"} + return c.ParamsParser(testStruct) + }) + }) + t.Run("ReqHeaderParser", func(t *testing.T) { + t.Parallel() + withValues(t, func(c *Ctx, testStruct *TestStruct) error { + c.Request().Header.Add("name", "foo") + c.Request().Header.Add("name2", "bar") + c.Request().Header.Add("class", "111") + c.Request().Header.Add("class2", "222") + return c.ReqHeaderParser(testStruct) + }) + }) +} + // go test -run Test_Ctx_Get func Test_Ctx_Get(t *testing.T) { t.Parallel()