Browse Source

Bump gorilla/mux to 1.7.0

This release drops support for Go < 1.7, and removes the gorilla/context
dependency (which was needed for older Go versions).

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Sebastiaan van Stijn 6 years ago
parent
commit
477eeef60c

+ 1 - 2
vendor.conf

@@ -5,8 +5,7 @@ github.com/Microsoft/go-winio v0.4.11
 github.com/docker/libtrust 9cbd2a1374f46905c68a4eb3694a130610adc62a
 github.com/docker/libtrust 9cbd2a1374f46905c68a4eb3694a130610adc62a
 github.com/go-check/check 4ed411733c5785b40214c70bce814c3a3a689609 https://github.com/cpuguy83/check.git
 github.com/go-check/check 4ed411733c5785b40214c70bce814c3a3a689609 https://github.com/cpuguy83/check.git
 github.com/golang/gddo 9b12a26f3fbd7397dee4e20939ddca719d840d2a
 github.com/golang/gddo 9b12a26f3fbd7397dee4e20939ddca719d840d2a
-github.com/gorilla/context v1.1
-github.com/gorilla/mux v1.6.2
+github.com/gorilla/mux v1.7.0
 github.com/Microsoft/opengcs v0.3.9
 github.com/Microsoft/opengcs v0.3.9
 github.com/kr/pty 5cf931ef8f
 github.com/kr/pty 5cf931ef8f
 github.com/mattn/go-shellwords v1.0.3
 github.com/mattn/go-shellwords v1.0.3

+ 0 - 27
vendor/github.com/gorilla/context/LICENSE

@@ -1,27 +0,0 @@
-Copyright (c) 2012 Rodrigo Moraes. All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
-
-	 * Redistributions of source code must retain the above copyright
-notice, this list of conditions and the following disclaimer.
-	 * Redistributions in binary form must reproduce the above
-copyright notice, this list of conditions and the following disclaimer
-in the documentation and/or other materials provided with the
-distribution.
-	 * Neither the name of Google Inc. nor the names of its
-contributors may be used to endorse or promote products derived from
-this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+ 0 - 7
vendor/github.com/gorilla/context/README.md

@@ -1,7 +0,0 @@
-context
-=======
-[![Build Status](https://travis-ci.org/gorilla/context.png?branch=master)](https://travis-ci.org/gorilla/context)
-
-gorilla/context is a general purpose registry for global request variables.
-
-Read the full documentation here: http://www.gorillatoolkit.org/pkg/context

+ 0 - 143
vendor/github.com/gorilla/context/context.go

@@ -1,143 +0,0 @@
-// Copyright 2012 The Gorilla Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package context
-
-import (
-	"net/http"
-	"sync"
-	"time"
-)
-
-var (
-	mutex sync.RWMutex
-	data  = make(map[*http.Request]map[interface{}]interface{})
-	datat = make(map[*http.Request]int64)
-)
-
-// Set stores a value for a given key in a given request.
-func Set(r *http.Request, key, val interface{}) {
-	mutex.Lock()
-	if data[r] == nil {
-		data[r] = make(map[interface{}]interface{})
-		datat[r] = time.Now().Unix()
-	}
-	data[r][key] = val
-	mutex.Unlock()
-}
-
-// Get returns a value stored for a given key in a given request.
-func Get(r *http.Request, key interface{}) interface{} {
-	mutex.RLock()
-	if ctx := data[r]; ctx != nil {
-		value := ctx[key]
-		mutex.RUnlock()
-		return value
-	}
-	mutex.RUnlock()
-	return nil
-}
-
-// GetOk returns stored value and presence state like multi-value return of map access.
-func GetOk(r *http.Request, key interface{}) (interface{}, bool) {
-	mutex.RLock()
-	if _, ok := data[r]; ok {
-		value, ok := data[r][key]
-		mutex.RUnlock()
-		return value, ok
-	}
-	mutex.RUnlock()
-	return nil, false
-}
-
-// GetAll returns all stored values for the request as a map. Nil is returned for invalid requests.
-func GetAll(r *http.Request) map[interface{}]interface{} {
-	mutex.RLock()
-	if context, ok := data[r]; ok {
-		result := make(map[interface{}]interface{}, len(context))
-		for k, v := range context {
-			result[k] = v
-		}
-		mutex.RUnlock()
-		return result
-	}
-	mutex.RUnlock()
-	return nil
-}
-
-// GetAllOk returns all stored values for the request as a map and a boolean value that indicates if
-// the request was registered.
-func GetAllOk(r *http.Request) (map[interface{}]interface{}, bool) {
-	mutex.RLock()
-	context, ok := data[r]
-	result := make(map[interface{}]interface{}, len(context))
-	for k, v := range context {
-		result[k] = v
-	}
-	mutex.RUnlock()
-	return result, ok
-}
-
-// Delete removes a value stored for a given key in a given request.
-func Delete(r *http.Request, key interface{}) {
-	mutex.Lock()
-	if data[r] != nil {
-		delete(data[r], key)
-	}
-	mutex.Unlock()
-}
-
-// Clear removes all values stored for a given request.
-//
-// This is usually called by a handler wrapper to clean up request
-// variables at the end of a request lifetime. See ClearHandler().
-func Clear(r *http.Request) {
-	mutex.Lock()
-	clear(r)
-	mutex.Unlock()
-}
-
-// clear is Clear without the lock.
-func clear(r *http.Request) {
-	delete(data, r)
-	delete(datat, r)
-}
-
-// Purge removes request data stored for longer than maxAge, in seconds.
-// It returns the amount of requests removed.
-//
-// If maxAge <= 0, all request data is removed.
-//
-// This is only used for sanity check: in case context cleaning was not
-// properly set some request data can be kept forever, consuming an increasing
-// amount of memory. In case this is detected, Purge() must be called
-// periodically until the problem is fixed.
-func Purge(maxAge int) int {
-	mutex.Lock()
-	count := 0
-	if maxAge <= 0 {
-		count = len(data)
-		data = make(map[*http.Request]map[interface{}]interface{})
-		datat = make(map[*http.Request]int64)
-	} else {
-		min := time.Now().Unix() - int64(maxAge)
-		for r := range data {
-			if datat[r] < min {
-				clear(r)
-				count++
-			}
-		}
-	}
-	mutex.Unlock()
-	return count
-}
-
-// ClearHandler wraps an http.Handler and clears request values at the end
-// of a request lifetime.
-func ClearHandler(h http.Handler) http.Handler {
-	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
-		defer Clear(r)
-		h.ServeHTTP(w, r)
-	})
-}

+ 0 - 82
vendor/github.com/gorilla/context/doc.go

@@ -1,82 +0,0 @@
-// Copyright 2012 The Gorilla Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-/*
-Package context stores values shared during a request lifetime.
-
-For example, a router can set variables extracted from the URL and later
-application handlers can access those values, or it can be used to store
-sessions values to be saved at the end of a request. There are several
-others common uses.
-
-The idea was posted by Brad Fitzpatrick to the go-nuts mailing list:
-
-	http://groups.google.com/group/golang-nuts/msg/e2d679d303aa5d53
-
-Here's the basic usage: first define the keys that you will need. The key
-type is interface{} so a key can be of any type that supports equality.
-Here we define a key using a custom int type to avoid name collisions:
-
-	package foo
-
-	import (
-		"github.com/gorilla/context"
-	)
-
-	type key int
-
-	const MyKey key = 0
-
-Then set a variable. Variables are bound to an http.Request object, so you
-need a request instance to set a value:
-
-	context.Set(r, MyKey, "bar")
-
-The application can later access the variable using the same key you provided:
-
-	func MyHandler(w http.ResponseWriter, r *http.Request) {
-		// val is "bar".
-		val := context.Get(r, foo.MyKey)
-
-		// returns ("bar", true)
-		val, ok := context.GetOk(r, foo.MyKey)
-		// ...
-	}
-
-And that's all about the basic usage. We discuss some other ideas below.
-
-Any type can be stored in the context. To enforce a given type, make the key
-private and wrap Get() and Set() to accept and return values of a specific
-type:
-
-	type key int
-
-	const mykey key = 0
-
-	// GetMyKey returns a value for this package from the request values.
-	func GetMyKey(r *http.Request) SomeType {
-		if rv := context.Get(r, mykey); rv != nil {
-			return rv.(SomeType)
-		}
-		return nil
-	}
-
-	// SetMyKey sets a value for this package in the request values.
-	func SetMyKey(r *http.Request, val SomeType) {
-		context.Set(r, mykey, val)
-	}
-
-Variables must be cleared at the end of a request, to remove all values
-that were stored. This can be done in an http.Handler, after a request was
-served. Just call Clear() passing the request:
-
-	context.Clear(r)
-
-...or use ClearHandler(), which conveniently wraps an http.Handler to clear
-variables at the end of a request lifetime.
-
-The Routers from the packages gorilla/mux and gorilla/pat call Clear()
-so if you are using either of them you don't need to clear the context manually.
-*/
-package context

+ 1 - 1
vendor/github.com/gorilla/mux/LICENSE

@@ -1,4 +1,4 @@
-Copyright (c) 2012 Rodrigo Moraes. All rights reserved.
+Copyright (c) 2012-2018 The Gorilla Authors. All rights reserved.
 
 
 Redistribution and use in source and binary forms, with or without
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are
 modification, are permitted provided that the following conditions are

+ 8 - 8
vendor/github.com/gorilla/mux/README.md

@@ -6,7 +6,7 @@
 
 
 ![Gorilla Logo](http://www.gorillatoolkit.org/static/images/gorilla-icon-64.png)
 ![Gorilla Logo](http://www.gorillatoolkit.org/static/images/gorilla-icon-64.png)
 
 
-http://www.gorillatoolkit.org/pkg/mux
+https://www.gorillatoolkit.org/pkg/mux
 
 
 Package `gorilla/mux` implements a request router and dispatcher for matching incoming requests to
 Package `gorilla/mux` implements a request router and dispatcher for matching incoming requests to
 their respective handler.
 their respective handler.
@@ -88,7 +88,7 @@ r := mux.NewRouter()
 // Only matches if domain is "www.example.com".
 // Only matches if domain is "www.example.com".
 r.Host("www.example.com")
 r.Host("www.example.com")
 // Matches a dynamic subdomain.
 // Matches a dynamic subdomain.
-r.Host("{subdomain:[a-z]+}.domain.com")
+r.Host("{subdomain:[a-z]+}.example.com")
 ```
 ```
 
 
 There are several other matchers that can be added. To match path prefixes:
 There are several other matchers that can be added. To match path prefixes:
@@ -238,13 +238,13 @@ This also works for host and query value variables:
 
 
 ```go
 ```go
 r := mux.NewRouter()
 r := mux.NewRouter()
-r.Host("{subdomain}.domain.com").
+r.Host("{subdomain}.example.com").
   Path("/articles/{category}/{id:[0-9]+}").
   Path("/articles/{category}/{id:[0-9]+}").
   Queries("filter", "{filter}").
   Queries("filter", "{filter}").
   HandlerFunc(ArticleHandler).
   HandlerFunc(ArticleHandler).
   Name("article")
   Name("article")
 
 
-// url.String() will be "http://news.domain.com/articles/technology/42?filter=gorilla"
+// url.String() will be "http://news.example.com/articles/technology/42?filter=gorilla"
 url, err := r.Get("article").URL("subdomain", "news",
 url, err := r.Get("article").URL("subdomain", "news",
                                  "category", "technology",
                                  "category", "technology",
                                  "id", "42",
                                  "id", "42",
@@ -264,7 +264,7 @@ r.HeadersRegexp("Content-Type", "application/(text|json)")
 There's also a way to build only the URL host or path for a route: use the methods `URLHost()` or `URLPath()` instead. For the previous route, we would do:
 There's also a way to build only the URL host or path for a route: use the methods `URLHost()` or `URLPath()` instead. For the previous route, we would do:
 
 
 ```go
 ```go
-// "http://news.domain.com/"
+// "http://news.example.com/"
 host, err := r.Get("article").URLHost("subdomain", "news")
 host, err := r.Get("article").URLHost("subdomain", "news")
 
 
 // "/articles/technology/42"
 // "/articles/technology/42"
@@ -275,12 +275,12 @@ And if you use subrouters, host and path defined separately can be built as well
 
 
 ```go
 ```go
 r := mux.NewRouter()
 r := mux.NewRouter()
-s := r.Host("{subdomain}.domain.com").Subrouter()
+s := r.Host("{subdomain}.example.com").Subrouter()
 s.Path("/articles/{category}/{id:[0-9]+}").
 s.Path("/articles/{category}/{id:[0-9]+}").
   HandlerFunc(ArticleHandler).
   HandlerFunc(ArticleHandler).
   Name("article")
   Name("article")
 
 
-// "http://news.domain.com/articles/technology/42"
+// "http://news.example.com/articles/technology/42"
 url, err := r.Get("article").URL("subdomain", "news",
 url, err := r.Get("article").URL("subdomain", "news",
                                  "category", "technology",
                                  "category", "technology",
                                  "id", "42")
                                  "id", "42")
@@ -503,8 +503,8 @@ package main
 
 
 func HealthCheckHandler(w http.ResponseWriter, r *http.Request) {
 func HealthCheckHandler(w http.ResponseWriter, r *http.Request) {
     // A very simple health check.
     // A very simple health check.
-    w.WriteHeader(http.StatusOK)
     w.Header().Set("Content-Type", "application/json")
     w.Header().Set("Content-Type", "application/json")
+    w.WriteHeader(http.StatusOK)
 
 
     // In the future we could report back on the status of our DB, or our cache
     // In the future we could report back on the status of our DB, or our cache
     // (e.g. Redis) by performing a simple PING, and include them in the response.
     // (e.g. Redis) by performing a simple PING, and include them in the response.

+ 0 - 6
vendor/github.com/gorilla/mux/context_native.go → vendor/github.com/gorilla/mux/context.go

@@ -1,5 +1,3 @@
-// +build go1.7
-
 package mux
 package mux
 
 
 import (
 import (
@@ -18,7 +16,3 @@ func contextSet(r *http.Request, key, val interface{}) *http.Request {
 
 
 	return r.WithContext(context.WithValue(r.Context(), key, val))
 	return r.WithContext(context.WithValue(r.Context(), key, val))
 }
 }
-
-func contextClear(r *http.Request) {
-	return
-}

+ 0 - 26
vendor/github.com/gorilla/mux/context_gorilla.go

@@ -1,26 +0,0 @@
-// +build !go1.7
-
-package mux
-
-import (
-	"net/http"
-
-	"github.com/gorilla/context"
-)
-
-func contextGet(r *http.Request, key interface{}) interface{} {
-	return context.Get(r, key)
-}
-
-func contextSet(r *http.Request, key, val interface{}) *http.Request {
-	if val == nil {
-		return r
-	}
-
-	context.Set(r, key, val)
-	return r
-}
-
-func contextClear(r *http.Request) {
-	context.Clear(r)
-}

+ 68 - 55
vendor/github.com/gorilla/mux/mux.go

@@ -22,7 +22,7 @@ var (
 
 
 // NewRouter returns a new router instance.
 // NewRouter returns a new router instance.
 func NewRouter() *Router {
 func NewRouter() *Router {
-	return &Router{namedRoutes: make(map[string]*Route), KeepContext: false}
+	return &Router{namedRoutes: make(map[string]*Route)}
 }
 }
 
 
 // Router registers routes to be matched and dispatches a handler.
 // Router registers routes to be matched and dispatches a handler.
@@ -50,24 +50,78 @@ type Router struct {
 	// Configurable Handler to be used when the request method does not match the route.
 	// Configurable Handler to be used when the request method does not match the route.
 	MethodNotAllowedHandler http.Handler
 	MethodNotAllowedHandler http.Handler
 
 
-	// Parent route, if this is a subrouter.
-	parent parentRoute
 	// Routes to be matched, in order.
 	// Routes to be matched, in order.
 	routes []*Route
 	routes []*Route
+
 	// Routes by name for URL building.
 	// Routes by name for URL building.
 	namedRoutes map[string]*Route
 	namedRoutes map[string]*Route
-	// See Router.StrictSlash(). This defines the flag for new routes.
-	strictSlash bool
-	// See Router.SkipClean(). This defines the flag for new routes.
-	skipClean bool
+
 	// If true, do not clear the request context after handling the request.
 	// If true, do not clear the request context after handling the request.
-	// This has no effect when go1.7+ is used, since the context is stored
+	//
+	// Deprecated: No effect when go1.7+ is used, since the context is stored
 	// on the request itself.
 	// on the request itself.
 	KeepContext bool
 	KeepContext bool
-	// see Router.UseEncodedPath(). This defines a flag for all routes.
-	useEncodedPath bool
+
 	// Slice of middlewares to be called after a match is found
 	// Slice of middlewares to be called after a match is found
 	middlewares []middleware
 	middlewares []middleware
+
+	// configuration shared with `Route`
+	routeConf
+}
+
+// common route configuration shared between `Router` and `Route`
+type routeConf struct {
+	// If true, "/path/foo%2Fbar/to" will match the path "/path/{var}/to"
+	useEncodedPath bool
+
+	// If true, when the path pattern is "/path/", accessing "/path" will
+	// redirect to the former and vice versa.
+	strictSlash bool
+
+	// If true, when the path pattern is "/path//to", accessing "/path//to"
+	// will not redirect
+	skipClean bool
+
+	// Manager for the variables from host and path.
+	regexp routeRegexpGroup
+
+	// List of matchers.
+	matchers []matcher
+
+	// The scheme used when building URLs.
+	buildScheme string
+
+	buildVarsFunc BuildVarsFunc
+}
+
+// returns an effective deep copy of `routeConf`
+func copyRouteConf(r routeConf) routeConf {
+	c := r
+
+	if r.regexp.path != nil {
+		c.regexp.path = copyRouteRegexp(r.regexp.path)
+	}
+
+	if r.regexp.host != nil {
+		c.regexp.host = copyRouteRegexp(r.regexp.host)
+	}
+
+	c.regexp.queries = make([]*routeRegexp, 0, len(r.regexp.queries))
+	for _, q := range r.regexp.queries {
+		c.regexp.queries = append(c.regexp.queries, copyRouteRegexp(q))
+	}
+
+	c.matchers = make([]matcher, 0, len(r.matchers))
+	for _, m := range r.matchers {
+		c.matchers = append(c.matchers, m)
+	}
+
+	return c
+}
+
+func copyRouteRegexp(r *routeRegexp) *routeRegexp {
+	c := *r
+	return &c
 }
 }
 
 
 // Match attempts to match the given request against the router's registered routes.
 // Match attempts to match the given request against the router's registered routes.
@@ -155,22 +209,18 @@ func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
 		handler = http.NotFoundHandler()
 		handler = http.NotFoundHandler()
 	}
 	}
 
 
-	if !r.KeepContext {
-		defer contextClear(req)
-	}
-
 	handler.ServeHTTP(w, req)
 	handler.ServeHTTP(w, req)
 }
 }
 
 
 // Get returns a route registered with the given name.
 // Get returns a route registered with the given name.
 func (r *Router) Get(name string) *Route {
 func (r *Router) Get(name string) *Route {
-	return r.getNamedRoutes()[name]
+	return r.namedRoutes[name]
 }
 }
 
 
 // GetRoute returns a route registered with the given name. This method
 // GetRoute returns a route registered with the given name. This method
 // was renamed to Get() and remains here for backwards compatibility.
 // was renamed to Get() and remains here for backwards compatibility.
 func (r *Router) GetRoute(name string) *Route {
 func (r *Router) GetRoute(name string) *Route {
-	return r.getNamedRoutes()[name]
+	return r.namedRoutes[name]
 }
 }
 
 
 // StrictSlash defines the trailing slash behavior for new routes. The initial
 // StrictSlash defines the trailing slash behavior for new routes. The initial
@@ -221,51 +271,14 @@ func (r *Router) UseEncodedPath() *Router {
 	return r
 	return r
 }
 }
 
 
-// ----------------------------------------------------------------------------
-// parentRoute
-// ----------------------------------------------------------------------------
-
-func (r *Router) getBuildScheme() string {
-	if r.parent != nil {
-		return r.parent.getBuildScheme()
-	}
-	return ""
-}
-
-// getNamedRoutes returns the map where named routes are registered.
-func (r *Router) getNamedRoutes() map[string]*Route {
-	if r.namedRoutes == nil {
-		if r.parent != nil {
-			r.namedRoutes = r.parent.getNamedRoutes()
-		} else {
-			r.namedRoutes = make(map[string]*Route)
-		}
-	}
-	return r.namedRoutes
-}
-
-// getRegexpGroup returns regexp definitions from the parent route, if any.
-func (r *Router) getRegexpGroup() *routeRegexpGroup {
-	if r.parent != nil {
-		return r.parent.getRegexpGroup()
-	}
-	return nil
-}
-
-func (r *Router) buildVars(m map[string]string) map[string]string {
-	if r.parent != nil {
-		m = r.parent.buildVars(m)
-	}
-	return m
-}
-
 // ----------------------------------------------------------------------------
 // ----------------------------------------------------------------------------
 // Route factories
 // Route factories
 // ----------------------------------------------------------------------------
 // ----------------------------------------------------------------------------
 
 
 // NewRoute registers an empty route.
 // NewRoute registers an empty route.
 func (r *Router) NewRoute() *Route {
 func (r *Router) NewRoute() *Route {
-	route := &Route{parent: r, strictSlash: r.strictSlash, skipClean: r.skipClean, useEncodedPath: r.useEncodedPath}
+	// initialize a route with a copy of the parent router's configuration
+	route := &Route{routeConf: copyRouteConf(r.routeConf), namedRoutes: r.namedRoutes}
 	r.routes = append(r.routes, route)
 	r.routes = append(r.routes, route)
 	return route
 	return route
 }
 }

+ 5 - 9
vendor/github.com/gorilla/mux/regexp.go

@@ -267,7 +267,7 @@ type routeRegexpGroup struct {
 }
 }
 
 
 // setMatch extracts the variables from the URL once a route matches.
 // setMatch extracts the variables from the URL once a route matches.
-func (v *routeRegexpGroup) setMatch(req *http.Request, m *RouteMatch, r *Route) {
+func (v routeRegexpGroup) setMatch(req *http.Request, m *RouteMatch, r *Route) {
 	// Store host variables.
 	// Store host variables.
 	if v.host != nil {
 	if v.host != nil {
 		host := getHost(req)
 		host := getHost(req)
@@ -296,7 +296,7 @@ func (v *routeRegexpGroup) setMatch(req *http.Request, m *RouteMatch, r *Route)
 					} else {
 					} else {
 						u.Path += "/"
 						u.Path += "/"
 					}
 					}
-					m.Handler = http.RedirectHandler(u.String(), 301)
+					m.Handler = http.RedirectHandler(u.String(), http.StatusMovedPermanently)
 				}
 				}
 			}
 			}
 		}
 		}
@@ -312,17 +312,13 @@ func (v *routeRegexpGroup) setMatch(req *http.Request, m *RouteMatch, r *Route)
 }
 }
 
 
 // getHost tries its best to return the request host.
 // getHost tries its best to return the request host.
+// According to section 14.23 of RFC 2616 the Host header
+// can include the port number if the default value of 80 is not used.
 func getHost(r *http.Request) string {
 func getHost(r *http.Request) string {
 	if r.URL.IsAbs() {
 	if r.URL.IsAbs() {
 		return r.URL.Host
 		return r.URL.Host
 	}
 	}
-	host := r.Host
-	// Slice off any port information.
-	if i := strings.Index(host, ":"); i != -1 {
-		host = host[:i]
-	}
-	return host
-
+	return r.Host
 }
 }
 
 
 func extractVars(input string, matches []int, names []string, output map[string]string) {
 func extractVars(input string, matches []int, names []string, output map[string]string) {

+ 43 - 96
vendor/github.com/gorilla/mux/route.go

@@ -15,24 +15,8 @@ import (
 
 
 // Route stores information to match a request and build URLs.
 // Route stores information to match a request and build URLs.
 type Route struct {
 type Route struct {
-	// Parent where the route was registered (a Router).
-	parent parentRoute
 	// Request handler for the route.
 	// Request handler for the route.
 	handler http.Handler
 	handler http.Handler
-	// List of matchers.
-	matchers []matcher
-	// Manager for the variables from host and path.
-	regexp *routeRegexpGroup
-	// If true, when the path pattern is "/path/", accessing "/path" will
-	// redirect to the former and vice versa.
-	strictSlash bool
-	// If true, when the path pattern is "/path//to", accessing "/path//to"
-	// will not redirect
-	skipClean bool
-	// If true, "/path/foo%2Fbar/to" will match the path "/path/{var}/to"
-	useEncodedPath bool
-	// The scheme used when building URLs.
-	buildScheme string
 	// If true, this route never matches: it is only used to build URLs.
 	// If true, this route never matches: it is only used to build URLs.
 	buildOnly bool
 	buildOnly bool
 	// The name used to build URLs.
 	// The name used to build URLs.
@@ -40,7 +24,11 @@ type Route struct {
 	// Error resulted from building a route.
 	// Error resulted from building a route.
 	err error
 	err error
 
 
-	buildVarsFunc BuildVarsFunc
+	// "global" reference to all named routes
+	namedRoutes map[string]*Route
+
+	// config possibly passed in from `Router`
+	routeConf
 }
 }
 
 
 // SkipClean reports whether path cleaning is enabled for this route via
 // SkipClean reports whether path cleaning is enabled for this route via
@@ -64,6 +52,18 @@ func (r *Route) Match(req *http.Request, match *RouteMatch) bool {
 				matchErr = ErrMethodMismatch
 				matchErr = ErrMethodMismatch
 				continue
 				continue
 			}
 			}
+
+			// Ignore ErrNotFound errors. These errors arise from match call
+			// to Subrouters.
+			//
+			// This prevents subsequent matching subrouters from failing to
+			// run middleware. If not ignored, the middleware would see a
+			// non-nil MatchErr and be skipped, even when there was a
+			// matching route.
+			if match.MatchErr == ErrNotFound {
+				match.MatchErr = nil
+			}
+
 			matchErr = nil
 			matchErr = nil
 			return false
 			return false
 		}
 		}
@@ -93,9 +93,7 @@ func (r *Route) Match(req *http.Request, match *RouteMatch) bool {
 	}
 	}
 
 
 	// Set variables.
 	// Set variables.
-	if r.regexp != nil {
-		r.regexp.setMatch(req, match, r)
-	}
+	r.regexp.setMatch(req, match, r)
 	return true
 	return true
 }
 }
 
 
@@ -137,7 +135,7 @@ func (r *Route) GetHandler() http.Handler {
 // Name -----------------------------------------------------------------------
 // Name -----------------------------------------------------------------------
 
 
 // Name sets the name for the route, used to build URLs.
 // Name sets the name for the route, used to build URLs.
-// If the name was registered already it will be overwritten.
+// It is an error to call Name more than once on a route.
 func (r *Route) Name(name string) *Route {
 func (r *Route) Name(name string) *Route {
 	if r.name != "" {
 	if r.name != "" {
 		r.err = fmt.Errorf("mux: route already has name %q, can't set %q",
 		r.err = fmt.Errorf("mux: route already has name %q, can't set %q",
@@ -145,7 +143,7 @@ func (r *Route) Name(name string) *Route {
 	}
 	}
 	if r.err == nil {
 	if r.err == nil {
 		r.name = name
 		r.name = name
-		r.getNamedRoutes()[name] = r
+		r.namedRoutes[name] = r
 	}
 	}
 	return r
 	return r
 }
 }
@@ -177,7 +175,6 @@ func (r *Route) addRegexpMatcher(tpl string, typ regexpType) error {
 	if r.err != nil {
 	if r.err != nil {
 		return r.err
 		return r.err
 	}
 	}
-	r.regexp = r.getRegexpGroup()
 	if typ == regexpTypePath || typ == regexpTypePrefix {
 	if typ == regexpTypePath || typ == regexpTypePrefix {
 		if len(tpl) > 0 && tpl[0] != '/' {
 		if len(tpl) > 0 && tpl[0] != '/' {
 			return fmt.Errorf("mux: path must start with a slash, got %q", tpl)
 			return fmt.Errorf("mux: path must start with a slash, got %q", tpl)
@@ -424,7 +421,7 @@ func (r *Route) Schemes(schemes ...string) *Route {
 	for k, v := range schemes {
 	for k, v := range schemes {
 		schemes[k] = strings.ToLower(v)
 		schemes[k] = strings.ToLower(v)
 	}
 	}
-	if r.buildScheme == "" && len(schemes) > 0 {
+	if len(schemes) > 0 {
 		r.buildScheme = schemes[0]
 		r.buildScheme = schemes[0]
 	}
 	}
 	return r.addMatcher(schemeMatcher(schemes))
 	return r.addMatcher(schemeMatcher(schemes))
@@ -439,7 +436,15 @@ type BuildVarsFunc func(map[string]string) map[string]string
 // BuildVarsFunc adds a custom function to be used to modify build variables
 // BuildVarsFunc adds a custom function to be used to modify build variables
 // before a route's URL is built.
 // before a route's URL is built.
 func (r *Route) BuildVarsFunc(f BuildVarsFunc) *Route {
 func (r *Route) BuildVarsFunc(f BuildVarsFunc) *Route {
-	r.buildVarsFunc = f
+	if r.buildVarsFunc != nil {
+		// compose the old and new functions
+		old := r.buildVarsFunc
+		r.buildVarsFunc = func(m map[string]string) map[string]string {
+			return f(old(m))
+		}
+	} else {
+		r.buildVarsFunc = f
+	}
 	return r
 	return r
 }
 }
 
 
@@ -458,7 +463,8 @@ func (r *Route) BuildVarsFunc(f BuildVarsFunc) *Route {
 // Here, the routes registered in the subrouter won't be tested if the host
 // Here, the routes registered in the subrouter won't be tested if the host
 // doesn't match.
 // doesn't match.
 func (r *Route) Subrouter() *Router {
 func (r *Route) Subrouter() *Router {
-	router := &Router{parent: r, strictSlash: r.strictSlash}
+	// initialize a subrouter with a copy of the parent route's configuration
+	router := &Router{routeConf: copyRouteConf(r.routeConf), namedRoutes: r.namedRoutes}
 	r.addMatcher(router)
 	r.addMatcher(router)
 	return router
 	return router
 }
 }
@@ -502,9 +508,6 @@ func (r *Route) URL(pairs ...string) (*url.URL, error) {
 	if r.err != nil {
 	if r.err != nil {
 		return nil, r.err
 		return nil, r.err
 	}
 	}
-	if r.regexp == nil {
-		return nil, errors.New("mux: route doesn't have a host or path")
-	}
 	values, err := r.prepareVars(pairs...)
 	values, err := r.prepareVars(pairs...)
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
@@ -516,8 +519,8 @@ func (r *Route) URL(pairs ...string) (*url.URL, error) {
 			return nil, err
 			return nil, err
 		}
 		}
 		scheme = "http"
 		scheme = "http"
-		if s := r.getBuildScheme(); s != "" {
-			scheme = s
+		if r.buildScheme != "" {
+			scheme = r.buildScheme
 		}
 		}
 	}
 	}
 	if r.regexp.path != nil {
 	if r.regexp.path != nil {
@@ -547,7 +550,7 @@ func (r *Route) URLHost(pairs ...string) (*url.URL, error) {
 	if r.err != nil {
 	if r.err != nil {
 		return nil, r.err
 		return nil, r.err
 	}
 	}
-	if r.regexp == nil || r.regexp.host == nil {
+	if r.regexp.host == nil {
 		return nil, errors.New("mux: route doesn't have a host")
 		return nil, errors.New("mux: route doesn't have a host")
 	}
 	}
 	values, err := r.prepareVars(pairs...)
 	values, err := r.prepareVars(pairs...)
@@ -562,8 +565,8 @@ func (r *Route) URLHost(pairs ...string) (*url.URL, error) {
 		Scheme: "http",
 		Scheme: "http",
 		Host:   host,
 		Host:   host,
 	}
 	}
-	if s := r.getBuildScheme(); s != "" {
-		u.Scheme = s
+	if r.buildScheme != "" {
+		u.Scheme = r.buildScheme
 	}
 	}
 	return u, nil
 	return u, nil
 }
 }
@@ -575,7 +578,7 @@ func (r *Route) URLPath(pairs ...string) (*url.URL, error) {
 	if r.err != nil {
 	if r.err != nil {
 		return nil, r.err
 		return nil, r.err
 	}
 	}
-	if r.regexp == nil || r.regexp.path == nil {
+	if r.regexp.path == nil {
 		return nil, errors.New("mux: route doesn't have a path")
 		return nil, errors.New("mux: route doesn't have a path")
 	}
 	}
 	values, err := r.prepareVars(pairs...)
 	values, err := r.prepareVars(pairs...)
@@ -600,7 +603,7 @@ func (r *Route) GetPathTemplate() (string, error) {
 	if r.err != nil {
 	if r.err != nil {
 		return "", r.err
 		return "", r.err
 	}
 	}
-	if r.regexp == nil || r.regexp.path == nil {
+	if r.regexp.path == nil {
 		return "", errors.New("mux: route doesn't have a path")
 		return "", errors.New("mux: route doesn't have a path")
 	}
 	}
 	return r.regexp.path.template, nil
 	return r.regexp.path.template, nil
@@ -614,7 +617,7 @@ func (r *Route) GetPathRegexp() (string, error) {
 	if r.err != nil {
 	if r.err != nil {
 		return "", r.err
 		return "", r.err
 	}
 	}
-	if r.regexp == nil || r.regexp.path == nil {
+	if r.regexp.path == nil {
 		return "", errors.New("mux: route does not have a path")
 		return "", errors.New("mux: route does not have a path")
 	}
 	}
 	return r.regexp.path.regexp.String(), nil
 	return r.regexp.path.regexp.String(), nil
@@ -629,7 +632,7 @@ func (r *Route) GetQueriesRegexp() ([]string, error) {
 	if r.err != nil {
 	if r.err != nil {
 		return nil, r.err
 		return nil, r.err
 	}
 	}
-	if r.regexp == nil || r.regexp.queries == nil {
+	if r.regexp.queries == nil {
 		return nil, errors.New("mux: route doesn't have queries")
 		return nil, errors.New("mux: route doesn't have queries")
 	}
 	}
 	var queries []string
 	var queries []string
@@ -648,7 +651,7 @@ func (r *Route) GetQueriesTemplates() ([]string, error) {
 	if r.err != nil {
 	if r.err != nil {
 		return nil, r.err
 		return nil, r.err
 	}
 	}
-	if r.regexp == nil || r.regexp.queries == nil {
+	if r.regexp.queries == nil {
 		return nil, errors.New("mux: route doesn't have queries")
 		return nil, errors.New("mux: route doesn't have queries")
 	}
 	}
 	var queries []string
 	var queries []string
@@ -683,7 +686,7 @@ func (r *Route) GetHostTemplate() (string, error) {
 	if r.err != nil {
 	if r.err != nil {
 		return "", r.err
 		return "", r.err
 	}
 	}
-	if r.regexp == nil || r.regexp.host == nil {
+	if r.regexp.host == nil {
 		return "", errors.New("mux: route doesn't have a host")
 		return "", errors.New("mux: route doesn't have a host")
 	}
 	}
 	return r.regexp.host.template, nil
 	return r.regexp.host.template, nil
@@ -700,64 +703,8 @@ func (r *Route) prepareVars(pairs ...string) (map[string]string, error) {
 }
 }
 
 
 func (r *Route) buildVars(m map[string]string) map[string]string {
 func (r *Route) buildVars(m map[string]string) map[string]string {
-	if r.parent != nil {
-		m = r.parent.buildVars(m)
-	}
 	if r.buildVarsFunc != nil {
 	if r.buildVarsFunc != nil {
 		m = r.buildVarsFunc(m)
 		m = r.buildVarsFunc(m)
 	}
 	}
 	return m
 	return m
 }
 }
-
-// ----------------------------------------------------------------------------
-// parentRoute
-// ----------------------------------------------------------------------------
-
-// parentRoute allows routes to know about parent host and path definitions.
-type parentRoute interface {
-	getBuildScheme() string
-	getNamedRoutes() map[string]*Route
-	getRegexpGroup() *routeRegexpGroup
-	buildVars(map[string]string) map[string]string
-}
-
-func (r *Route) getBuildScheme() string {
-	if r.buildScheme != "" {
-		return r.buildScheme
-	}
-	if r.parent != nil {
-		return r.parent.getBuildScheme()
-	}
-	return ""
-}
-
-// getNamedRoutes returns the map where named routes are registered.
-func (r *Route) getNamedRoutes() map[string]*Route {
-	if r.parent == nil {
-		// During tests router is not always set.
-		r.parent = NewRouter()
-	}
-	return r.parent.getNamedRoutes()
-}
-
-// getRegexpGroup returns regexp definitions from this route.
-func (r *Route) getRegexpGroup() *routeRegexpGroup {
-	if r.regexp == nil {
-		if r.parent == nil {
-			// During tests router is not always set.
-			r.parent = NewRouter()
-		}
-		regexp := r.parent.getRegexpGroup()
-		if regexp == nil {
-			r.regexp = new(routeRegexpGroup)
-		} else {
-			// Copy.
-			r.regexp = &routeRegexpGroup{
-				host:    regexp.host,
-				path:    regexp.path,
-				queries: regexp.queries,
-			}
-		}
-	}
-	return r.regexp
-}