Skip to content

Commit f527679

Browse files
author
Kush Mansingh
committed
Add mechanism to route based on the escaped path
1 parent 7804150 commit f527679

File tree

3 files changed

+31
-6
lines changed

3 files changed

+31
-6
lines changed

mux.go

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,9 @@ func (r *Router) Match(req *http.Request, match *RouteMatch) bool {
7676
// mux.Vars(request).
7777
func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
7878
if !r.skipClean {
79+
path := getPath(req)
7980
// Clean path to canonical form and redirect.
80-
if p := cleanPath(req.URL.Path); p != req.URL.Path {
81+
if p := cleanPath(path); p != path {
8182

8283
// Added 3 lines (Philip Schlump) - It was dropping the query string and #whatever from query.
8384
// This matches with fix in go 1.2 r.c. 4 for same problem. Go Issue:
@@ -358,6 +359,19 @@ func setCurrentRoute(r *http.Request, val interface{}) *http.Request {
358359
// Helpers
359360
// ----------------------------------------------------------------------------
360361

362+
// getPath returns the escaped path if possible; URL.EscapedPath() was added
363+
// in golang 1.5.
364+
func getPath(req *http.Request) string {
365+
path := req.URL.Path
366+
var urlForChecking interface{} = req.URL
367+
if urlWithPath, ok := urlForChecking.(interface {
368+
EscapedPath() string
369+
}); ok {
370+
path = urlWithPath.EscapedPath()
371+
}
372+
return path
373+
}
374+
361375
// cleanPath returns the canonical path for p, eliminating . and .. elements.
362376
// Borrowed from the net/http package.
363377
func cleanPath(p string) string {

mux_test.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,16 @@ func TestPath(t *testing.T) {
309309
pathTemplate: `/111/{v1:[0-9]{3}}/333`,
310310
shouldMatch: false,
311311
},
312+
{
313+
title: "Path route, URL with encoded slash does match",
314+
route: new(Route).Path("/v1/{v1}/v2"),
315+
request: newRequest("GET", "http://localhost/v1/1%2F2/v2"),
316+
vars: map[string]string{"v1": "1%2F2"},
317+
host: "",
318+
path: "/v1/1%2F2/v2",
319+
pathTemplate: `/v1/{v1}/v2`,
320+
shouldMatch: true,
321+
},
312322
{
313323
title: "Path route with multiple patterns, match",
314324
route: new(Route).Path("/{v1:[0-9]{3}}/{v2:[0-9]{3}}/{v3:[0-9]{3}}"),

regexp.go

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -149,8 +149,8 @@ func (r *routeRegexp) Match(req *http.Request, match *RouteMatch) bool {
149149
if r.matchQuery {
150150
return r.matchQueryString(req)
151151
}
152-
153-
return r.regexp.MatchString(req.URL.Path)
152+
path := getPath(req)
153+
return r.regexp.MatchString(path)
154154
}
155155

156156
return r.regexp.MatchString(getHost(req))
@@ -253,14 +253,15 @@ func (v *routeRegexpGroup) setMatch(req *http.Request, m *RouteMatch, r *Route)
253253
extractVars(host, matches, v.host.varsN, m.Vars)
254254
}
255255
}
256+
path := getPath(req)
256257
// Store path variables.
257258
if v.path != nil {
258-
matches := v.path.regexp.FindStringSubmatchIndex(req.URL.Path)
259+
matches := v.path.regexp.FindStringSubmatchIndex(path)
259260
if len(matches) > 0 {
260-
extractVars(req.URL.Path, matches, v.path.varsN, m.Vars)
261+
extractVars(path, matches, v.path.varsN, m.Vars)
261262
// Check if we should redirect.
262263
if v.path.strictSlash {
263-
p1 := strings.HasSuffix(req.URL.Path, "/")
264+
p1 := strings.HasSuffix(path, "/")
264265
p2 := strings.HasSuffix(v.path.template, "/")
265266
if p1 != p2 {
266267
u, _ := url.Parse(req.URL.String())

0 commit comments

Comments
 (0)