Repository: labstack/echo (go)

Issue:
HTTP panic when using static and params routers
### Issue Description

HTTP panic when using static and params routers

### Checklist

- [x] Dependencies installed
- [x] No typos
- [x] Searched existing issues and docs

### Expected behaviour

router not found

### Actual behaviour
```
echo: http: panic serving [::1]:60088: runtime error: index out of range [-1]
goroutine 6 [running]:
net/http.(*conn).serve.func1(0xc0001337c0)
	/usr/local/Cellar/go/1.15.2/libexec/src/net/http/server.go:1801 +0x147
panic(0x1343e40, 0xc000016580)
	/usr/local/Cellar/go/1.15.2/libexec/src/runtime/panic.go:975 +0x3e9
github.com/labstack/echo/v4.(*Router).Find(0xc00000e940, 0xc000016560, 0x3, 0xc000016564, 0x12, 0x13d1b80, 0xc000133860)
	/Users/andrey/go/pkg/mod/github.com/labstack/echo/v4@v4.1.17/router.go:431 +0x11ca
github.com/labstack/echo/v4.(*Echo).ServeHTTP(0xc00000c1e0, 0x13cdf00, 0xc0001781c0, 0xc000184000)
	/Users/andrey/go/pkg/mod/github.com/labstack/echo/v4@v4.1.17/echo.go:619 +0x12b
net/http.serverHandler.ServeHTTP(0xc000178000, 0x13cdf00, 0xc0001781c0, 0xc000184000)
	/usr/local/Cellar/go/1.15.2/libexec/src/net/http/server.go:2843 +0xa3
net/http.(*conn).serve(0xc0001337c0, 0x13ce6c0, 0xc0000786c0)
	/usr/local/Cellar/go/1.15.2/libexec/src/net/http/server.go:1925 +0x8ad
created by net/http.(*Server).Serve
	/usr/local/Cellar/go/1.15.2/libexec/src/net/http/server.go:2969 +0x36c
```
### Steps to reproduce

`curl -X GET -H "Content-Type: application/json"  localhost:8811/users/creates`

### Working code to debug

```go
package main

import (
	"github.com/labstack/echo/v4"
	"github.com/labstack/echo/v4/middleware"
)

func main() {
	s := echo.New()
	s.Use(middleware.Logger())
	users := s.Group("/users")

	users.GET("/create", func(c echo.Context) error {
		return nil
	})
	users.GET("/:id/edit", func(c echo.Context) error {
		return nil
	})
	users.GET("/:id/active", func(c echo.Context) error {
		return nil
	})

	s.Start(":8811")
}
```

### Version/commit
v4.1.17


Pull request description:
Fixed panic when Router#Find fails on Param paths
Fixed panic when Router#Find fails to find a route that could match a Param route that only have children routes and no root route.
e.g
/create
/:id/edit
/:id/active

Finding /creates results in panic because the router tree node that belongs to the param route :id don't have pnames on it. The childrens of :id (:id/edit and :id/active) have the pnames properly set, but those are not processed because /creates don't match on those paths.
This fix #1653 

Patch:
diff --git a/router.go b/router.go
index ed728d6..4c3898c 100644
--- a/router.go
+++ b/router.go
@@ -428,7 +428,9 @@ func (r *Router) Find(method, path string, c Context) {
 				pos := strings.IndexByte(ns, '/')
 				if pos == -1 {
 					// If no slash is remaining in search string set param value
-					pvalues[len(cn.pnames)-1] = search
+					if len(cn.pnames) > 0 {
+						pvalues[len(cn.pnames)-1] = search
+					}
 					break
 				} else if pos > 0 {
 					// Otherwise continue route processing with restored next node


Test patch:
diff --git a/router_test.go b/router_test.go
index 0e88323..fca3a79 100644
--- a/router_test.go
+++ b/router_test.go
@@ -1298,6 +1298,40 @@ func TestRouterParam1466(t *testing.T) {
 	assert.Equal(t, 0, c.response.Status)
 }
 
+// Issue #1653
+func TestRouterPanicWhenParamNoRootOnlyChildsFailsFind(t *testing.T) {
+	e := New()
+	r := e.router
+
+	r.Add(http.MethodGet, "/users/create", handlerHelper("create", 1))
+	r.Add(http.MethodGet, "/users/:id/edit", func(c Context) error {
+		return nil
+	})
+	r.Add(http.MethodGet, "/users/:id/active", func(c Context) error {
+		return nil
+	})
+
+	c := e.NewContext(nil, nil).(*context)
+	r.Find(http.MethodGet, "/users/alice/edit", c)
+	assert.Equal(t, "alice", c.Param("id"))
+
+	c = e.NewContext(nil, nil).(*context)
+	r.Find(http.MethodGet, "/users/bob/active", c)
+	assert.Equal(t, "bob", c.Param("id"))
+
+	c = e.NewContext(nil, nil).(*context)
+	r.Find(http.MethodGet, "/users/create", c)
+	c.Handler()(c)
+	assert.Equal(t, 1, c.Get("create"))
+	assert.Equal(t, "/users/create", c.Get("path"))
+
+	//This panic before the fix for Issue #1653
+	c = e.NewContext(nil, nil).(*context)
+	r.Find(http.MethodGet, "/users/createNotFound", c)
+	he := c.Handler()(c).(*HTTPError)
+	assert.Equal(t, http.StatusNotFound, he.Code)
+}
+
 func benchmarkRouterRoutes(b *testing.B, routes []*Route) {
 	e := New()
 	r := e.router