Skip to content

Commit

Permalink
When route is registered with empty path it is normalized to /. Mak…
Browse files Browse the repository at this point in the history
…e sure that returned echo.Route structs reflect that behavior. (#2616)
  • Loading branch information
aldas authored Mar 27, 2024
1 parent d549290 commit 447c92d
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 15 deletions.
5 changes: 5 additions & 0 deletions echo_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1598,6 +1598,11 @@ func TestEchoReverse(t *testing.T) {
whenParams []interface{}
expect string
}{
{
name: "ok, not existing path returns empty url",
whenRouteName: "not-existing",
expect: "",
},
{
name: "ok,static with no params",
whenRouteName: "/static",
Expand Down
38 changes: 23 additions & 15 deletions router.go
Original file line number Diff line number Diff line change
Expand Up @@ -185,8 +185,18 @@ func (r *Router) Reverse(name string, params ...interface{}) string {
return uri.String()
}

func normalizePathSlash(path string) string {
if path == "" {
path = "/"
} else if path[0] != '/' {
path = "/" + path
}
return path
}

func (r *Router) add(method, path, name string, h HandlerFunc) *Route {
r.Add(method, path, h)
path = normalizePathSlash(path)
r.insert(method, path, h)

route := &Route{
Method: method,
Expand All @@ -199,13 +209,11 @@ func (r *Router) add(method, path, name string, h HandlerFunc) *Route {

// Add registers a new route for method and path with matching handler.
func (r *Router) Add(method, path string, h HandlerFunc) {
// Validate path
if path == "" {
path = "/"
}
if path[0] != '/' {
path = "/" + path
}
r.insert(method, normalizePathSlash(path), h)
}

func (r *Router) insert(method, path string, h HandlerFunc) {
path = normalizePathSlash(path)
pnames := []string{} // Param names
ppath := path // Pristine path

Expand All @@ -224,7 +232,7 @@ func (r *Router) Add(method, path string, h HandlerFunc) {
}
j := i + 1

r.insert(method, path[:i], staticKind, routeMethod{})
r.insertNode(method, path[:i], staticKind, routeMethod{})
for ; i < lcpIndex && path[i] != '/'; i++ {
}

Expand All @@ -234,21 +242,21 @@ func (r *Router) Add(method, path string, h HandlerFunc) {

if i == lcpIndex {
// path node is last fragment of route path. ie. `/users/:id`
r.insert(method, path[:i], paramKind, routeMethod{ppath, pnames, h})
r.insertNode(method, path[:i], paramKind, routeMethod{ppath, pnames, h})
} else {
r.insert(method, path[:i], paramKind, routeMethod{})
r.insertNode(method, path[:i], paramKind, routeMethod{})
}
} else if path[i] == '*' {
r.insert(method, path[:i], staticKind, routeMethod{})
r.insertNode(method, path[:i], staticKind, routeMethod{})
pnames = append(pnames, "*")
r.insert(method, path[:i+1], anyKind, routeMethod{ppath, pnames, h})
r.insertNode(method, path[:i+1], anyKind, routeMethod{ppath, pnames, h})
}
}

r.insert(method, path, staticKind, routeMethod{ppath, pnames, h})
r.insertNode(method, path, staticKind, routeMethod{ppath, pnames, h})
}

func (r *Router) insert(method, path string, t kind, rm routeMethod) {
func (r *Router) insertNode(method, path string, t kind, rm routeMethod) {
// Adjust max param
paramLen := len(rm.pnames)
if *r.echo.maxParam < paramLen {
Expand Down
16 changes: 16 additions & 0 deletions router_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2770,6 +2770,22 @@ func TestRouter_Routes(t *testing.T) {
}
}

func TestRouter_addEmptyPathToSlashReverse(t *testing.T) {
e := New()
r := e.router
r.add(http.MethodGet, "", "empty", handlerFunc) // emtpy path is normalized to `/`

assert.Equal(t, "/", r.Reverse("empty"))
}

func TestRouter_ReverseNotFound(t *testing.T) {
e := New()
r := e.router
r.add(http.MethodGet, "", "empty", handlerFunc)

assert.Equal(t, "", r.Reverse("not-existing"))
}

func TestRouter_Reverse(t *testing.T) {
e := New()
r := e.router
Expand Down

0 comments on commit 447c92d

Please sign in to comment.