Browse Source

GetQueryTemplates and GetQueryRegexp extraction (#304)

Developers can now extract the query templates and regexps
from a router as lists of combined query pairs.
pull/207/merge
Paul B. Beskow 8 years ago committed by Kamil Kisiel
parent
commit
10490f55fa
  1. 28
      README.md
  2. 588
      mux_test.go
  3. 38
      route.go

28
README.md

@ -201,22 +201,34 @@ func main() {
r.HandleFunc("/products", handler).Methods("POST") r.HandleFunc("/products", handler).Methods("POST")
r.HandleFunc("/articles", handler).Methods("GET") r.HandleFunc("/articles", handler).Methods("GET")
r.HandleFunc("/articles/{id}", handler).Methods("GET", "PUT") r.HandleFunc("/articles/{id}", handler).Methods("GET", "PUT")
r.HandleFunc("/authors", handler).Queries("surname", "{surname}")
r.Walk(func(route *mux.Route, router *mux.Router, ancestors []*mux.Route) error { r.Walk(func(route *mux.Route, router *mux.Router, ancestors []*mux.Route) error {
t, err := route.GetPathTemplate() t, err := route.GetPathTemplate()
if err != nil { if err != nil {
return err return err
} }
qt, err := route.GetQueriesTemplates()
if err != nil {
return err
}
// p will contain regular expression is compatible with regular expression in Perl, Python, and other languages. // p will contain regular expression is compatible with regular expression in Perl, Python, and other languages.
// for instance the regular expression for path '/articles/{id}' will be '^/articles/(?P<v0>[^/]+)$' // for instance the regular expression for path '/articles/{id}' will be '^/articles/(?P<v0>[^/]+)$'
p, err := route.GetPathRegexp() p, err := route.GetPathRegexp()
if err != nil { if err != nil {
return err return err
} }
// qr will contain a list of regular expressions with the same semantics as GetPathRegexp,
// just applied to the Queries pairs instead, e.g., 'Queries("surname", "{surname}") will return
// {"^surname=(?P<v0>.*)$}. Where each combined query pair will have an entry in the list.
qr, err := route.GetQueriesRegexp()
if err != nil {
return err
}
m, err := route.GetMethods() m, err := route.GetMethods()
if err != nil { if err != nil {
return err return err
} }
fmt.Println(strings.Join(m, ","), t, p) fmt.Println(strings.Join(m, ","), strings.Join(qt, ","), strings.Join(qr, ","), t, p)
return nil return nil
}) })
http.Handle("/", r) http.Handle("/", r)
@ -339,22 +351,34 @@ r.HandleFunc("/", handler)
r.HandleFunc("/products", handler).Methods("POST") r.HandleFunc("/products", handler).Methods("POST")
r.HandleFunc("/articles", handler).Methods("GET") r.HandleFunc("/articles", handler).Methods("GET")
r.HandleFunc("/articles/{id}", handler).Methods("GET", "PUT") r.HandleFunc("/articles/{id}", handler).Methods("GET", "PUT")
r.HandleFunc("/authors", handler).Queries("surname", "{surname}")
r.Walk(func(route *mux.Route, router *mux.Router, ancestors []*mux.Route) error { r.Walk(func(route *mux.Route, router *mux.Router, ancestors []*mux.Route) error {
t, err := route.GetPathTemplate() t, err := route.GetPathTemplate()
if err != nil { if err != nil {
return err return err
} }
qt, err := route.GetQueriesTemplates()
if err != nil {
return err
}
// p will contain a regular expression that is compatible with regular expressions in Perl, Python, and other languages. // p will contain a regular expression that is compatible with regular expressions in Perl, Python, and other languages.
// For example, the regular expression for path '/articles/{id}' will be '^/articles/(?P<v0>[^/]+)$'. // For example, the regular expression for path '/articles/{id}' will be '^/articles/(?P<v0>[^/]+)$'.
p, err := route.GetPathRegexp() p, err := route.GetPathRegexp()
if err != nil { if err != nil {
return err return err
} }
// qr will contain a list of regular expressions with the same semantics as GetPathRegexp,
// just applied to the Queries pairs instead, e.g., 'Queries("surname", "{surname}") will return
// {"^surname=(?P<v0>.*)$}. Where each combined query pair will have an entry in the list.
qr, err := route.GetQueriesRegexp()
if err != nil {
return err
}
m, err := route.GetMethods() m, err := route.GetMethods()
if err != nil { if err != nil {
return err return err
} }
fmt.Println(strings.Join(m, ","), t, p) fmt.Println(strings.Join(m, ","), strings.Join(qt, ","), strings.Join(qr, ","), t, p)
return nil return nil
}) })
``` ```

588
mux_test.go

@ -29,20 +29,22 @@ func (r *routeRegexp) GoString() string {
} }
type routeTest struct { type routeTest struct {
title string // title of the test title string // title of the test
route *Route // the route being tested route *Route // the route being tested
request *http.Request // a request to test the route request *http.Request // a request to test the route
vars map[string]string // the expected vars of the match vars map[string]string // the expected vars of the match
scheme string // the expected scheme of the built URL scheme string // the expected scheme of the built URL
host string // the expected host of the built URL host string // the expected host of the built URL
path string // the expected path of the built URL path string // the expected path of the built URL
query string // the expected query string of the built URL query string // the expected query string of the built URL
pathTemplate string // the expected path template of the route pathTemplate string // the expected path template of the route
hostTemplate string // the expected host template of the route hostTemplate string // the expected host template of the route
methods []string // the expected route methods queriesTemplate string // the expected query template of the route
pathRegexp string // the expected path regexp methods []string // the expected route methods
shouldMatch bool // whether the request is expected to match the route at all pathRegexp string // the expected path regexp
shouldRedirect bool // whether the request should result in a redirect queriesRegexp string // the expected query regexp
shouldMatch bool // whether the request is expected to match the route at all
shouldRedirect bool // whether the request should result in a redirect
} }
func TestHost(t *testing.T) { func TestHost(t *testing.T) {
@ -739,257 +741,309 @@ func TestMethods(t *testing.T) {
func TestQueries(t *testing.T) { func TestQueries(t *testing.T) {
tests := []routeTest{ tests := []routeTest{
{ {
title: "Queries route, match", title: "Queries route, match",
route: new(Route).Queries("foo", "bar", "baz", "ding"), route: new(Route).Queries("foo", "bar", "baz", "ding"),
request: newRequest("GET", "http://localhost?foo=bar&baz=ding"), request: newRequest("GET", "http://localhost?foo=bar&baz=ding"),
vars: map[string]string{}, vars: map[string]string{},
host: "", host: "",
path: "", path: "",
query: "foo=bar&baz=ding", query: "foo=bar&baz=ding",
shouldMatch: true, queriesTemplate: "foo=bar,baz=ding",
}, queriesRegexp: "^foo=bar$,^baz=ding$",
{ shouldMatch: true,
title: "Queries route, match with a query string", },
route: new(Route).Host("www.example.com").Path("/api").Queries("foo", "bar", "baz", "ding"), {
request: newRequest("GET", "http://www.example.com/api?foo=bar&baz=ding"), title: "Queries route, match with a query string",
vars: map[string]string{}, route: new(Route).Host("www.example.com").Path("/api").Queries("foo", "bar", "baz", "ding"),
host: "", request: newRequest("GET", "http://www.example.com/api?foo=bar&baz=ding"),
path: "", vars: map[string]string{},
query: "foo=bar&baz=ding", host: "",
pathTemplate: `/api`, path: "",
hostTemplate: `www.example.com`, query: "foo=bar&baz=ding",
shouldMatch: true, pathTemplate: `/api`,
}, hostTemplate: `www.example.com`,
{ queriesTemplate: "foo=bar,baz=ding",
title: "Queries route, match with a query string out of order", queriesRegexp: "^foo=bar$,^baz=ding$",
route: new(Route).Host("www.example.com").Path("/api").Queries("foo", "bar", "baz", "ding"), shouldMatch: true,
request: newRequest("GET", "http://www.example.com/api?baz=ding&foo=bar"), },
vars: map[string]string{}, {
host: "", title: "Queries route, match with a query string out of order",
path: "", route: new(Route).Host("www.example.com").Path("/api").Queries("foo", "bar", "baz", "ding"),
query: "foo=bar&baz=ding", request: newRequest("GET", "http://www.example.com/api?baz=ding&foo=bar"),
pathTemplate: `/api`, vars: map[string]string{},
hostTemplate: `www.example.com`, host: "",
shouldMatch: true, path: "",
}, query: "foo=bar&baz=ding",
{ pathTemplate: `/api`,
title: "Queries route, bad query", hostTemplate: `www.example.com`,
route: new(Route).Queries("foo", "bar", "baz", "ding"), queriesTemplate: "foo=bar,baz=ding",
request: newRequest("GET", "http://localhost?foo=bar&baz=dong"), queriesRegexp: "^foo=bar$,^baz=ding$",
vars: map[string]string{}, shouldMatch: true,
host: "", },
path: "", {
shouldMatch: false, title: "Queries route, bad query",
}, route: new(Route).Queries("foo", "bar", "baz", "ding"),
{ request: newRequest("GET", "http://localhost?foo=bar&baz=dong"),
title: "Queries route with pattern, match", vars: map[string]string{},
route: new(Route).Queries("foo", "{v1}"), host: "",
request: newRequest("GET", "http://localhost?foo=bar"), path: "",
vars: map[string]string{"v1": "bar"}, queriesTemplate: "foo=bar,baz=ding",
host: "", queriesRegexp: "^foo=bar$,^baz=ding$",
path: "", shouldMatch: false,
query: "foo=bar", },
shouldMatch: true, {
}, title: "Queries route with pattern, match",
{ route: new(Route).Queries("foo", "{v1}"),
title: "Queries route with multiple patterns, match", request: newRequest("GET", "http://localhost?foo=bar"),
route: new(Route).Queries("foo", "{v1}", "baz", "{v2}"), vars: map[string]string{"v1": "bar"},
request: newRequest("GET", "http://localhost?foo=bar&baz=ding"), host: "",
vars: map[string]string{"v1": "bar", "v2": "ding"}, path: "",
host: "", query: "foo=bar",
path: "", queriesTemplate: "foo={v1}",
query: "foo=bar&baz=ding", queriesRegexp: "^foo=(?P<v0>.*)$",
shouldMatch: true, shouldMatch: true,
}, },
{ {
title: "Queries route with regexp pattern, match", title: "Queries route with multiple patterns, match",
route: new(Route).Queries("foo", "{v1:[0-9]+}"), route: new(Route).Queries("foo", "{v1}", "baz", "{v2}"),
request: newRequest("GET", "http://localhost?foo=10"), request: newRequest("GET", "http://localhost?foo=bar&baz=ding"),
vars: map[string]string{"v1": "10"}, vars: map[string]string{"v1": "bar", "v2": "ding"},
host: "", host: "",
path: "", path: "",
query: "foo=10", query: "foo=bar&baz=ding",
shouldMatch: true, queriesTemplate: "foo={v1},baz={v2}",
}, queriesRegexp: "^foo=(?P<v0>.*)$,^baz=(?P<v0>.*)$",
{ shouldMatch: true,
title: "Queries route with regexp pattern, regexp does not match", },
route: new(Route).Queries("foo", "{v1:[0-9]+}"), {
request: newRequest("GET", "http://localhost?foo=a"), title: "Queries route with regexp pattern, match",
vars: map[string]string{}, route: new(Route).Queries("foo", "{v1:[0-9]+}"),
host: "", request: newRequest("GET", "http://localhost?foo=10"),
path: "", vars: map[string]string{"v1": "10"},
shouldMatch: false, host: "",
}, path: "",
{ query: "foo=10",
title: "Queries route with regexp pattern with quantifier, match", queriesTemplate: "foo={v1:[0-9]+}",
route: new(Route).Queries("foo", "{v1:[0-9]{1}}"), queriesRegexp: "^foo=(?P<v0>[0-9]+)$",
request: newRequest("GET", "http://localhost?foo=1"), shouldMatch: true,
vars: map[string]string{"v1": "1"}, },
host: "", {
path: "", title: "Queries route with regexp pattern, regexp does not match",
query: "foo=1", route: new(Route).Queries("foo", "{v1:[0-9]+}"),
shouldMatch: true, request: newRequest("GET", "http://localhost?foo=a"),
}, vars: map[string]string{},
{ host: "",
title: "Queries route with regexp pattern with quantifier, additional variable in query string, match", path: "",
route: new(Route).Queries("foo", "{v1:[0-9]{1}}"), queriesTemplate: "foo={v1:[0-9]+}",
request: newRequest("GET", "http://localhost?bar=2&foo=1"), queriesRegexp: "^foo=(?P<v0>[0-9]+)$",
vars: map[string]string{"v1": "1"}, shouldMatch: false,
host: "", },
path: "", {
query: "foo=1", title: "Queries route with regexp pattern with quantifier, match",
shouldMatch: true, route: new(Route).Queries("foo", "{v1:[0-9]{1}}"),
}, request: newRequest("GET", "http://localhost?foo=1"),
{ vars: map[string]string{"v1": "1"},
title: "Queries route with regexp pattern with quantifier, regexp does not match", host: "",
route: new(Route).Queries("foo", "{v1:[0-9]{1}}"), path: "",
request: newRequest("GET", "http://localhost?foo=12"), query: "foo=1",
vars: map[string]string{}, queriesTemplate: "foo={v1:[0-9]{1}}",
host: "", queriesRegexp: "^foo=(?P<v0>[0-9]{1})$",
path: "", shouldMatch: true,
shouldMatch: false, },
}, {
{ title: "Queries route with regexp pattern with quantifier, additional variable in query string, match",
title: "Queries route with regexp pattern with quantifier, additional capturing group", route: new(Route).Queries("foo", "{v1:[0-9]{1}}"),
route: new(Route).Queries("foo", "{v1:[0-9]{1}(?:a|b)}"), request: newRequest("GET", "http://localhost?bar=2&foo=1"),
request: newRequest("GET", "http://localhost?foo=1a"), vars: map[string]string{"v1": "1"},
vars: map[string]string{"v1": "1a"}, host: "",
host: "", path: "",
path: "", query: "foo=1",
query: "foo=1a", queriesTemplate: "foo={v1:[0-9]{1}}",
shouldMatch: true, queriesRegexp: "^foo=(?P<v0>[0-9]{1})$",
}, shouldMatch: true,
{ },
title: "Queries route with regexp pattern with quantifier, additional variable in query string, regexp does not match", {
route: new(Route).Queries("foo", "{v1:[0-9]{1}}"), title: "Queries route with regexp pattern with quantifier, regexp does not match",
request: newRequest("GET", "http://localhost?foo=12"), route: new(Route).Queries("foo", "{v1:[0-9]{1}}"),
vars: map[string]string{}, request: newRequest("GET", "http://localhost?foo=12"),
host: "", vars: map[string]string{},
path: "", host: "",
shouldMatch: false, path: "",
}, queriesTemplate: "foo={v1:[0-9]{1}}",
{ queriesRegexp: "^foo=(?P<v0>[0-9]{1})$",
title: "Queries route with hyphenated name, match", shouldMatch: false,
route: new(Route).Queries("foo", "{v-1}"), },
request: newRequest("GET", "http://localhost?foo=bar"), {
vars: map[string]string{"v-1": "bar"}, title: "Queries route with regexp pattern with quantifier, additional capturing group",
host: "", route: new(Route).Queries("foo", "{v1:[0-9]{1}(?:a|b)}"),
path: "", request: newRequest("GET", "http://localhost?foo=1a"),
query: "foo=bar", vars: map[string]string{"v1": "1a"},
shouldMatch: true, host: "",
}, path: "",
{ query: "foo=1a",
title: "Queries route with multiple hyphenated names, match", queriesTemplate: "foo={v1:[0-9]{1}(?:a|b)}",
route: new(Route).Queries("foo", "{v-1}", "baz", "{v-2}"), queriesRegexp: "^foo=(?P<v0>[0-9]{1}(?:a|b))$",
request: newRequest("GET", "http://localhost?foo=bar&baz=ding"), shouldMatch: true,
vars: map[string]string{"v-1": "bar", "v-2": "ding"}, },
host: "", {
path: "", title: "Queries route with regexp pattern with quantifier, additional variable in query string, regexp does not match",
query: "foo=bar&baz=ding", route: new(Route).Queries("foo", "{v1:[0-9]{1}}"),
shouldMatch: true, request: newRequest("GET", "http://localhost?foo=12"),
}, vars: map[string]string{},
{ host: "",
title: "Queries route with hyphenate name and pattern, match", path: "",
route: new(Route).Queries("foo", "{v-1:[0-9]+}"), queriesTemplate: "foo={v1:[0-9]{1}}",
request: newRequest("GET", "http://localhost?foo=10"), queriesRegexp: "^foo=(?P<v0>[0-9]{1})$",
vars: map[string]string{"v-1": "10"}, shouldMatch: false,
host: "", },
path: "", {
query: "foo=10", title: "Queries route with hyphenated name, match",
shouldMatch: true, route: new(Route).Queries("foo", "{v-1}"),
}, request: newRequest("GET", "http://localhost?foo=bar"),
{ vars: map[string]string{"v-1": "bar"},
title: "Queries route with hyphenated name and pattern with quantifier, additional capturing group", host: "",
route: new(Route).Queries("foo", "{v-1:[0-9]{1}(?:a|b)}"), path: "",
request: newRequest("GET", "http://localhost?foo=1a"), query: "foo=bar",
vars: map[string]string{"v-1": "1a"}, queriesTemplate: "foo={v-1}",
host: "", queriesRegexp: "^foo=(?P<v0>.*)$",
path: "", shouldMatch: true,
query: "foo=1a", },
shouldMatch: true, {
}, title: "Queries route with multiple hyphenated names, match",
{ route: new(Route).Queries("foo", "{v-1}", "baz", "{v-2}"),
title: "Queries route with empty value, should match", request: newRequest("GET", "http://localhost?foo=bar&baz=ding"),
route: new(Route).Queries("foo", ""), vars: map[string]string{"v-1": "bar", "v-2": "ding"},
request: newRequest("GET", "http://localhost?foo=bar"), host: "",
vars: map[string]string{}, path: "",
host: "", query: "foo=bar&baz=ding",
path: "", queriesTemplate: "foo={v-1},baz={v-2}",
query: "foo=", queriesRegexp: "^foo=(?P<v0>.*)$,^baz=(?P<v0>.*)$",
shouldMatch: true, shouldMatch: true,
}, },
{ {
title: "Queries route with empty value and no parameter in request, should not match", title: "Queries route with hyphenate name and pattern, match",
route: new(Route).Queries("foo", ""), route: new(Route).Queries("foo", "{v-1:[0-9]+}"),
request: newRequest("GET", "http://localhost"), request: newRequest("GET", "http://localhost?foo=10"),
vars: map[string]string{}, vars: map[string]string{"v-1": "10"},
host: "", host: "",
path: "", path: "",
shouldMatch: false, query: "foo=10",
}, queriesTemplate: "foo={v-1:[0-9]+}",
{ queriesRegexp: "^foo=(?P<v0>[0-9]+)$",
title: "Queries route with empty value and empty parameter in request, should match", shouldMatch: true,
route: new(Route).Queries("foo", ""), },
request: newRequest("GET", "http://localhost?foo="), {
vars: map[string]string{}, title: "Queries route with hyphenated name and pattern with quantifier, additional capturing group",
host: "", route: new(Route).Queries("foo", "{v-1:[0-9]{1}(?:a|b)}"),
path: "", request: newRequest("GET", "http://localhost?foo=1a"),
query: "foo=", vars: map[string]string{"v-1": "1a"},
shouldMatch: true, host: "",
}, path: "",
{ query: "foo=1a",
title: "Queries route with overlapping value, should not match", queriesTemplate: "foo={v-1:[0-9]{1}(?:a|b)}",
route: new(Route).Queries("foo", "bar"), queriesRegexp: "^foo=(?P<v0>[0-9]{1}(?:a|b))$",
request: newRequest("GET", "http://localhost?foo=barfoo"), shouldMatch: true,
vars: map[string]string{}, },
host: "", {
path: "", title: "Queries route with empty value, should match",
shouldMatch: false, route: new(Route).Queries("foo", ""),
}, request: newRequest("GET", "http://localhost?foo=bar"),
{ vars: map[string]string{},
title: "Queries route with no parameter in request, should not match", host: "",
route: new(Route).Queries("foo", "{bar}"), path: "",
request: newRequest("GET", "http://localhost"), query: "foo=",
vars: map[string]string{}, queriesTemplate: "foo=",
host: "", queriesRegexp: "^foo=.*$",
path: "", shouldMatch: true,
shouldMatch: false, },
}, {
{ title: "Queries route with empty value and no parameter in request, should not match",
title: "Queries route with empty parameter in request, should match", route: new(Route).Queries("foo", ""),
route: new(Route).Queries("foo", "{bar}"), request: newRequest("GET", "http://localhost"),
request: newRequest("GET", "http://localhost?foo="), vars: map[string]string{},
vars: map[string]string{"foo": ""}, host: "",
host: "", path: "",
path: "", queriesTemplate: "foo=",
query: "foo=", queriesRegexp: "^foo=.*$",
shouldMatch: true, shouldMatch: false,
}, },
{ {
title: "Queries route, bad submatch", title: "Queries route with empty value and empty parameter in request, should match",
route: new(Route).Queries("foo", "bar", "baz", "ding"), route: new(Route).Queries("foo", ""),
request: newRequest("GET", "http://localhost?fffoo=bar&baz=dingggg"), request: newRequest("GET", "http://localhost?foo="),
vars: map[string]string{}, vars: map[string]string{},
host: "", host: "",
path: "", path: "",
shouldMatch: false, query: "foo=",
}, queriesTemplate: "foo=",
{ queriesRegexp: "^foo=.*$",
title: "Queries route with pattern, match, escaped value", shouldMatch: true,
route: new(Route).Queries("foo", "{v1}"), },
request: newRequest("GET", "http://localhost?foo=%25bar%26%20%2F%3D%3F"), {
vars: map[string]string{"v1": "%bar& /=?"}, title: "Queries route with overlapping value, should not match",
host: "", route: new(Route).Queries("foo", "bar"),
path: "", request: newRequest("GET", "http://localhost?foo=barfoo"),
query: "foo=%25bar%26+%2F%3D%3F", vars: map[string]string{},
shouldMatch: true, host: "",
path: "",
queriesTemplate: "foo=bar",
queriesRegexp: "^foo=bar$",
shouldMatch: false,
},
{
title: "Queries route with no parameter in request, should not match",
route: new(Route).Queries("foo", "{bar}"),
request: newRequest("GET", "http://localhost"),
vars: map[string]string{},
host: "",
path: "",
queriesTemplate: "foo={bar}",
queriesRegexp: "^foo=(?P<v0>.*)$",
shouldMatch: false,
},
{
title: "Queries route with empty parameter in request, should match",
route: new(Route).Queries("foo", "{bar}"),
request: newRequest("GET", "http://localhost?foo="),
vars: map[string]string{"foo": ""},
host: "",
path: "",
query: "foo=",
queriesTemplate: "foo={bar}",
queriesRegexp: "^foo=(?P<v0>.*)$",
shouldMatch: true,
},
{
title: "Queries route, bad submatch",
route: new(Route).Queries("foo", "bar", "baz", "ding"),
request: newRequest("GET", "http://localhost?fffoo=bar&baz=dingggg"),
vars: map[string]string{},
host: "",
path: "",
queriesTemplate: "foo=bar,baz=ding",
queriesRegexp: "^foo=bar$,^baz=ding$",
shouldMatch: false,
},
{
title: "Queries route with pattern, match, escaped value",
route: new(Route).Queries("foo", "{v1}"),
request: newRequest("GET", "http://localhost?foo=%25bar%26%20%2F%3D%3F"),
vars: map[string]string{"v1": "%bar& /=?"},
host: "",
path: "",
query: "foo=%25bar%26+%2F%3D%3F",
queriesTemplate: "foo={v1}",
queriesRegexp: "^foo=(?P<v0>.*)$",
shouldMatch: true,
}, },
} }
for _, test := range tests { for _, test := range tests {
testRoute(t, test) testRoute(t, test)
testTemplate(t, test) testTemplate(t, test)
testQueriesTemplates(t, test)
testUseEscapedRoute(t, test) testUseEscapedRoute(t, test)
testQueriesRegexp(t, test)
} }
} }
@ -1717,6 +1771,24 @@ func testRegexp(t *testing.T, test routeTest) {
} }
} }
func testQueriesRegexp(t *testing.T, test routeTest) {
route := test.route
queries, queriesErr := route.GetQueriesRegexp()
gotQueries := strings.Join(queries, ",")
if test.queriesRegexp != "" && queriesErr == nil && gotQueries != test.queriesRegexp {
t.Errorf("(%v) GetQueriesRegexp not equal: expected %v, got %v", test.title, test.queriesRegexp, gotQueries)
}
}
func testQueriesTemplates(t *testing.T, test routeTest) {
route := test.route
queries, queriesErr := route.GetQueriesTemplates()
gotQueries := strings.Join(queries, ",")
if test.queriesTemplate != "" && queriesErr == nil && gotQueries != test.queriesTemplate {
t.Errorf("(%v) GetQueriesTemplates not equal: expected %v, got %v", test.title, test.queriesTemplate, gotQueries)
}
}
type TestA301ResponseWriter struct { type TestA301ResponseWriter struct {
hh http.Header hh http.Header
status int status int

38
route.go

@ -608,6 +608,44 @@ func (r *Route) GetPathRegexp() (string, error) {
return r.regexp.path.regexp.String(), nil return r.regexp.path.regexp.String(), nil
} }
// GetQueriesRegexp returns the expanded regular expressions used to match the
// route queries.
// This is useful for building simple REST API documentation and for instrumentation
// against third-party services.
// An empty list will be returned if the route does not have queries.
func (r *Route) GetQueriesRegexp() ([]string, error) {
if r.err != nil {
return nil, r.err
}
if r.regexp == nil || r.regexp.queries == nil {
return nil, errors.New("mux: route doesn't have queries")
}
var queries []string
for _, query := range r.regexp.queries {
queries = append(queries, query.regexp.String())
}
return queries, nil
}
// GetQueriesTemplates returns the templates used to build the
// query matching.
// This is useful for building simple REST API documentation and for instrumentation
// against third-party services.
// An empty list will be returned if the route does not define queries.
func (r *Route) GetQueriesTemplates() ([]string, error) {
if r.err != nil {
return nil, r.err
}
if r.regexp == nil || r.regexp.queries == nil {
return nil, errors.New("mux: route doesn't have queries")
}
var queries []string
for _, query := range r.regexp.queries {
queries = append(queries, query.template)
}
return queries, nil
}
// GetMethods returns the methods the route matches against // GetMethods returns the methods the route matches against
// This is useful for building simple REST API documentation and for instrumentation // This is useful for building simple REST API documentation and for instrumentation
// against third-party services. // against third-party services.

Loading…
Cancel
Save