Browse Source

Merge 11231c0e93 into 91708ff8e3

pull/662/merge
Francesco Mari 4 years ago committed by GitHub
parent
commit
c6b5acca7e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 16
      mux.go
  2. 17
      mux_test.go
  3. 18
      regexp.go
  4. 1
      route.go

16
mux.go

@ -84,6 +84,8 @@ type routeConf struct { @@ -84,6 +84,8 @@ type routeConf struct {
// will not redirect
skipClean bool
unescapeVars bool
// Manager for the variables from host and path.
regexp routeRegexpGroup
@ -260,6 +262,20 @@ func (r *Router) SkipClean(value bool) *Router { @@ -260,6 +262,20 @@ func (r *Router) SkipClean(value bool) *Router {
return r
}
// UnescapeVars tells the router to escape the route variables before invoking
// the handler. This is useful when used together with UseEncodedPath to avoid
// un-escaping the variable values in the handler.
//
// For example, if the router is configured only with UseEncodedPath(), and
// "/path/foo%2Fbar/to" matches the path template "/path/{var}/to", your handler
// will receive the value "foo%2Fbar" for the variable "var". Instead, if the
// router is configured with both UseEncodedPath() and UnescapeVars(), the value
// for the variable "var" will be "foo/bar".
func (r *Router) UnescapeVars() *Router {
r.unescapeVars = true
return r
}
// UseEncodedPath tells the router to match the encoded original path
// to the routes.
// For eg. "/path/foo%2Fbar/to" will match the path "/path/{var}/to".

17
mux_test.go

@ -1540,13 +1540,10 @@ func TestStrictSlash(t *testing.T) { @@ -1540,13 +1540,10 @@ func TestStrictSlash(t *testing.T) {
}
func TestUseEncodedPath(t *testing.T) {
r := NewRouter()
r.UseEncodedPath()
tests := []routeTest{
{
title: "Router with useEncodedPath, URL with encoded slash does match",
route: r.NewRoute().Path("/v1/{v1}/v2"),
route: NewRouter().UseEncodedPath().NewRoute().Path("/v1/{v1}/v2"),
request: newRequest("GET", "http://localhost/v1/1%2F2/v2"),
vars: map[string]string{"v1": "1%2F2"},
host: "",
@ -1554,9 +1551,19 @@ func TestUseEncodedPath(t *testing.T) { @@ -1554,9 +1551,19 @@ func TestUseEncodedPath(t *testing.T) {
pathTemplate: `/v1/{v1}/v2`,
shouldMatch: true,
},
{
title: "Router with useEncodedPath, URL with encoded slash does match, variables decoded",
route: NewRouter().UseEncodedPath().UnescapeVars().NewRoute().Path("/v1/{v1}/v2"),
request: newRequest("GET", "http://localhost/v1/1%2F2/v2"),
vars: map[string]string{"v1": "1/2"},
host: "",
path: "/v1/1%2F2/v2",
pathTemplate: `/v1/{v1}/v2`,
shouldMatch: true,
},
{
title: "Router with useEncodedPath, URL with encoded slash doesn't match",
route: r.NewRoute().Path("/v1/1/2/v2"),
route: NewRouter().UseEncodedPath().NewRoute().Path("/v1/1/2/v2"),
request: newRequest("GET", "http://localhost/v1/1%2F2/v2"),
vars: map[string]string{"v1": "1%2F2"},
host: "",

18
regexp.go

@ -17,6 +17,7 @@ import ( @@ -17,6 +17,7 @@ import (
type routeRegexpOptions struct {
strictSlash bool
useEncodedPath bool
unescapeVars bool
}
type regexpType int
@ -204,8 +205,12 @@ func (r *routeRegexp) url(values map[string]string) (string, error) { @@ -204,8 +205,12 @@ func (r *routeRegexp) url(values map[string]string) (string, error) {
if r.regexpType == regexpTypeQuery {
value = url.QueryEscape(value)
}
if r.options.unescapeVars {
urlValues[k] = url.PathEscape(value)
} else {
urlValues[k] = value
}
}
rv := fmt.Sprintf(r.reverse, urlValues...)
if !r.regexp.MatchString(rv) {
// The URL is checked against the full regexp, instead of checking
@ -345,6 +350,9 @@ func (v routeRegexpGroup) setMatch(req *http.Request, m *RouteMatch, r *Route) { @@ -345,6 +350,9 @@ func (v routeRegexpGroup) setMatch(req *http.Request, m *RouteMatch, r *Route) {
matches := v.path.regexp.FindStringSubmatchIndex(path)
if len(matches) > 0 {
extractVars(path, matches, v.path.varsN, m.Vars)
if r.unescapeVars {
unescapeVars(m.Vars)
}
// Check if we should redirect.
if v.path.options.strictSlash {
p1 := strings.HasSuffix(path, "/")
@ -386,3 +394,13 @@ func extractVars(input string, matches []int, names []string, output map[string] @@ -386,3 +394,13 @@ func extractVars(input string, matches []int, names []string, output map[string]
output[name] = input[matches[2*i+2]:matches[2*i+3]]
}
}
func unescapeVars(vars map[string]string) {
for k, v := range vars {
if decoded, err := url.PathUnescape(v); err != nil {
vars[k] = v
} else {
vars[k] = decoded
}
}
}

1
route.go

@ -186,6 +186,7 @@ func (r *Route) addRegexpMatcher(tpl string, typ regexpType) error { @@ -186,6 +186,7 @@ func (r *Route) addRegexpMatcher(tpl string, typ regexpType) error {
rr, err := newRouteRegexp(tpl, typ, routeRegexpOptions{
strictSlash: r.strictSlash,
useEncodedPath: r.useEncodedPath,
unescapeVars: r.unescapeVars,
})
if err != nil {
return err

Loading…
Cancel
Save