diff --git a/router.go b/router.go index 912cfeac0..deef2b2a9 100644 --- a/router.go +++ b/router.go @@ -231,8 +231,17 @@ func (r *Router) insert(method, path string, h HandlerFunc) { } j := i + 1 + startingPoint := i r.insertNode(method, path[:i], staticKind, routeMethod{}) - for ; i < lcpIndex && path[i] != '/'; i++ { + for ; i < lcpIndex; i++ { + if path[i] == '/' { + break + } + + if i > startingPoint && path[i-1] == '\\' && string(path[i]) == ":" { + i-- + break + } } pnames = append(pnames, path[j:i]) @@ -672,7 +681,13 @@ func (r *Router) Find(method, path string, c Context) { // act similarly to any node - consider all remaining search as match i = l } else { - for ; i < l && search[i] != '/'; i++ { + for ; i < l; i++ { + if search[i] == '/' { + break + } + if i > 0 && search[i-1] != '/' && string(search[i]) == ":" { + break + } } } diff --git a/router_test.go b/router_test.go index 203d014ec..7ceb91f30 100644 --- a/router_test.go +++ b/router_test.go @@ -1458,6 +1458,8 @@ func TestRouterParam_escapeColon(t *testing.T) { e.POST("/multilevel\\:undelete/second\\:something", handlerFunc) e.POST("/mixed/:id/second\\:something", handlerFunc) e.POST("/v1/some/resource/name:customVerb", handlerFunc) + e.POST("/files/:fileId\\:delete", handlerFunc) + e.POST("/files/:fileId\\:restore", handlerFunc) var testCases = []struct { whenURL string @@ -1491,6 +1493,16 @@ func TestRouterParam_escapeColon(t *testing.T) { expectRoute: "/v1/some/resource/name:customVerb", expectParam: map[string]string{"customVerb": ":PATCH"}, }, + { + whenURL: "/files/1234:delete", + expectRoute: "/files/:fileId\\:delete", + expectParam: map[string]string{"fileId": "1234"}, + }, + { + whenURL: "/files/1234:restore", + expectRoute: "/files/:fileId\\:restore", + expectParam: map[string]string{"fileId": "1234"}, + }, } for _, tc := range testCases { t.Run(tc.whenURL, func(t *testing.T) {