mirror of
https://github.com/labstack/echo.git
synced 2025-11-27 22:38:25 +02:00
Allow escaping of colon in route path so Google Cloud API "custom methods" https://cloud.google.com/apis/design/custom_methods can be implemented (resolves #1987) (#1988)
Allow escaping of colon in route path so Google Cloud API "custom methods" https://cloud.google.com/apis/design/custom_methods could be implemented (resolves #1987)
This commit is contained in:
@@ -98,6 +98,9 @@ func (r *Router) Add(method, path string, h HandlerFunc) {
|
|||||||
|
|
||||||
for i, lcpIndex := 0, len(path); i < lcpIndex; i++ {
|
for i, lcpIndex := 0, len(path); i < lcpIndex; i++ {
|
||||||
if path[i] == ':' {
|
if path[i] == ':' {
|
||||||
|
if i > 0 && path[i-1] == '\\' {
|
||||||
|
continue
|
||||||
|
}
|
||||||
j := i + 1
|
j := i + 1
|
||||||
|
|
||||||
r.insert(method, path[:i], nil, staticKind, "", nil)
|
r.insert(method, path[:i], nil, staticKind, "", nil)
|
||||||
|
|||||||
@@ -1118,6 +1118,58 @@ func TestRouterParamStaticConflict(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRouterParam_escapeColon(t *testing.T) {
|
||||||
|
// to allow Google cloud API like route paths with colon in them
|
||||||
|
// i.e. https://service.name/v1/some/resource/name:customVerb <- that `:customVerb` is not path param. It is just a string
|
||||||
|
e := New()
|
||||||
|
|
||||||
|
e.POST("/files/a/long/file\\:undelete", handlerFunc)
|
||||||
|
e.POST("/v1/some/resource/name:customVerb", handlerFunc)
|
||||||
|
|
||||||
|
var testCases = []struct {
|
||||||
|
whenURL string
|
||||||
|
expectRoute interface{}
|
||||||
|
expectParam map[string]string
|
||||||
|
expectError string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
whenURL: "/files/a/long/file\\:undelete",
|
||||||
|
expectRoute: "/files/a/long/file\\:undelete",
|
||||||
|
expectParam: map[string]string{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
whenURL: "/files/a/long/file\\:notMatching",
|
||||||
|
expectRoute: nil,
|
||||||
|
expectError: "code=404, message=Not Found",
|
||||||
|
expectParam: nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
whenURL: "/v1/some/resource/name:PATCH",
|
||||||
|
expectRoute: "/v1/some/resource/name:customVerb",
|
||||||
|
expectParam: map[string]string{"customVerb": ":PATCH"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tc := range testCases {
|
||||||
|
t.Run(tc.whenURL, func(t *testing.T) {
|
||||||
|
c := e.NewContext(nil, nil).(*context)
|
||||||
|
|
||||||
|
e.router.Find(http.MethodPost, tc.whenURL, c)
|
||||||
|
err := c.handler(c)
|
||||||
|
|
||||||
|
assert.Equal(t, tc.expectRoute, c.Get("path"))
|
||||||
|
if tc.expectError != "" {
|
||||||
|
assert.EqualError(t, err, tc.expectError)
|
||||||
|
} else {
|
||||||
|
assert.NoError(t, err)
|
||||||
|
}
|
||||||
|
for param, expectedValue := range tc.expectParam {
|
||||||
|
assert.Equal(t, expectedValue, c.Param(param))
|
||||||
|
}
|
||||||
|
checkUnusedParamValues(t, c, tc.expectParam)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestRouterMatchAny(t *testing.T) {
|
func TestRouterMatchAny(t *testing.T) {
|
||||||
e := New()
|
e := New()
|
||||||
r := e.router
|
r := e.router
|
||||||
|
|||||||
Reference in New Issue
Block a user