Skip to content

Commit

Permalink
Merge pull request #506 from ReneWerner87/route_with_accents
Browse files Browse the repository at this point in the history
🚀 Added possibility to work with urlencoded special characters in the route
  • Loading branch information
Fenny authored Jun 25, 2020
2 parents e34326d + 0a4f58f commit 36cd6cc
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 1 deletion.
5 changes: 5 additions & 0 deletions app.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
8 changes: 7 additions & 1 deletion ctx.go
Original file line number Diff line number Diff line change
Expand Up @@ -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] == '/' {
Expand Down
43 changes: 43 additions & 0 deletions router_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,32 @@ 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))
// without special chars
resp, err = app.Test(httptest.NewRequest(MethodGet, "/créer", nil))
utils.AssertEqual(t, nil, err, "app.Test(req)")
utils.AssertEqual(t, StatusOK, resp.StatusCode, "Status code")

// 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()

Expand Down Expand Up @@ -405,6 +431,23 @@ func Benchmark_Router_Handler_CaseSensitive(b *testing.B) {
}
}

// go test -v ./... -run=^$ -bench=Benchmark_Router_Handler_Unescape -benchmem -count=4
func Benchmark_Router_Handler_Unescape(b *testing.B) {
app := New()
app.Settings.UnescapePath = true
registerDummyRoutes(app)
app.Delete("/créer", func(c *Ctx) {})

c := &fasthttp.RequestCtx{}

c.Request.Header.SetMethod(MethodDelete)
c.URI().SetPath("/cr%C3%A9er")

for n := 0; n < b.N; n++ {
app.handler(c)
}
}

// go test -v ./... -run=^$ -bench=Benchmark_Router_Handler_StrictRouting -benchmem -count=4
func Benchmark_Router_Handler_StrictRouting(b *testing.B) {
app := New()
Expand Down
14 changes: 14 additions & 0 deletions utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,3 +116,17 @@ func Benchmark_Utils_getGroupPath(b *testing.B) {
// func Benchmark_Utils_parseTokenList(b *testing.B) {
// // TODO
// }

func Benchmark_Utils_Unescape(b *testing.B) {
unescaped := ""
dst := make([]byte, 0)

for n := 0; n < b.N; n++ {
source := "/cr%C3%A9er"
pathBytes := getBytes(source)
pathBytes = fasthttp.AppendUnquotedArg(dst[:0], pathBytes)
unescaped = getString(pathBytes)
}

utils.AssertEqual(b, "/créer", unescaped)
}

0 comments on commit 36cd6cc

Please sign in to comment.