Browse Source

pattern aliases

pull/598/head
Bergutov Ruslan 5 years ago
parent
commit
27f0c4aaa9
  1. 10
      mux.go
  2. 40
      mux_test.go
  3. 8
      regexp.go
  4. 13
      route.go

10
mux.go

@ -92,6 +92,8 @@ type routeConf struct {
buildScheme string buildScheme string
buildVarsFunc BuildVarsFunc buildVarsFunc BuildVarsFunc
registeredPatterns map[string]string
} }
// returns an effective deep copy of `routeConf` // returns an effective deep copy of `routeConf`
@ -122,6 +124,14 @@ func copyRouteRegexp(r *routeRegexp) *routeRegexp {
return &c return &c
} }
func (r *Router) RegisterPattern(alias string, pattern string) *Router {
if r.registeredPatterns == nil {
r.registeredPatterns = map[string]string{}
}
r.registeredPatterns[alias] = pattern
return r
}
// Match attempts to match the given request against the router's registered routes. // Match attempts to match the given request against the router's registered routes.
// //
// If the request matches a route of this router or one of its subrouters the Route, // If the request matches a route of this router or one of its subrouters the Route,

40
mux_test.go

@ -216,6 +216,16 @@ func TestHost(t *testing.T) {
hostTemplate: `{v-1:[a-z]{3}}.{v-2:[a-z]{3}}.{v-3:[a-z]{3}}`, hostTemplate: `{v-1:[a-z]{3}}.{v-2:[a-z]{3}}.{v-3:[a-z]{3}}`,
shouldMatch: true, shouldMatch: true,
}, },
{
title: "Host route with alias patterns",
route: new(Route).RegisterPattern("version", "[a-z]{3}").Host("{v-1:version}.{v-2:version}.{v-3:version}"),
request: newRequest("GET", "http://aaa.bbb.ccc/111/222/333"),
vars: map[string]string{"v-1": "aaa", "v-2": "bbb", "v-3": "ccc"},
host: "aaa.bbb.ccc",
path: "",
hostTemplate: `{v-1:version}.{v-2:version}.{v-3:version}`,
shouldMatch: true,
},
} }
for _, test := range tests { for _, test := range tests {
t.Run(test.title, func(t *testing.T) { t.Run(test.title, func(t *testing.T) {
@ -449,6 +459,36 @@ func TestPath(t *testing.T) {
pathTemplate: `/{category:a|b/c}/{product}/{id:[0-9]+}`, pathTemplate: `/{category:a|b/c}/{product}/{id:[0-9]+}`,
shouldMatch: true, shouldMatch: true,
}, },
{
title: "Path route with regexp alias patterns",
route: new(Route).RegisterPattern("digits", "[0-9]+").Path("/{id:digits}"),
request: newRequest("GET", "http://localhost/1"),
vars: map[string]string{"id": "1"},
host: "",
path: "/1",
pathTemplate: `/{id:digits}`,
shouldMatch: true,
},
{
title: "Path route with regexp alias patterns",
route: new(Route).RegisterPattern("uuid", "[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-4[a-fA-F0-9]{3}-[8|9|aA|bB][a-fA-F0-9]{3}-[a-fA-F0-9]{12}").Path("/{category:uuid}/{product:uuid}"),
request: newRequest("GET", "http://localhost/dce51145-5cc3-4b54-bfb0-7bdb64a67e4d/a385ddcb-278e-4234-93dd-4d7b0fcb95c1"),
vars: map[string]string{"category": "dce51145-5cc3-4b54-bfb0-7bdb64a67e4d", "product": "a385ddcb-278e-4234-93dd-4d7b0fcb95c1"},
host: "",
path: "/dce51145-5cc3-4b54-bfb0-7bdb64a67e4d/a385ddcb-278e-4234-93dd-4d7b0fcb95c1",
pathTemplate: `/{category:uuid}/{product:uuid}`,
shouldMatch: true,
},
{
title: "Path route with regexp alias patterns passed through router",
route: NewRouter().RegisterPattern("digits", "[0-9]+").Path("/{id:digits}"),
request: newRequest("GET", "http://localhost/1"),
vars: map[string]string{"id": "1"},
host: "",
path: "/1",
pathTemplate: `/{id:digits}`,
shouldMatch: true,
},
} }
for _, test := range tests { for _, test := range tests {

8
regexp.go

@ -15,8 +15,9 @@ import (
) )
type routeRegexpOptions struct { type routeRegexpOptions struct {
strictSlash bool strictSlash bool
useEncodedPath bool useEncodedPath bool
registeredPatterns map[string]string
} }
type regexpType int type regexpType int
@ -85,6 +86,9 @@ func newRouteRegexp(tpl string, typ regexpType, options routeRegexpOptions) (*ro
return nil, fmt.Errorf("mux: missing name or pattern in %q", return nil, fmt.Errorf("mux: missing name or pattern in %q",
tpl[idxs[i]:end]) tpl[idxs[i]:end])
} }
if registeredPattern, ok := options.registeredPatterns[patt]; ok {
patt = registeredPattern
}
// Build the regexp pattern. // Build the regexp pattern.
fmt.Fprintf(pattern, "%s(?P<%s>%s)", regexp.QuoteMeta(raw), varGroupName(i/2), patt) fmt.Fprintf(pattern, "%s(?P<%s>%s)", regexp.QuoteMeta(raw), varGroupName(i/2), patt)

13
route.go

@ -31,6 +31,14 @@ type Route struct {
routeConf routeConf
} }
func (r *Route) RegisterPattern(alias string, pattern string) *Route {
if r.registeredPatterns == nil {
r.registeredPatterns = map[string]string{}
}
r.registeredPatterns[alias] = pattern
return r
}
// SkipClean reports whether path cleaning is enabled for this route via // SkipClean reports whether path cleaning is enabled for this route via
// Router.SkipClean. // Router.SkipClean.
func (r *Route) SkipClean() bool { func (r *Route) SkipClean() bool {
@ -184,8 +192,9 @@ func (r *Route) addRegexpMatcher(tpl string, typ regexpType) error {
} }
} }
rr, err := newRouteRegexp(tpl, typ, routeRegexpOptions{ rr, err := newRouteRegexp(tpl, typ, routeRegexpOptions{
strictSlash: r.strictSlash, strictSlash: r.strictSlash,
useEncodedPath: r.useEncodedPath, useEncodedPath: r.useEncodedPath,
registeredPatterns: r.registeredPatterns,
}) })
if err != nil { if err != nil {
return err return err

Loading…
Cancel
Save