aboutsummaryrefslogtreecommitdiff
path: root/vendor/github.com/gorilla/mux/mux.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/gorilla/mux/mux.go')
-rw-r--r--vendor/github.com/gorilla/mux/mux.go159
1 files changed, 90 insertions, 69 deletions
diff --git a/vendor/github.com/gorilla/mux/mux.go b/vendor/github.com/gorilla/mux/mux.go
index efabd24..782a34b 100644
--- a/vendor/github.com/gorilla/mux/mux.go
+++ b/vendor/github.com/gorilla/mux/mux.go
@@ -5,6 +5,7 @@
package mux
import (
+ "context"
"errors"
"fmt"
"net/http"
@@ -13,13 +14,16 @@ import (
)
var (
+ // ErrMethodMismatch is returned when the method in the request does not match
+ // the method defined against the route.
ErrMethodMismatch = errors.New("method is not allowed")
- ErrNotFound = errors.New("no matching route was found")
+ // ErrNotFound is returned when no route match is found.
+ ErrNotFound = errors.New("no matching route was found")
)
// NewRouter returns a new router instance.
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.
@@ -47,24 +51,75 @@ type Router struct {
// Configurable Handler to be used when the request method does not match the route.
MethodNotAllowedHandler http.Handler
- // Parent route, if this is a subrouter.
- parent parentRoute
// Routes to be matched, in order.
routes []*Route
+
// Routes by name for URL building.
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.
- // This has no effect when go1.7+ is used, since the context is stored
- // on the request itself.
+ //
+ // Deprecated: No effect, since the context is stored on the request itself.
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
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, len(r.matchers))
+ copy(c.matchers, r.matchers)
+
+ return c
+}
+
+func copyRouteRegexp(r *routeRegexp) *routeRegexp {
+ c := *r
+ return &c
}
// Match attempts to match the given request against the router's registered routes.
@@ -95,9 +150,9 @@ func (r *Router) Match(req *http.Request, match *RouteMatch) bool {
if r.MethodNotAllowedHandler != nil {
match.Handler = r.MethodNotAllowedHandler
return true
- } else {
- return false
}
+
+ return false
}
// Closest match for a router (includes sub-routers)
@@ -140,8 +195,8 @@ func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
var handler http.Handler
if r.Match(req, &match) {
handler = match.Handler
- req = setVars(req, match.Vars)
- req = setCurrentRoute(req, match.Route)
+ req = requestWithVars(req, match.Vars)
+ req = requestWithRoute(req, match.Route)
}
if handler == nil && match.MatchErr == ErrMethodMismatch {
@@ -152,22 +207,18 @@ func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
handler = http.NotFoundHandler()
}
- if !r.KeepContext {
- defer contextClear(req)
- }
-
handler.ServeHTTP(w, req)
}
// Get returns a route registered with the given name.
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
// was renamed to Get() and remains here for backwards compatibility.
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
@@ -219,54 +270,23 @@ func (r *Router) UseEncodedPath() *Router {
}
// ----------------------------------------------------------------------------
-// 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
// ----------------------------------------------------------------------------
// NewRoute registers an empty 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)
return route
}
+// Name registers a new route with a name.
+// See Route.Name().
+func (r *Router) Name(name string) *Route {
+ return r.NewRoute().Name(name)
+}
+
// Handle registers a new route with a matcher for the URL path.
// See Route.Path() and Route.Handler().
func (r *Router) Handle(path string, handler http.Handler) *Route {
@@ -406,7 +426,7 @@ const (
// Vars returns the route variables for the current request, if any.
func Vars(r *http.Request) map[string]string {
- if rv := contextGet(r, varsKey); rv != nil {
+ if rv := r.Context().Value(varsKey); rv != nil {
return rv.(map[string]string)
}
return nil
@@ -415,21 +435,22 @@ func Vars(r *http.Request) map[string]string {
// CurrentRoute returns the matched route for the current request, if any.
// This only works when called inside the handler of the matched route
// because the matched route is stored in the request context which is cleared
-// after the handler returns, unless the KeepContext option is set on the
-// Router.
+// after the handler returns.
func CurrentRoute(r *http.Request) *Route {
- if rv := contextGet(r, routeKey); rv != nil {
+ if rv := r.Context().Value(routeKey); rv != nil {
return rv.(*Route)
}
return nil
}
-func setVars(r *http.Request, val interface{}) *http.Request {
- return contextSet(r, varsKey, val)
+func requestWithVars(r *http.Request, vars map[string]string) *http.Request {
+ ctx := context.WithValue(r.Context(), varsKey, vars)
+ return r.WithContext(ctx)
}
-func setCurrentRoute(r *http.Request, val interface{}) *http.Request {
- return contextSet(r, routeKey, val)
+func requestWithRoute(r *http.Request, route *Route) *http.Request {
+ ctx := context.WithValue(r.Context(), routeKey, route)
+ return r.WithContext(ctx)
}
// ----------------------------------------------------------------------------
nihil fit ex nihilo