Browse Source

Merge 27dd380df8 into f395758b85

pull/463/merge
George Vilches 6 years ago committed by GitHub
parent
commit
b8fa9a6978
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 40
      mux.go
  2. 34
      mux_test.go
  3. 19
      regexp.go
  4. 1
      route.go

40
mux.go

@ -114,6 +114,8 @@ func copyRouteConf(r routeConf) routeConf { @@ -114,6 +114,8 @@ func copyRouteConf(r routeConf) routeConf {
c.matchers = make([]matcher, len(r.matchers))
copy(c.matchers, r.matchers)
c.skipClean = r.skipClean
return c
}
@ -171,26 +173,6 @@ func (r *Router) Match(req *http.Request, match *RouteMatch) bool { @@ -171,26 +173,6 @@ func (r *Router) Match(req *http.Request, match *RouteMatch) bool {
// When there is a match, the route variables can be retrieved calling
// mux.Vars(request).
func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
if !r.skipClean {
path := req.URL.Path
if r.useEncodedPath {
path = req.URL.EscapedPath()
}
// Clean path to canonical form and redirect.
if p := cleanPath(path); p != path {
// Added 3 lines (Philip Schlump) - It was dropping the query string and #whatever from query.
// This matches with fix in go 1.2 r.c. 4 for same problem. Go Issue:
// http://code.google.com/p/go/issues/detail?id=5252
url := *req.URL
url.Path = p
p = url.String()
w.Header().Set("Location", p)
w.WriteHeader(http.StatusMovedPermanently)
return
}
}
var match RouteMatch
var handler http.Handler
if r.Match(req, &match) {
@ -207,6 +189,17 @@ func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) { @@ -207,6 +189,17 @@ func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
handler = http.NotFoundHandler()
}
if match.OnlyMatchedCleanPath {
// Added 3 lines (Philip Schlump) - It was dropping the query string and #whatever from query.
// This matches with fix in go 1.2 r.c. 4 for same problem. Go Issue:
// http://code.google.com/p/go/issues/detail?id=5252
url := *req.URL
url.Path = match.CleanPath
w.Header().Set("Location", url.String())
w.WriteHeader(http.StatusMovedPermanently)
return
}
handler.ServeHTTP(w, req)
}
@ -411,6 +404,13 @@ type RouteMatch struct { @@ -411,6 +404,13 @@ type RouteMatch struct {
Handler http.Handler
Vars map[string]string
// Cleaned version of the path being matched.
CleanPath string
// true if a valid route match occurs, but only on the cleaned version
// of a URL.
OnlyMatchedCleanPath bool
// MatchErr is set to appropriate matching error
// It is set to ErrMethodMismatch if there is a mismatch in
// the request method and route method

34
mux_test.go

@ -1999,6 +1999,40 @@ func TestSkipClean(t *testing.T) { @@ -1999,6 +1999,40 @@ func TestSkipClean(t *testing.T) {
}
}
func TestSkipCleanSubrouter(t *testing.T) {
func1 := func(w http.ResponseWriter, r *http.Request) {}
func2 := func(w http.ResponseWriter, r *http.Request) {}
r := NewRouter().SkipClean(true)
r.HandleFunc("/api/", func1).Name("func2")
subRouter := r.PathPrefix("/v0").Subrouter().SkipClean(false)
subRouter.HandleFunc("/action/do/", func2).Name("func2")
req, _ := http.NewRequest("GET", "http://localhost/api/?abc=def", nil)
res := NewRecorder()
r.ServeHTTP(res, req)
if len(res.HeaderMap["Location"]) != 0 {
t.Errorf("Req 1: Shouldn't redirect since route is already clean")
}
req, _ = http.NewRequest("GET", "http://localhost//api/?abc=def", nil)
res = NewRecorder()
r.ServeHTTP(res, req)
if len(res.HeaderMap["Location"]) != 0 {
t.Errorf("Req 2: Shouldn't redirect since skip clean is disabled")
}
req, _ = http.NewRequest("GET", "http://localhost/v0/action//do/?ghi=jkl", nil)
res = NewRecorder()
r.ServeHTTP(res, req)
if len(res.HeaderMap["Location"]) == 0 {
t.Errorf("Req 3: Should redirect since skip clean is enabled for subroute")
}
}
// https://plus.google.com/101022900381697718949/posts/eWy6DjFJ6uW
func TestSubrouterHeader(t *testing.T) {
expected := "func1 response"

19
regexp.go

@ -17,6 +17,7 @@ import ( @@ -17,6 +17,7 @@ import (
type routeRegexpOptions struct {
strictSlash bool
useEncodedPath bool
skipClean bool
}
type regexpType int
@ -189,7 +190,23 @@ func (r *routeRegexp) Match(req *http.Request, match *RouteMatch) bool { @@ -189,7 +190,23 @@ func (r *routeRegexp) Match(req *http.Request, match *RouteMatch) bool {
if r.options.useEncodedPath {
path = req.URL.EscapedPath()
}
return r.regexp.MatchString(path)
if !r.options.skipClean {
// Only clean the path when needed, and cache the result for later use.
if match.CleanPath == "" {
// Clean path to canonical form for testing purposes.
match.CleanPath = cleanPath(path)
}
path = match.CleanPath
}
isMatch := r.regexp.MatchString(path)
if isMatch {
if !r.options.skipClean && req.URL.Path != match.CleanPath {
match.OnlyMatchedCleanPath = true
} else {
match.OnlyMatchedCleanPath = false
}
}
return isMatch
}
}

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,
skipClean: r.skipClean,
})
if err != nil {
return err

Loading…
Cancel
Save