diff --git a/mux_test.go b/mux_test.go index 6b2c1d2..44cc57e 100644 --- a/mux_test.go +++ b/mux_test.go @@ -552,6 +552,24 @@ func TestQueries(t *testing.T) { path: "", shouldMatch: false, }, + { + title: "Queries route with regexp pattern with quantifier, match", + route: new(Route).Queries("foo", "{v1:[0-9]{1}}"), + request: newRequest("GET", "http://localhost?foo=1"), + vars: map[string]string{"v1": "1"}, + host: "", + path: "", + shouldMatch: true, + }, + { + title: "Queries route with regexp pattern with quantifier, regexp does not match", + route: new(Route).Queries("foo", "{v1:[0-9]{1}}"), + request: newRequest("GET", "http://localhost?foo=12"), + vars: map[string]string{}, + host: "", + path: "", + shouldMatch: false, + }, } for _, test := range tests { diff --git a/regexp.go b/regexp.go index aa30679..8838727 100644 --- a/regexp.go +++ b/regexp.go @@ -35,7 +35,6 @@ func newRouteRegexp(tpl string, matchHost, matchPrefix, matchQuery, strictSlash defaultPattern := "[^/]+" if matchQuery { defaultPattern = "[^?&]+" - matchPrefix = true } else if matchHost { defaultPattern = "[^.]+" matchPrefix = false @@ -53,9 +52,7 @@ func newRouteRegexp(tpl string, matchHost, matchPrefix, matchQuery, strictSlash varsN := make([]string, len(idxs)/2) varsR := make([]*regexp.Regexp, len(idxs)/2) pattern := bytes.NewBufferString("") - if !matchQuery { - pattern.WriteByte('^') - } + pattern.WriteByte('^') reverse := bytes.NewBufferString("") var end int var err error @@ -78,6 +75,7 @@ func newRouteRegexp(tpl string, matchHost, matchPrefix, matchQuery, strictSlash fmt.Fprintf(pattern, "%s(%s)", regexp.QuoteMeta(raw), patt) // Build the reverse template. fmt.Fprintf(reverse, "%s%%s", raw) + // Append variable name and compiled pattern. varsN[i/2] = name varsR[i/2], err = regexp.Compile(fmt.Sprintf("^%s$", patt)) @@ -141,7 +139,7 @@ type routeRegexp struct { func (r *routeRegexp) Match(req *http.Request, match *RouteMatch) bool { if !r.matchHost { if r.matchQuery { - return r.regexp.MatchString(req.URL.RawQuery) + return r.regexp.MatchString(r.getUrlQuery(req)) } else { return r.regexp.MatchString(req.URL.Path) } @@ -175,6 +173,18 @@ func (r *routeRegexp) url(values map[string]string) (string, error) { return rv, nil } +// getUrlQuery returns a single query parameter from a request URL. +// For a URL with foo=bar&baz=ding, we return only the relevant key +// value pair for the routeRegexp. +func (r *routeRegexp) getUrlQuery(req *http.Request) string { + keyVal := strings.Split(r.template, "=") + if len(keyVal) == 0 { + return "" + } + re := regexp.MustCompile(keyVal[0] + "[^&]*") + return re.FindString(req.URL.RawQuery) +} + // braceIndices returns the first level curly brace indices from a string. // It returns an error in case of unbalanced braces. func braceIndices(s string) ([]int, error) { @@ -246,9 +256,8 @@ func (v *routeRegexpGroup) setMatch(req *http.Request, m *RouteMatch, r *Route) } } // Store query string variables. - rawQuery := req.URL.RawQuery for _, q := range v.queries { - queryVars := q.regexp.FindStringSubmatch(rawQuery) + queryVars := q.regexp.FindStringSubmatch(q.getUrlQuery(req)) if queryVars != nil { for k, v := range q.varsN { m.Vars[v] = queryVars[k+1] diff --git a/route.go b/route.go index 00d2300..6cb12d3 100644 --- a/route.go +++ b/route.go @@ -336,7 +336,7 @@ func (r *Route) Queries(pairs ...string) *Route { return nil } for i := 0; i < length; i += 2 { - if r.err = r.addRegexpMatcher(pairs[i]+"="+pairs[i+1], false, true, true); r.err != nil { + if r.err = r.addRegexpMatcher(pairs[i]+"="+pairs[i+1], false, false, true); r.err != nil { return r } }