mirror of
https://github.com/labstack/echo.git
synced 2025-07-05 00:58:47 +02:00
Proper colon support in reverse (#2416)
* Adds support of the escaped colon in echo.Reverse --------- Co-authored-by: Mihard <mihard@webird.ru>
This commit is contained in:
93
echo_test.go
93
echo_test.go
@ -1517,6 +1517,83 @@ func TestEcho_OnAddRouteHandler(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestEchoReverse(t *testing.T) {
|
func TestEchoReverse(t *testing.T) {
|
||||||
|
var testCases = []struct {
|
||||||
|
name string
|
||||||
|
whenRouteName string
|
||||||
|
whenParams []interface{}
|
||||||
|
expect string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "ok,static with no params",
|
||||||
|
whenRouteName: "/static",
|
||||||
|
expect: "/static",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ok,static with non existent param",
|
||||||
|
whenRouteName: "/static",
|
||||||
|
whenParams: []interface{}{"missing param"},
|
||||||
|
expect: "/static",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ok, wildcard with no params",
|
||||||
|
whenRouteName: "/static/*",
|
||||||
|
expect: "/static/*",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ok, wildcard with params",
|
||||||
|
whenRouteName: "/static/*",
|
||||||
|
whenParams: []interface{}{"foo.txt"},
|
||||||
|
expect: "/static/foo.txt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ok, single param without param",
|
||||||
|
whenRouteName: "/params/:foo",
|
||||||
|
expect: "/params/:foo",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ok, single param with param",
|
||||||
|
whenRouteName: "/params/:foo",
|
||||||
|
whenParams: []interface{}{"one"},
|
||||||
|
expect: "/params/one",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ok, multi param without params",
|
||||||
|
whenRouteName: "/params/:foo/bar/:qux",
|
||||||
|
expect: "/params/:foo/bar/:qux",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ok, multi param with one param",
|
||||||
|
whenRouteName: "/params/:foo/bar/:qux",
|
||||||
|
whenParams: []interface{}{"one"},
|
||||||
|
expect: "/params/one/bar/:qux",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ok, multi param with all params",
|
||||||
|
whenRouteName: "/params/:foo/bar/:qux",
|
||||||
|
whenParams: []interface{}{"one", "two"},
|
||||||
|
expect: "/params/one/bar/two",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ok, multi param + wildcard with all params",
|
||||||
|
whenRouteName: "/params/:foo/bar/:qux/*",
|
||||||
|
whenParams: []interface{}{"one", "two", "three"},
|
||||||
|
expect: "/params/one/bar/two/three",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ok, backslash is not escaped",
|
||||||
|
whenRouteName: "/backslash",
|
||||||
|
whenParams: []interface{}{"test"},
|
||||||
|
expect: `/a\b/test`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ok, escaped colon verbs",
|
||||||
|
whenRouteName: "/params:customVerb",
|
||||||
|
whenParams: []interface{}{"PATCH"},
|
||||||
|
expect: `/params:PATCH`,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tc := range testCases {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
e := New()
|
e := New()
|
||||||
dummyHandler := func(Context) error { return nil }
|
dummyHandler := func(Context) error { return nil }
|
||||||
|
|
||||||
@ -1525,18 +1602,12 @@ func TestEchoReverse(t *testing.T) {
|
|||||||
e.GET("/params/:foo", dummyHandler).Name = "/params/:foo"
|
e.GET("/params/:foo", dummyHandler).Name = "/params/:foo"
|
||||||
e.GET("/params/:foo/bar/:qux", dummyHandler).Name = "/params/:foo/bar/:qux"
|
e.GET("/params/:foo/bar/:qux", dummyHandler).Name = "/params/:foo/bar/:qux"
|
||||||
e.GET("/params/:foo/bar/:qux/*", dummyHandler).Name = "/params/:foo/bar/:qux/*"
|
e.GET("/params/:foo/bar/:qux/*", dummyHandler).Name = "/params/:foo/bar/:qux/*"
|
||||||
|
e.GET("/a\\b/:x", dummyHandler).Name = "/backslash"
|
||||||
|
e.GET("/params\\::customVerb", dummyHandler).Name = "/params:customVerb"
|
||||||
|
|
||||||
assert.Equal(t, "/static", e.Reverse("/static"))
|
assert.Equal(t, tc.expect, e.Reverse(tc.whenRouteName, tc.whenParams...))
|
||||||
assert.Equal(t, "/static", e.Reverse("/static", "missing param"))
|
})
|
||||||
assert.Equal(t, "/static/*", e.Reverse("/static/*"))
|
}
|
||||||
assert.Equal(t, "/static/foo.txt", e.Reverse("/static/*", "foo.txt"))
|
|
||||||
|
|
||||||
assert.Equal(t, "/params/:foo", e.Reverse("/params/:foo"))
|
|
||||||
assert.Equal(t, "/params/one", e.Reverse("/params/:foo", "one"))
|
|
||||||
assert.Equal(t, "/params/:foo/bar/:qux", e.Reverse("/params/:foo/bar/:qux"))
|
|
||||||
assert.Equal(t, "/params/one/bar/:qux", e.Reverse("/params/:foo/bar/:qux", "one"))
|
|
||||||
assert.Equal(t, "/params/one/bar/two", e.Reverse("/params/:foo/bar/:qux", "one", "two"))
|
|
||||||
assert.Equal(t, "/params/one/bar/two/three", e.Reverse("/params/:foo/bar/:qux/*", "one", "two", "three"))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestEchoReverseHandleHostProperly(t *testing.T) {
|
func TestEchoReverseHandleHostProperly(t *testing.T) {
|
||||||
|
@ -159,7 +159,12 @@ func (r *Router) Reverse(name string, params ...interface{}) string {
|
|||||||
for _, route := range r.routes {
|
for _, route := range r.routes {
|
||||||
if route.Name == name {
|
if route.Name == name {
|
||||||
for i, l := 0, len(route.Path); i < l; i++ {
|
for i, l := 0, len(route.Path); i < l; i++ {
|
||||||
if (route.Path[i] == ':' || route.Path[i] == '*') && n < ln {
|
hasBackslash := route.Path[i] == '\\'
|
||||||
|
if hasBackslash && i+1 < l && route.Path[i+1] == ':' {
|
||||||
|
i++ // backslash before colon escapes that colon. in that case skip backslash
|
||||||
|
}
|
||||||
|
if n < ln && (route.Path[i] == '*' || (!hasBackslash && route.Path[i] == ':')) {
|
||||||
|
// in case of `*` wildcard or `:` (unescaped colon) param we replace everything till next slash or end of path
|
||||||
for ; i < l && route.Path[i] != '/'; i++ {
|
for ; i < l && route.Path[i] != '/'; i++ {
|
||||||
}
|
}
|
||||||
uri.WriteString(fmt.Sprintf("%v", params[n]))
|
uri.WriteString(fmt.Sprintf("%v", params[n]))
|
||||||
|
Reference in New Issue
Block a user