GetQueryTemplates and GetQueryRegexp extraction (#304)
Developers can now extract the query templates and regexps from a router as lists of combined query pairs.
This commit is contained in:
committed by
Kamil Kisiel
parent
9bd9ff2d1d
commit
10490f55fa
28
README.md
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
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|||||||
492
mux_test.go
492
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",
|
title: "Queries route, match with a query string",
|
||||||
route: new(Route).Host("www.example.com").Path("/api").Queries("foo", "bar", "baz", "ding"),
|
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"),
|
request: newRequest("GET", "http://www.example.com/api?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",
|
||||||
pathTemplate: `/api`,
|
pathTemplate: `/api`,
|
||||||
hostTemplate: `www.example.com`,
|
hostTemplate: `www.example.com`,
|
||||||
shouldMatch: true,
|
queriesTemplate: "foo=bar,baz=ding",
|
||||||
|
queriesRegexp: "^foo=bar$,^baz=ding$",
|
||||||
|
shouldMatch: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Queries route, match with a query string out of order",
|
title: "Queries route, match with a query string out of order",
|
||||||
route: new(Route).Host("www.example.com").Path("/api").Queries("foo", "bar", "baz", "ding"),
|
route: new(Route).Host("www.example.com").Path("/api").Queries("foo", "bar", "baz", "ding"),
|
||||||
request: newRequest("GET", "http://www.example.com/api?baz=ding&foo=bar"),
|
request: newRequest("GET", "http://www.example.com/api?baz=ding&foo=bar"),
|
||||||
vars: map[string]string{},
|
vars: map[string]string{},
|
||||||
host: "",
|
host: "",
|
||||||
path: "",
|
path: "",
|
||||||
query: "foo=bar&baz=ding",
|
query: "foo=bar&baz=ding",
|
||||||
pathTemplate: `/api`,
|
pathTemplate: `/api`,
|
||||||
hostTemplate: `www.example.com`,
|
hostTemplate: `www.example.com`,
|
||||||
shouldMatch: true,
|
queriesTemplate: "foo=bar,baz=ding",
|
||||||
|
queriesRegexp: "^foo=bar$,^baz=ding$",
|
||||||
|
shouldMatch: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Queries route, bad query",
|
title: "Queries route, bad query",
|
||||||
route: new(Route).Queries("foo", "bar", "baz", "ding"),
|
route: new(Route).Queries("foo", "bar", "baz", "ding"),
|
||||||
request: newRequest("GET", "http://localhost?foo=bar&baz=dong"),
|
request: newRequest("GET", "http://localhost?foo=bar&baz=dong"),
|
||||||
vars: map[string]string{},
|
vars: map[string]string{},
|
||||||
host: "",
|
host: "",
|
||||||
path: "",
|
path: "",
|
||||||
shouldMatch: false,
|
queriesTemplate: "foo=bar,baz=ding",
|
||||||
|
queriesRegexp: "^foo=bar$,^baz=ding$",
|
||||||
|
shouldMatch: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Queries route with pattern, match",
|
title: "Queries route with pattern, match",
|
||||||
route: new(Route).Queries("foo", "{v1}"),
|
route: new(Route).Queries("foo", "{v1}"),
|
||||||
request: newRequest("GET", "http://localhost?foo=bar"),
|
request: newRequest("GET", "http://localhost?foo=bar"),
|
||||||
vars: map[string]string{"v1": "bar"},
|
vars: map[string]string{"v1": "bar"},
|
||||||
host: "",
|
host: "",
|
||||||
path: "",
|
path: "",
|
||||||
query: "foo=bar",
|
query: "foo=bar",
|
||||||
shouldMatch: true,
|
queriesTemplate: "foo={v1}",
|
||||||
|
queriesRegexp: "^foo=(?P<v0>.*)$",
|
||||||
|
shouldMatch: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Queries route with multiple patterns, match",
|
title: "Queries route with multiple patterns, match",
|
||||||
route: new(Route).Queries("foo", "{v1}", "baz", "{v2}"),
|
route: new(Route).Queries("foo", "{v1}", "baz", "{v2}"),
|
||||||
request: newRequest("GET", "http://localhost?foo=bar&baz=ding"),
|
request: newRequest("GET", "http://localhost?foo=bar&baz=ding"),
|
||||||
vars: map[string]string{"v1": "bar", "v2": "ding"},
|
vars: map[string]string{"v1": "bar", "v2": "ding"},
|
||||||
host: "",
|
host: "",
|
||||||
path: "",
|
path: "",
|
||||||
query: "foo=bar&baz=ding",
|
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, match",
|
title: "Queries route with regexp pattern, match",
|
||||||
route: new(Route).Queries("foo", "{v1:[0-9]+}"),
|
route: new(Route).Queries("foo", "{v1:[0-9]+}"),
|
||||||
request: newRequest("GET", "http://localhost?foo=10"),
|
request: newRequest("GET", "http://localhost?foo=10"),
|
||||||
vars: map[string]string{"v1": "10"},
|
vars: map[string]string{"v1": "10"},
|
||||||
host: "",
|
host: "",
|
||||||
path: "",
|
path: "",
|
||||||
query: "foo=10",
|
query: "foo=10",
|
||||||
shouldMatch: true,
|
queriesTemplate: "foo={v1:[0-9]+}",
|
||||||
|
queriesRegexp: "^foo=(?P<v0>[0-9]+)$",
|
||||||
|
shouldMatch: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Queries route with regexp pattern, regexp does not match",
|
title: "Queries route with regexp pattern, regexp does not match",
|
||||||
route: new(Route).Queries("foo", "{v1:[0-9]+}"),
|
route: new(Route).Queries("foo", "{v1:[0-9]+}"),
|
||||||
request: newRequest("GET", "http://localhost?foo=a"),
|
request: newRequest("GET", "http://localhost?foo=a"),
|
||||||
vars: map[string]string{},
|
vars: map[string]string{},
|
||||||
host: "",
|
host: "",
|
||||||
path: "",
|
path: "",
|
||||||
shouldMatch: false,
|
queriesTemplate: "foo={v1:[0-9]+}",
|
||||||
|
queriesRegexp: "^foo=(?P<v0>[0-9]+)$",
|
||||||
|
shouldMatch: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Queries route with regexp pattern with quantifier, match",
|
title: "Queries route with regexp pattern with quantifier, match",
|
||||||
route: new(Route).Queries("foo", "{v1:[0-9]{1}}"),
|
route: new(Route).Queries("foo", "{v1:[0-9]{1}}"),
|
||||||
request: newRequest("GET", "http://localhost?foo=1"),
|
request: newRequest("GET", "http://localhost?foo=1"),
|
||||||
vars: map[string]string{"v1": "1"},
|
vars: map[string]string{"v1": "1"},
|
||||||
host: "",
|
host: "",
|
||||||
path: "",
|
path: "",
|
||||||
query: "foo=1",
|
query: "foo=1",
|
||||||
shouldMatch: true,
|
queriesTemplate: "foo={v1:[0-9]{1}}",
|
||||||
|
queriesRegexp: "^foo=(?P<v0>[0-9]{1})$",
|
||||||
|
shouldMatch: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Queries route with regexp pattern with quantifier, additional variable in query string, match",
|
title: "Queries route with regexp pattern with quantifier, additional variable in query string, match",
|
||||||
route: new(Route).Queries("foo", "{v1:[0-9]{1}}"),
|
route: new(Route).Queries("foo", "{v1:[0-9]{1}}"),
|
||||||
request: newRequest("GET", "http://localhost?bar=2&foo=1"),
|
request: newRequest("GET", "http://localhost?bar=2&foo=1"),
|
||||||
vars: map[string]string{"v1": "1"},
|
vars: map[string]string{"v1": "1"},
|
||||||
host: "",
|
host: "",
|
||||||
path: "",
|
path: "",
|
||||||
query: "foo=1",
|
query: "foo=1",
|
||||||
shouldMatch: true,
|
queriesTemplate: "foo={v1:[0-9]{1}}",
|
||||||
|
queriesRegexp: "^foo=(?P<v0>[0-9]{1})$",
|
||||||
|
shouldMatch: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Queries route with regexp pattern with quantifier, regexp does not match",
|
title: "Queries route with regexp pattern with quantifier, regexp does not match",
|
||||||
route: new(Route).Queries("foo", "{v1:[0-9]{1}}"),
|
route: new(Route).Queries("foo", "{v1:[0-9]{1}}"),
|
||||||
request: newRequest("GET", "http://localhost?foo=12"),
|
request: newRequest("GET", "http://localhost?foo=12"),
|
||||||
vars: map[string]string{},
|
vars: map[string]string{},
|
||||||
host: "",
|
host: "",
|
||||||
path: "",
|
path: "",
|
||||||
shouldMatch: false,
|
queriesTemplate: "foo={v1:[0-9]{1}}",
|
||||||
|
queriesRegexp: "^foo=(?P<v0>[0-9]{1})$",
|
||||||
|
shouldMatch: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Queries route with regexp pattern with quantifier, additional capturing group",
|
title: "Queries route with regexp pattern with quantifier, additional capturing group",
|
||||||
route: new(Route).Queries("foo", "{v1:[0-9]{1}(?:a|b)}"),
|
route: new(Route).Queries("foo", "{v1:[0-9]{1}(?:a|b)}"),
|
||||||
request: newRequest("GET", "http://localhost?foo=1a"),
|
request: newRequest("GET", "http://localhost?foo=1a"),
|
||||||
vars: map[string]string{"v1": "1a"},
|
vars: map[string]string{"v1": "1a"},
|
||||||
host: "",
|
host: "",
|
||||||
path: "",
|
path: "",
|
||||||
query: "foo=1a",
|
query: "foo=1a",
|
||||||
shouldMatch: true,
|
queriesTemplate: "foo={v1:[0-9]{1}(?:a|b)}",
|
||||||
|
queriesRegexp: "^foo=(?P<v0>[0-9]{1}(?:a|b))$",
|
||||||
|
shouldMatch: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Queries route with regexp pattern with quantifier, additional variable in query string, regexp does not match",
|
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}}"),
|
route: new(Route).Queries("foo", "{v1:[0-9]{1}}"),
|
||||||
request: newRequest("GET", "http://localhost?foo=12"),
|
request: newRequest("GET", "http://localhost?foo=12"),
|
||||||
vars: map[string]string{},
|
vars: map[string]string{},
|
||||||
host: "",
|
host: "",
|
||||||
path: "",
|
path: "",
|
||||||
shouldMatch: false,
|
queriesTemplate: "foo={v1:[0-9]{1}}",
|
||||||
|
queriesRegexp: "^foo=(?P<v0>[0-9]{1})$",
|
||||||
|
shouldMatch: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Queries route with hyphenated name, match",
|
title: "Queries route with hyphenated name, match",
|
||||||
route: new(Route).Queries("foo", "{v-1}"),
|
route: new(Route).Queries("foo", "{v-1}"),
|
||||||
request: newRequest("GET", "http://localhost?foo=bar"),
|
request: newRequest("GET", "http://localhost?foo=bar"),
|
||||||
vars: map[string]string{"v-1": "bar"},
|
vars: map[string]string{"v-1": "bar"},
|
||||||
host: "",
|
host: "",
|
||||||
path: "",
|
path: "",
|
||||||
query: "foo=bar",
|
query: "foo=bar",
|
||||||
shouldMatch: true,
|
queriesTemplate: "foo={v-1}",
|
||||||
|
queriesRegexp: "^foo=(?P<v0>.*)$",
|
||||||
|
shouldMatch: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Queries route with multiple hyphenated names, match",
|
title: "Queries route with multiple hyphenated names, match",
|
||||||
route: new(Route).Queries("foo", "{v-1}", "baz", "{v-2}"),
|
route: new(Route).Queries("foo", "{v-1}", "baz", "{v-2}"),
|
||||||
request: newRequest("GET", "http://localhost?foo=bar&baz=ding"),
|
request: newRequest("GET", "http://localhost?foo=bar&baz=ding"),
|
||||||
vars: map[string]string{"v-1": "bar", "v-2": "ding"},
|
vars: map[string]string{"v-1": "bar", "v-2": "ding"},
|
||||||
host: "",
|
host: "",
|
||||||
path: "",
|
path: "",
|
||||||
query: "foo=bar&baz=ding",
|
query: "foo=bar&baz=ding",
|
||||||
shouldMatch: true,
|
queriesTemplate: "foo={v-1},baz={v-2}",
|
||||||
|
queriesRegexp: "^foo=(?P<v0>.*)$,^baz=(?P<v0>.*)$",
|
||||||
|
shouldMatch: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Queries route with hyphenate name and pattern, match",
|
title: "Queries route with hyphenate name and pattern, match",
|
||||||
route: new(Route).Queries("foo", "{v-1:[0-9]+}"),
|
route: new(Route).Queries("foo", "{v-1:[0-9]+}"),
|
||||||
request: newRequest("GET", "http://localhost?foo=10"),
|
request: newRequest("GET", "http://localhost?foo=10"),
|
||||||
vars: map[string]string{"v-1": "10"},
|
vars: map[string]string{"v-1": "10"},
|
||||||
host: "",
|
host: "",
|
||||||
path: "",
|
path: "",
|
||||||
query: "foo=10",
|
query: "foo=10",
|
||||||
shouldMatch: true,
|
queriesTemplate: "foo={v-1:[0-9]+}",
|
||||||
|
queriesRegexp: "^foo=(?P<v0>[0-9]+)$",
|
||||||
|
shouldMatch: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Queries route with hyphenated name and pattern with quantifier, additional capturing group",
|
title: "Queries route with hyphenated name and pattern with quantifier, additional capturing group",
|
||||||
route: new(Route).Queries("foo", "{v-1:[0-9]{1}(?:a|b)}"),
|
route: new(Route).Queries("foo", "{v-1:[0-9]{1}(?:a|b)}"),
|
||||||
request: newRequest("GET", "http://localhost?foo=1a"),
|
request: newRequest("GET", "http://localhost?foo=1a"),
|
||||||
vars: map[string]string{"v-1": "1a"},
|
vars: map[string]string{"v-1": "1a"},
|
||||||
host: "",
|
host: "",
|
||||||
path: "",
|
path: "",
|
||||||
query: "foo=1a",
|
query: "foo=1a",
|
||||||
shouldMatch: true,
|
queriesTemplate: "foo={v-1:[0-9]{1}(?:a|b)}",
|
||||||
|
queriesRegexp: "^foo=(?P<v0>[0-9]{1}(?:a|b))$",
|
||||||
|
shouldMatch: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Queries route with empty value, should match",
|
title: "Queries route with empty value, should match",
|
||||||
route: new(Route).Queries("foo", ""),
|
route: new(Route).Queries("foo", ""),
|
||||||
request: newRequest("GET", "http://localhost?foo=bar"),
|
request: newRequest("GET", "http://localhost?foo=bar"),
|
||||||
vars: map[string]string{},
|
vars: map[string]string{},
|
||||||
host: "",
|
host: "",
|
||||||
path: "",
|
path: "",
|
||||||
query: "foo=",
|
query: "foo=",
|
||||||
shouldMatch: true,
|
queriesTemplate: "foo=",
|
||||||
|
queriesRegexp: "^foo=.*$",
|
||||||
|
shouldMatch: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Queries route with empty value and no parameter in request, should not match",
|
title: "Queries route with empty value and no parameter in request, should not match",
|
||||||
route: new(Route).Queries("foo", ""),
|
route: new(Route).Queries("foo", ""),
|
||||||
request: newRequest("GET", "http://localhost"),
|
request: newRequest("GET", "http://localhost"),
|
||||||
vars: map[string]string{},
|
vars: map[string]string{},
|
||||||
host: "",
|
host: "",
|
||||||
path: "",
|
path: "",
|
||||||
shouldMatch: false,
|
queriesTemplate: "foo=",
|
||||||
|
queriesRegexp: "^foo=.*$",
|
||||||
|
shouldMatch: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Queries route with empty value and empty parameter in request, should match",
|
title: "Queries route with empty value and empty parameter in request, should match",
|
||||||
route: new(Route).Queries("foo", ""),
|
route: new(Route).Queries("foo", ""),
|
||||||
request: newRequest("GET", "http://localhost?foo="),
|
request: newRequest("GET", "http://localhost?foo="),
|
||||||
vars: map[string]string{},
|
vars: map[string]string{},
|
||||||
host: "",
|
host: "",
|
||||||
path: "",
|
path: "",
|
||||||
query: "foo=",
|
query: "foo=",
|
||||||
shouldMatch: true,
|
queriesTemplate: "foo=",
|
||||||
|
queriesRegexp: "^foo=.*$",
|
||||||
|
shouldMatch: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Queries route with overlapping value, should not match",
|
title: "Queries route with overlapping value, should not match",
|
||||||
route: new(Route).Queries("foo", "bar"),
|
route: new(Route).Queries("foo", "bar"),
|
||||||
request: newRequest("GET", "http://localhost?foo=barfoo"),
|
request: newRequest("GET", "http://localhost?foo=barfoo"),
|
||||||
vars: map[string]string{},
|
vars: map[string]string{},
|
||||||
host: "",
|
host: "",
|
||||||
path: "",
|
path: "",
|
||||||
shouldMatch: false,
|
queriesTemplate: "foo=bar",
|
||||||
|
queriesRegexp: "^foo=bar$",
|
||||||
|
shouldMatch: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Queries route with no parameter in request, should not match",
|
title: "Queries route with no parameter in request, should not match",
|
||||||
route: new(Route).Queries("foo", "{bar}"),
|
route: new(Route).Queries("foo", "{bar}"),
|
||||||
request: newRequest("GET", "http://localhost"),
|
request: newRequest("GET", "http://localhost"),
|
||||||
vars: map[string]string{},
|
vars: map[string]string{},
|
||||||
host: "",
|
host: "",
|
||||||
path: "",
|
path: "",
|
||||||
shouldMatch: false,
|
queriesTemplate: "foo={bar}",
|
||||||
|
queriesRegexp: "^foo=(?P<v0>.*)$",
|
||||||
|
shouldMatch: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Queries route with empty parameter in request, should match",
|
title: "Queries route with empty parameter in request, should match",
|
||||||
route: new(Route).Queries("foo", "{bar}"),
|
route: new(Route).Queries("foo", "{bar}"),
|
||||||
request: newRequest("GET", "http://localhost?foo="),
|
request: newRequest("GET", "http://localhost?foo="),
|
||||||
vars: map[string]string{"foo": ""},
|
vars: map[string]string{"foo": ""},
|
||||||
host: "",
|
host: "",
|
||||||
path: "",
|
path: "",
|
||||||
query: "foo=",
|
query: "foo=",
|
||||||
shouldMatch: true,
|
queriesTemplate: "foo={bar}",
|
||||||
|
queriesRegexp: "^foo=(?P<v0>.*)$",
|
||||||
|
shouldMatch: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Queries route, bad submatch",
|
title: "Queries route, bad submatch",
|
||||||
route: new(Route).Queries("foo", "bar", "baz", "ding"),
|
route: new(Route).Queries("foo", "bar", "baz", "ding"),
|
||||||
request: newRequest("GET", "http://localhost?fffoo=bar&baz=dingggg"),
|
request: newRequest("GET", "http://localhost?fffoo=bar&baz=dingggg"),
|
||||||
vars: map[string]string{},
|
vars: map[string]string{},
|
||||||
host: "",
|
host: "",
|
||||||
path: "",
|
path: "",
|
||||||
shouldMatch: false,
|
queriesTemplate: "foo=bar,baz=ding",
|
||||||
|
queriesRegexp: "^foo=bar$,^baz=ding$",
|
||||||
|
shouldMatch: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Queries route with pattern, match, escaped value",
|
title: "Queries route with pattern, match, escaped value",
|
||||||
route: new(Route).Queries("foo", "{v1}"),
|
route: new(Route).Queries("foo", "{v1}"),
|
||||||
request: newRequest("GET", "http://localhost?foo=%25bar%26%20%2F%3D%3F"),
|
request: newRequest("GET", "http://localhost?foo=%25bar%26%20%2F%3D%3F"),
|
||||||
vars: map[string]string{"v1": "%bar& /=?"},
|
vars: map[string]string{"v1": "%bar& /=?"},
|
||||||
host: "",
|
host: "",
|
||||||
path: "",
|
path: "",
|
||||||
query: "foo=%25bar%26+%2F%3D%3F",
|
query: "foo=%25bar%26+%2F%3D%3F",
|
||||||
shouldMatch: true,
|
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
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.
|
||||||
|
|||||||
Reference in New Issue
Block a user