diff --git a/ctx.go b/ctx.go index d8818ff855..4bacb47304 100644 --- a/ctx.go +++ b/ctx.go @@ -861,7 +861,7 @@ func (c *Ctx) Params(key string, defaultValue ...string) string { if len(key) != len(c.route.Params[i]) { continue } - if c.route.Params[i] == key { + if c.route.Params[i] == key || (!c.app.config.CaseSensitive && utils.EqualFold(c.route.Params[i], key)) { // in case values are not here if len(c.values) <= i || len(c.values[i]) == 0 { break @@ -1182,20 +1182,24 @@ func (c *Ctx) Bind(vars Map) error { func (c *Ctx) getLocationFromRoute(route Route, params Map) (string, error) { buf := bytebufferpool.Get() for _, segment := range route.routeParser.segs { + if !segment.IsParam { + _, err := buf.WriteString(segment.Const) + if err != nil { + return "", err + } + continue + } + for key, val := range params { - if segment.IsParam && (key == segment.ParamName || (segment.IsGreedy && len(key) == 1 && isInCharset(key[0], greedyParameters))) { + isSame := key == segment.ParamName || (!c.app.config.CaseSensitive && utils.EqualFold(key, segment.ParamName)) + isGreedy := (segment.IsGreedy && len(key) == 1 && isInCharset(key[0], greedyParameters)) + if isSame || isGreedy { _, err := buf.WriteString(utils.ToString(val)) if err != nil { return "", err } } } - if !segment.IsParam { - _, err := buf.WriteString(segment.Const) - if err != nil { - return "", err - } - } } location := buf.String() // release buffer diff --git a/ctx_test.go b/ctx_test.go index 825cbb8966..f5a64c27e8 100644 --- a/ctx_test.go +++ b/ctx_test.go @@ -1413,6 +1413,11 @@ func Test_Ctx_Params(t *testing.T) { utils.AssertEqual(t, "", c.Params("optional")) return nil }) + app.Get("/test5/:id/:Id", func(c *Ctx) error { + utils.AssertEqual(t, "first", c.Params("id")) + utils.AssertEqual(t, "first", c.Params("Id")) + return nil + }) resp, err := app.Test(httptest.NewRequest(MethodGet, "/test/john", nil)) utils.AssertEqual(t, nil, err, "app.Test(req)") utils.AssertEqual(t, StatusOK, resp.StatusCode, "Status code") @@ -1428,6 +1433,32 @@ func Test_Ctx_Params(t *testing.T) { resp, err = app.Test(httptest.NewRequest(MethodGet, "/test4", nil)) utils.AssertEqual(t, nil, err, "app.Test(req)") utils.AssertEqual(t, StatusOK, resp.StatusCode, "Status code") + + resp, err = app.Test(httptest.NewRequest(MethodGet, "/test5/first/second", nil)) + utils.AssertEqual(t, nil, err) + utils.AssertEqual(t, StatusOK, resp.StatusCode, "Status code") +} + +func Test_Ctx_Params_Case_Sensitive(t *testing.T) { + t.Parallel() + app := New(Config{CaseSensitive: true}) + app.Get("/test/:User", func(c *Ctx) error { + utils.AssertEqual(t, "john", c.Params("User")) + utils.AssertEqual(t, "", c.Params("user")) + return nil + }) + app.Get("/test2/:id/:Id", func(c *Ctx) error { + utils.AssertEqual(t, "first", c.Params("id")) + utils.AssertEqual(t, "second", c.Params("Id")) + return nil + }) + resp, err := app.Test(httptest.NewRequest(MethodGet, "/test/john", nil)) + utils.AssertEqual(t, nil, err, "app.Test(req)") + utils.AssertEqual(t, StatusOK, resp.StatusCode, "Status code") + + resp, err = app.Test(httptest.NewRequest(MethodGet, "/test2/first/second", nil)) + utils.AssertEqual(t, nil, err) + utils.AssertEqual(t, StatusOK, resp.StatusCode, "Status code") } // go test -race -run Test_Ctx_AllParams @@ -2916,16 +2947,39 @@ func Benchmark_Ctx_Get_Location_From_Route(b *testing.B) { // go test -run Test_Ctx_Get_Location_From_Route_name func Test_Ctx_Get_Location_From_Route_name(t *testing.T) { - app := New() - c := app.AcquireCtx(&fasthttp.RequestCtx{}) - defer app.ReleaseCtx(c) - app.Get("/user/:name", func(c *Ctx) error { - return c.SendString(c.Params("name")) - }).Name("User") + t.Run("case insensitive", func(t *testing.T) { + app := New() + c := app.AcquireCtx(&fasthttp.RequestCtx{}) + defer app.ReleaseCtx(c) + app.Get("/user/:name", func(c *Ctx) error { + return c.SendString(c.Params("name")) + }).Name("User") - location, err := c.GetRouteURL("User", Map{"name": "fiber"}) - utils.AssertEqual(t, nil, err) - utils.AssertEqual(t, "/user/fiber", location) + location, err := c.GetRouteURL("User", Map{"name": "fiber"}) + utils.AssertEqual(t, nil, err) + utils.AssertEqual(t, "/user/fiber", location) + + location, err = c.GetRouteURL("User", Map{"Name": "fiber"}) + utils.AssertEqual(t, nil, err) + utils.AssertEqual(t, "/user/fiber", location) + }) + + t.Run("case sensitive",func(t *testing.T) { + app := New(Config{CaseSensitive: true}) + c := app.AcquireCtx(&fasthttp.RequestCtx{}) + defer app.ReleaseCtx(c) + app.Get("/user/:name", func(c *Ctx) error { + return c.SendString(c.Params("name")) + }).Name("User") + + location, err := c.GetRouteURL("User", Map{"name": "fiber"}) + utils.AssertEqual(t, nil, err) + utils.AssertEqual(t, "/user/fiber", location) + + location, err = c.GetRouteURL("User", Map{"Name": "fiber"}) + utils.AssertEqual(t, nil, err) + utils.AssertEqual(t, "/user/", location) + }) } // go test -run Test_Ctx_Get_Location_From_Route_name_Optional_greedy