From 2a412437b8378ea2d8668ca712b8d6078140aee2 Mon Sep 17 00:00:00 2001 From: Jinquan Wang Date: Thu, 11 Aug 2022 21:39:32 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=F0=9F=90=9B=20bug:=20Case=20sensitivity=20?= =?UTF-8?q?for=20parameters=20in=20GetRouteURL?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ctx.go | 20 +++++++++------ ctx_test.go | 72 ++++++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 75 insertions(+), 17 deletions(-) diff --git a/ctx.go b/ctx.go index 004cf3ec7a..68a8e3c269 100644 --- a/ctx.go +++ b/ctx.go @@ -833,7 +833,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 @@ -1154,20 +1154,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 325b67d78b..eb47f7e08a 100644 --- a/ctx_test.go +++ b/ctx_test.go @@ -1350,6 +1350,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") @@ -1365,6 +1370,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_Sencitive(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 @@ -2794,16 +2825,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 From 7d0bde33624bf623bf36985dad58c821b5fc6881 Mon Sep 17 00:00:00 2001 From: Jinquan Wang Date: Thu, 11 Aug 2022 21:52:07 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E2=9C=8F=EF=B8=8F=20perf:=20error=20spell?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ctx_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ctx_test.go b/ctx_test.go index eb47f7e08a..d37c8f7497 100644 --- a/ctx_test.go +++ b/ctx_test.go @@ -1376,7 +1376,7 @@ func Test_Ctx_Params(t *testing.T) { utils.AssertEqual(t, StatusOK, resp.StatusCode, "Status code") } -func Test_Ctx_Params_Case_Sencitive(t *testing.T) { +func Test_Ctx_Params_Case_Sensitive(t *testing.T) { t.Parallel() app := New(Config{CaseSensitive: true}) app.Get("/test/:User", func(c *Ctx) error {