diff --git a/app.go b/app.go index 792ac9397d..c2815ef71d 100644 --- a/app.go +++ b/app.go @@ -86,6 +86,11 @@ type Settings struct { // Default: false Immutable bool + // Converts all encoded characters in the route back before setting the path for the context, + // so that the routing can also work with urlencoded special characters + // Default: false + UnescapePath bool + // Enable or disable ETag header generation, since both weak and strong etags are generated // using the same hashing method (CRC-32). Weak ETags are the default when enabled. // Default value false diff --git a/ctx.go b/ctx.go index c6fc63a3e8..e35ab69003 100644 --- a/ctx.go +++ b/ctx.go @@ -987,10 +987,16 @@ func (ctx *Ctx) XHR() bool { // prettifyPath ... func (ctx *Ctx) prettifyPath() { + // If UnescapePath enabled, we decode the path + if ctx.app.Settings.UnescapePath { + pathBytes := getBytes(ctx.path) + pathBytes = fasthttp.AppendUnquotedArg(pathBytes[:0], pathBytes) + ctx.path = getString(pathBytes) + } // If CaseSensitive is disabled, we lowercase the original path if !ctx.app.Settings.CaseSensitive { // We are making a copy here to keep access to the original path - ctx.path = utils.ToLower(ctx.pathOriginal) + ctx.path = utils.ToLower(ctx.path) } // If StrictRouting is disabled, we strip all trailing slashes if !ctx.app.Settings.StrictRouting && len(ctx.path) > 1 && ctx.path[len(ctx.path)-1] == '/' { diff --git a/router_test.go b/router_test.go index b677ecfd9e..9e8f2bca84 100644 --- a/router_test.go +++ b/router_test.go @@ -146,6 +146,28 @@ func Test_Route_Match_Middleware(t *testing.T) { utils.AssertEqual(t, "bar/fasel", getString(body)) } +func Test_Route_Match_UnescapedPath(t *testing.T) { + app := New(&Settings{UnescapePath: true}) + + app.Use("/créer", func(ctx *Ctx) { + ctx.Send("test") + }) + + resp, err := app.Test(httptest.NewRequest(MethodGet, "/cr%C3%A9er", nil)) + utils.AssertEqual(t, nil, err, "app.Test(req)") + utils.AssertEqual(t, StatusOK, resp.StatusCode, "Status code") + + body, err := ioutil.ReadAll(resp.Body) + utils.AssertEqual(t, nil, err, "app.Test(req)") + utils.AssertEqual(t, "test", getString(body)) + + // check deactivated behavior + app.Settings.UnescapePath = false + resp, err = app.Test(httptest.NewRequest(MethodGet, "/cr%C3%A9er", nil)) + utils.AssertEqual(t, nil, err, "app.Test(req)") + utils.AssertEqual(t, StatusNotFound, resp.StatusCode, "Status code") +} + func Test_Route_Match_Middleware_HasPrefix(t *testing.T) { app := New()