mirror of
				https://github.com/k3s-io/kubernetes.git
				synced 2025-10-31 13:50:01 +00:00 
			
		
		
		
	Move deps from _workspace/ to vendor/
godep restore pushd $GOPATH/src/github.com/appc/spec git co master popd go get go4.org/errorutil rm -rf Godeps godep save ./... git add vendor git add -f $(git ls-files --other vendor/) git co -- Godeps/LICENSES Godeps/.license_file_state Godeps/OWNERS
This commit is contained in:
		
							
								
								
									
										7
									
								
								vendor/github.com/gorilla/mux/.travis.yml
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								vendor/github.com/gorilla/mux/.travis.yml
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | ||||
| language: go | ||||
|  | ||||
| go: | ||||
|   - 1.0 | ||||
|   - 1.1 | ||||
|   - 1.2 | ||||
|   - tip | ||||
							
								
								
									
										27
									
								
								vendor/github.com/gorilla/mux/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								vendor/github.com/gorilla/mux/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,27 @@ | ||||
| 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. | ||||
							
								
								
									
										7
									
								
								vendor/github.com/gorilla/mux/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								vendor/github.com/gorilla/mux/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | ||||
| mux | ||||
| === | ||||
| [](https://travis-ci.org/gorilla/mux) | ||||
|  | ||||
| gorilla/mux is a powerful URL router and dispatcher. | ||||
|  | ||||
| Read the full documentation here: http://www.gorillatoolkit.org/pkg/mux | ||||
							
								
								
									
										199
									
								
								vendor/github.com/gorilla/mux/doc.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										199
									
								
								vendor/github.com/gorilla/mux/doc.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,199 @@ | ||||
| // 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 gorilla/mux implements a request router and dispatcher. | ||||
|  | ||||
| The name mux stands for "HTTP request multiplexer". Like the standard | ||||
| http.ServeMux, mux.Router matches incoming requests against a list of | ||||
| registered routes and calls a handler for the route that matches the URL | ||||
| or other conditions. The main features are: | ||||
|  | ||||
| 	* Requests can be matched based on URL host, path, path prefix, schemes, | ||||
| 	  header and query values, HTTP methods or using custom matchers. | ||||
| 	* URL hosts and paths can have variables with an optional regular | ||||
| 	  expression. | ||||
| 	* Registered URLs can be built, or "reversed", which helps maintaining | ||||
| 	  references to resources. | ||||
| 	* Routes can be used as subrouters: nested routes are only tested if the | ||||
| 	  parent route matches. This is useful to define groups of routes that | ||||
| 	  share common conditions like a host, a path prefix or other repeated | ||||
| 	  attributes. As a bonus, this optimizes request matching. | ||||
| 	* It implements the http.Handler interface so it is compatible with the | ||||
| 	  standard http.ServeMux. | ||||
|  | ||||
| Let's start registering a couple of URL paths and handlers: | ||||
|  | ||||
| 	func main() { | ||||
| 		r := mux.NewRouter() | ||||
| 		r.HandleFunc("/", HomeHandler) | ||||
| 		r.HandleFunc("/products", ProductsHandler) | ||||
| 		r.HandleFunc("/articles", ArticlesHandler) | ||||
| 		http.Handle("/", r) | ||||
| 	} | ||||
|  | ||||
| Here we register three routes mapping URL paths to handlers. This is | ||||
| equivalent to how http.HandleFunc() works: if an incoming request URL matches | ||||
| one of the paths, the corresponding handler is called passing | ||||
| (http.ResponseWriter, *http.Request) as parameters. | ||||
|  | ||||
| Paths can have variables. They are defined using the format {name} or | ||||
| {name:pattern}. If a regular expression pattern is not defined, the matched | ||||
| variable will be anything until the next slash. For example: | ||||
|  | ||||
| 	r := mux.NewRouter() | ||||
| 	r.HandleFunc("/products/{key}", ProductHandler) | ||||
| 	r.HandleFunc("/articles/{category}/", ArticlesCategoryHandler) | ||||
| 	r.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler) | ||||
|  | ||||
| The names are used to create a map of route variables which can be retrieved | ||||
| calling mux.Vars(): | ||||
|  | ||||
| 	vars := mux.Vars(request) | ||||
| 	category := vars["category"] | ||||
|  | ||||
| And this is all you need to know about the basic usage. More advanced options | ||||
| are explained below. | ||||
|  | ||||
| Routes can also be restricted to a domain or subdomain. Just define a host | ||||
| pattern to be matched. They can also have variables: | ||||
|  | ||||
| 	r := mux.NewRouter() | ||||
| 	// Only matches if domain is "www.domain.com". | ||||
| 	r.Host("www.domain.com") | ||||
| 	// Matches a dynamic subdomain. | ||||
| 	r.Host("{subdomain:[a-z]+}.domain.com") | ||||
|  | ||||
| There are several other matchers that can be added. To match path prefixes: | ||||
|  | ||||
| 	r.PathPrefix("/products/") | ||||
|  | ||||
| ...or HTTP methods: | ||||
|  | ||||
| 	r.Methods("GET", "POST") | ||||
|  | ||||
| ...or URL schemes: | ||||
|  | ||||
| 	r.Schemes("https") | ||||
|  | ||||
| ...or header values: | ||||
|  | ||||
| 	r.Headers("X-Requested-With", "XMLHttpRequest") | ||||
|  | ||||
| ...or query values: | ||||
|  | ||||
| 	r.Queries("key", "value") | ||||
|  | ||||
| ...or to use a custom matcher function: | ||||
|  | ||||
| 	r.MatcherFunc(func(r *http.Request, rm *RouteMatch) bool { | ||||
| 		return r.ProtoMajor == 0 | ||||
|     }) | ||||
|  | ||||
| ...and finally, it is possible to combine several matchers in a single route: | ||||
|  | ||||
| 	r.HandleFunc("/products", ProductsHandler). | ||||
| 	  Host("www.domain.com"). | ||||
| 	  Methods("GET"). | ||||
| 	  Schemes("http") | ||||
|  | ||||
| Setting the same matching conditions again and again can be boring, so we have | ||||
| a way to group several routes that share the same requirements. | ||||
| We call it "subrouting". | ||||
|  | ||||
| For example, let's say we have several URLs that should only match when the | ||||
| host is "www.domain.com". Create a route for that host and get a "subrouter" | ||||
| from it: | ||||
|  | ||||
| 	r := mux.NewRouter() | ||||
| 	s := r.Host("www.domain.com").Subrouter() | ||||
|  | ||||
| Then register routes in the subrouter: | ||||
|  | ||||
| 	s.HandleFunc("/products/", ProductsHandler) | ||||
| 	s.HandleFunc("/products/{key}", ProductHandler) | ||||
| 	s.HandleFunc("/articles/{category}/{id:[0-9]+}"), ArticleHandler) | ||||
|  | ||||
| The three URL paths we registered above will only be tested if the domain is | ||||
| "www.domain.com", because the subrouter is tested first. This is not | ||||
| only convenient, but also optimizes request matching. You can create | ||||
| subrouters combining any attribute matchers accepted by a route. | ||||
|  | ||||
| Subrouters can be used to create domain or path "namespaces": you define | ||||
| subrouters in a central place and then parts of the app can register its | ||||
| paths relatively to a given subrouter. | ||||
|  | ||||
| There's one more thing about subroutes. When a subrouter has a path prefix, | ||||
| the inner routes use it as base for their paths: | ||||
|  | ||||
| 	r := mux.NewRouter() | ||||
| 	s := r.PathPrefix("/products").Subrouter() | ||||
| 	// "/products/" | ||||
| 	s.HandleFunc("/", ProductsHandler) | ||||
| 	// "/products/{key}/" | ||||
| 	s.HandleFunc("/{key}/", ProductHandler) | ||||
| 	// "/products/{key}/details" | ||||
| 	s.HandleFunc("/{key}/details", ProductDetailsHandler) | ||||
|  | ||||
| Now let's see how to build registered URLs. | ||||
|  | ||||
| Routes can be named. All routes that define a name can have their URLs built, | ||||
| or "reversed". We define a name calling Name() on a route. For example: | ||||
|  | ||||
| 	r := mux.NewRouter() | ||||
| 	r.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler). | ||||
| 	  Name("article") | ||||
|  | ||||
| To build a URL, get the route and call the URL() method, passing a sequence of | ||||
| key/value pairs for the route variables. For the previous route, we would do: | ||||
|  | ||||
| 	url, err := r.Get("article").URL("category", "technology", "id", "42") | ||||
|  | ||||
| ...and the result will be a url.URL with the following path: | ||||
|  | ||||
| 	"/articles/technology/42" | ||||
|  | ||||
| This also works for host variables: | ||||
|  | ||||
| 	r := mux.NewRouter() | ||||
| 	r.Host("{subdomain}.domain.com"). | ||||
| 	  Path("/articles/{category}/{id:[0-9]+}"). | ||||
| 	  HandlerFunc(ArticleHandler). | ||||
| 	  Name("article") | ||||
|  | ||||
| 	// url.String() will be "http://news.domain.com/articles/technology/42" | ||||
| 	url, err := r.Get("article").URL("subdomain", "news", | ||||
| 									 "category", "technology", | ||||
| 									 "id", "42") | ||||
|  | ||||
| All variables defined in the route are required, and their values must | ||||
| conform to the corresponding patterns. These requirements guarantee that a | ||||
| generated URL will always match a registered route -- the only exception is | ||||
| for explicitly defined "build-only" routes which never match. | ||||
|  | ||||
| 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: | ||||
|  | ||||
| 	// "http://news.domain.com/" | ||||
| 	host, err := r.Get("article").URLHost("subdomain", "news") | ||||
|  | ||||
| 	// "/articles/technology/42" | ||||
| 	path, err := r.Get("article").URLPath("category", "technology", "id", "42") | ||||
|  | ||||
| And if you use subrouters, host and path defined separately can be built | ||||
| as well: | ||||
|  | ||||
| 	r := mux.NewRouter() | ||||
| 	s := r.Host("{subdomain}.domain.com").Subrouter() | ||||
| 	s.Path("/articles/{category}/{id:[0-9]+}"). | ||||
| 	  HandlerFunc(ArticleHandler). | ||||
| 	  Name("article") | ||||
|  | ||||
| 	// "http://news.domain.com/articles/technology/42" | ||||
| 	url, err := r.Get("article").URL("subdomain", "news", | ||||
| 									 "category", "technology", | ||||
| 									 "id", "42") | ||||
| */ | ||||
| package mux | ||||
							
								
								
									
										366
									
								
								vendor/github.com/gorilla/mux/mux.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										366
									
								
								vendor/github.com/gorilla/mux/mux.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,366 @@ | ||||
| // 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 mux | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"net/http" | ||||
| 	"path" | ||||
|  | ||||
| 	"github.com/gorilla/context" | ||||
| ) | ||||
|  | ||||
| // NewRouter returns a new router instance. | ||||
| func NewRouter() *Router { | ||||
| 	return &Router{namedRoutes: make(map[string]*Route), KeepContext: false} | ||||
| } | ||||
|  | ||||
| // Router registers routes to be matched and dispatches a handler. | ||||
| // | ||||
| // It implements the http.Handler interface, so it can be registered to serve | ||||
| // requests: | ||||
| // | ||||
| //     var router = mux.NewRouter() | ||||
| // | ||||
| //     func main() { | ||||
| //         http.Handle("/", router) | ||||
| //     } | ||||
| // | ||||
| // Or, for Google App Engine, register it in a init() function: | ||||
| // | ||||
| //     func init() { | ||||
| //         http.Handle("/", router) | ||||
| //     } | ||||
| // | ||||
| // This will send all incoming requests to the router. | ||||
| type Router struct { | ||||
| 	// Configurable Handler to be used when no route matches. | ||||
| 	NotFoundHandler 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 | ||||
| 	// If true, do not clear the request context after handling the request | ||||
| 	KeepContext bool | ||||
| } | ||||
|  | ||||
| // Match matches registered routes against the request. | ||||
| func (r *Router) Match(req *http.Request, match *RouteMatch) bool { | ||||
| 	for _, route := range r.routes { | ||||
| 		if route.Match(req, match) { | ||||
| 			return true | ||||
| 		} | ||||
| 	} | ||||
| 	return false | ||||
| } | ||||
|  | ||||
| // ServeHTTP dispatches the handler registered in the matched route. | ||||
| // | ||||
| // 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) { | ||||
| 	// Clean path to canonical form and redirect. | ||||
| 	if p := cleanPath(req.URL.Path); p != req.URL.Path { | ||||
|  | ||||
| 		// Added 3 lines (Philip Schlump) - It was droping 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) { | ||||
| 		handler = match.Handler | ||||
| 		setVars(req, match.Vars) | ||||
| 		setCurrentRoute(req, match.Route) | ||||
| 	} | ||||
| 	if handler == nil { | ||||
| 		handler = r.NotFoundHandler | ||||
| 		if handler == nil { | ||||
| 			handler = http.NotFoundHandler() | ||||
| 		} | ||||
| 	} | ||||
| 	if !r.KeepContext { | ||||
| 		defer context.Clear(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] | ||||
| } | ||||
|  | ||||
| // 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] | ||||
| } | ||||
|  | ||||
| // StrictSlash defines the trailing slash behavior for new routes. The initial | ||||
| // value is false. | ||||
| // | ||||
| // When true, if the route path is "/path/", accessing "/path" will redirect | ||||
| // to the former and vice versa. In other words, your application will always | ||||
| // see the path as specified in the route. | ||||
| // | ||||
| // When false, if the route path is "/path", accessing "/path/" will not match | ||||
| // this route and vice versa. | ||||
| // | ||||
| // Special case: when a route sets a path prefix using the PathPrefix() method, | ||||
| // strict slash is ignored for that route because the redirect behavior can't | ||||
| // be determined from a prefix alone. However, any subrouters created from that | ||||
| // route inherit the original StrictSlash setting. | ||||
| func (r *Router) StrictSlash(value bool) *Router { | ||||
| 	r.strictSlash = value | ||||
| 	return r | ||||
| } | ||||
|  | ||||
| // ---------------------------------------------------------------------------- | ||||
| // parentRoute | ||||
| // ---------------------------------------------------------------------------- | ||||
|  | ||||
| // 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} | ||||
| 	r.routes = append(r.routes, route) | ||||
| 	return route | ||||
| } | ||||
|  | ||||
| // 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 { | ||||
| 	return r.NewRoute().Path(path).Handler(handler) | ||||
| } | ||||
|  | ||||
| // HandleFunc registers a new route with a matcher for the URL path. | ||||
| // See Route.Path() and Route.HandlerFunc(). | ||||
| func (r *Router) HandleFunc(path string, f func(http.ResponseWriter, | ||||
| 	*http.Request)) *Route { | ||||
| 	return r.NewRoute().Path(path).HandlerFunc(f) | ||||
| } | ||||
|  | ||||
| // Headers registers a new route with a matcher for request header values. | ||||
| // See Route.Headers(). | ||||
| func (r *Router) Headers(pairs ...string) *Route { | ||||
| 	return r.NewRoute().Headers(pairs...) | ||||
| } | ||||
|  | ||||
| // Host registers a new route with a matcher for the URL host. | ||||
| // See Route.Host(). | ||||
| func (r *Router) Host(tpl string) *Route { | ||||
| 	return r.NewRoute().Host(tpl) | ||||
| } | ||||
|  | ||||
| // MatcherFunc registers a new route with a custom matcher function. | ||||
| // See Route.MatcherFunc(). | ||||
| func (r *Router) MatcherFunc(f MatcherFunc) *Route { | ||||
| 	return r.NewRoute().MatcherFunc(f) | ||||
| } | ||||
|  | ||||
| // Methods registers a new route with a matcher for HTTP methods. | ||||
| // See Route.Methods(). | ||||
| func (r *Router) Methods(methods ...string) *Route { | ||||
| 	return r.NewRoute().Methods(methods...) | ||||
| } | ||||
|  | ||||
| // Path registers a new route with a matcher for the URL path. | ||||
| // See Route.Path(). | ||||
| func (r *Router) Path(tpl string) *Route { | ||||
| 	return r.NewRoute().Path(tpl) | ||||
| } | ||||
|  | ||||
| // PathPrefix registers a new route with a matcher for the URL path prefix. | ||||
| // See Route.PathPrefix(). | ||||
| func (r *Router) PathPrefix(tpl string) *Route { | ||||
| 	return r.NewRoute().PathPrefix(tpl) | ||||
| } | ||||
|  | ||||
| // Queries registers a new route with a matcher for URL query values. | ||||
| // See Route.Queries(). | ||||
| func (r *Router) Queries(pairs ...string) *Route { | ||||
| 	return r.NewRoute().Queries(pairs...) | ||||
| } | ||||
|  | ||||
| // Schemes registers a new route with a matcher for URL schemes. | ||||
| // See Route.Schemes(). | ||||
| func (r *Router) Schemes(schemes ...string) *Route { | ||||
| 	return r.NewRoute().Schemes(schemes...) | ||||
| } | ||||
|  | ||||
| // BuildVars registers a new route with a custom function for modifying | ||||
| // route variables before building a URL. | ||||
| func (r *Router) BuildVarsFunc(f BuildVarsFunc) *Route { | ||||
| 	return r.NewRoute().BuildVarsFunc(f) | ||||
| } | ||||
|  | ||||
| // ---------------------------------------------------------------------------- | ||||
| // Context | ||||
| // ---------------------------------------------------------------------------- | ||||
|  | ||||
| // RouteMatch stores information about a matched route. | ||||
| type RouteMatch struct { | ||||
| 	Route   *Route | ||||
| 	Handler http.Handler | ||||
| 	Vars    map[string]string | ||||
| } | ||||
|  | ||||
| type contextKey int | ||||
|  | ||||
| const ( | ||||
| 	varsKey contextKey = iota | ||||
| 	routeKey | ||||
| ) | ||||
|  | ||||
| // Vars returns the route variables for the current request, if any. | ||||
| func Vars(r *http.Request) map[string]string { | ||||
| 	if rv := context.Get(r, varsKey); rv != nil { | ||||
| 		return rv.(map[string]string) | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // CurrentRoute returns the matched route for the current request, if any. | ||||
| func CurrentRoute(r *http.Request) *Route { | ||||
| 	if rv := context.Get(r, routeKey); rv != nil { | ||||
| 		return rv.(*Route) | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func setVars(r *http.Request, val interface{}) { | ||||
| 	context.Set(r, varsKey, val) | ||||
| } | ||||
|  | ||||
| func setCurrentRoute(r *http.Request, val interface{}) { | ||||
| 	context.Set(r, routeKey, val) | ||||
| } | ||||
|  | ||||
| // ---------------------------------------------------------------------------- | ||||
| // Helpers | ||||
| // ---------------------------------------------------------------------------- | ||||
|  | ||||
| // cleanPath returns the canonical path for p, eliminating . and .. elements. | ||||
| // Borrowed from the net/http package. | ||||
| func cleanPath(p string) string { | ||||
| 	if p == "" { | ||||
| 		return "/" | ||||
| 	} | ||||
| 	if p[0] != '/' { | ||||
| 		p = "/" + p | ||||
| 	} | ||||
| 	np := path.Clean(p) | ||||
| 	// path.Clean removes trailing slash except for root; | ||||
| 	// put the trailing slash back if necessary. | ||||
| 	if p[len(p)-1] == '/' && np != "/" { | ||||
| 		np += "/" | ||||
| 	} | ||||
| 	return np | ||||
| } | ||||
|  | ||||
| // uniqueVars returns an error if two slices contain duplicated strings. | ||||
| func uniqueVars(s1, s2 []string) error { | ||||
| 	for _, v1 := range s1 { | ||||
| 		for _, v2 := range s2 { | ||||
| 			if v1 == v2 { | ||||
| 				return fmt.Errorf("mux: duplicated route variable %q", v2) | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // mapFromPairs converts variadic string parameters to a string map. | ||||
| func mapFromPairs(pairs ...string) (map[string]string, error) { | ||||
| 	length := len(pairs) | ||||
| 	if length%2 != 0 { | ||||
| 		return nil, fmt.Errorf( | ||||
| 			"mux: number of parameters must be multiple of 2, got %v", pairs) | ||||
| 	} | ||||
| 	m := make(map[string]string, length/2) | ||||
| 	for i := 0; i < length; i += 2 { | ||||
| 		m[pairs[i]] = pairs[i+1] | ||||
| 	} | ||||
| 	return m, nil | ||||
| } | ||||
|  | ||||
| // matchInArray returns true if the given string value is in the array. | ||||
| func matchInArray(arr []string, value string) bool { | ||||
| 	for _, v := range arr { | ||||
| 		if v == value { | ||||
| 			return true | ||||
| 		} | ||||
| 	} | ||||
| 	return false | ||||
| } | ||||
|  | ||||
| // matchMap returns true if the given key/value pairs exist in a given map. | ||||
| func matchMap(toCheck map[string]string, toMatch map[string][]string, | ||||
| 	canonicalKey bool) bool { | ||||
| 	for k, v := range toCheck { | ||||
| 		// Check if key exists. | ||||
| 		if canonicalKey { | ||||
| 			k = http.CanonicalHeaderKey(k) | ||||
| 		} | ||||
| 		if values := toMatch[k]; values == nil { | ||||
| 			return false | ||||
| 		} else if v != "" { | ||||
| 			// If value was defined as an empty string we only check that the | ||||
| 			// key exists. Otherwise we also check for equality. | ||||
| 			valueExists := false | ||||
| 			for _, value := range values { | ||||
| 				if v == value { | ||||
| 					valueExists = true | ||||
| 					break | ||||
| 				} | ||||
| 			} | ||||
| 			if !valueExists { | ||||
| 				return false | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	return true | ||||
| } | ||||
							
								
								
									
										272
									
								
								vendor/github.com/gorilla/mux/regexp.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										272
									
								
								vendor/github.com/gorilla/mux/regexp.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,272 @@ | ||||
| // 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 mux | ||||
|  | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"fmt" | ||||
| 	"net/http" | ||||
| 	"net/url" | ||||
| 	"regexp" | ||||
| 	"strings" | ||||
| ) | ||||
|  | ||||
| // newRouteRegexp parses a route template and returns a routeRegexp, | ||||
| // used to match a host, a path or a query string. | ||||
| // | ||||
| // It will extract named variables, assemble a regexp to be matched, create | ||||
| // a "reverse" template to build URLs and compile regexps to validate variable | ||||
| // values used in URL building. | ||||
| // | ||||
| // Previously we accepted only Python-like identifiers for variable | ||||
| // names ([a-zA-Z_][a-zA-Z0-9_]*), but currently the only restriction is that | ||||
| // name and pattern can't be empty, and names can't contain a colon. | ||||
| func newRouteRegexp(tpl string, matchHost, matchPrefix, matchQuery, strictSlash bool) (*routeRegexp, error) { | ||||
| 	// Check if it is well-formed. | ||||
| 	idxs, errBraces := braceIndices(tpl) | ||||
| 	if errBraces != nil { | ||||
| 		return nil, errBraces | ||||
| 	} | ||||
| 	// Backup the original. | ||||
| 	template := tpl | ||||
| 	// Now let's parse it. | ||||
| 	defaultPattern := "[^/]+" | ||||
| 	if matchQuery { | ||||
| 		defaultPattern = "[^?&]+" | ||||
| 		matchPrefix = true | ||||
| 	} else if matchHost { | ||||
| 		defaultPattern = "[^.]+" | ||||
| 		matchPrefix = false | ||||
| 	} | ||||
| 	// Only match strict slash if not matching | ||||
| 	if matchPrefix || matchHost || matchQuery { | ||||
| 		strictSlash = false | ||||
| 	} | ||||
| 	// Set a flag for strictSlash. | ||||
| 	endSlash := false | ||||
| 	if strictSlash && strings.HasSuffix(tpl, "/") { | ||||
| 		tpl = tpl[:len(tpl)-1] | ||||
| 		endSlash = true | ||||
| 	} | ||||
| 	varsN := make([]string, len(idxs)/2) | ||||
| 	varsR := make([]*regexp.Regexp, len(idxs)/2) | ||||
| 	pattern := bytes.NewBufferString("") | ||||
| 	if !matchQuery { | ||||
| 		pattern.WriteByte('^') | ||||
| 	} | ||||
| 	reverse := bytes.NewBufferString("") | ||||
| 	var end int | ||||
| 	var err error | ||||
| 	for i := 0; i < len(idxs); i += 2 { | ||||
| 		// Set all values we are interested in. | ||||
| 		raw := tpl[end:idxs[i]] | ||||
| 		end = idxs[i+1] | ||||
| 		parts := strings.SplitN(tpl[idxs[i]+1:end-1], ":", 2) | ||||
| 		name := parts[0] | ||||
| 		patt := defaultPattern | ||||
| 		if len(parts) == 2 { | ||||
| 			patt = parts[1] | ||||
| 		} | ||||
| 		// Name or pattern can't be empty. | ||||
| 		if name == "" || patt == "" { | ||||
| 			return nil, fmt.Errorf("mux: missing name or pattern in %q", | ||||
| 				tpl[idxs[i]:end]) | ||||
| 		} | ||||
| 		// Build the regexp pattern. | ||||
| 		fmt.Fprintf(pattern, "%s(%s)", regexp.QuoteMeta(raw), patt) | ||||
| 		// Build the reverse template. | ||||
| 		fmt.Fprintf(reverse, "%s%%s", raw) | ||||
| 		// Append variable name and compiled pattern. | ||||
| 		varsN[i/2] = name | ||||
| 		varsR[i/2], err = regexp.Compile(fmt.Sprintf("^%s$", patt)) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 	} | ||||
| 	// Add the remaining. | ||||
| 	raw := tpl[end:] | ||||
| 	pattern.WriteString(regexp.QuoteMeta(raw)) | ||||
| 	if strictSlash { | ||||
| 		pattern.WriteString("[/]?") | ||||
| 	} | ||||
| 	if !matchPrefix { | ||||
| 		pattern.WriteByte('$') | ||||
| 	} | ||||
| 	reverse.WriteString(raw) | ||||
| 	if endSlash { | ||||
| 		reverse.WriteByte('/') | ||||
| 	} | ||||
| 	// Compile full regexp. | ||||
| 	reg, errCompile := regexp.Compile(pattern.String()) | ||||
| 	if errCompile != nil { | ||||
| 		return nil, errCompile | ||||
| 	} | ||||
| 	// Done! | ||||
| 	return &routeRegexp{ | ||||
| 		template:    template, | ||||
| 		matchHost:   matchHost, | ||||
| 		matchQuery:  matchQuery, | ||||
| 		strictSlash: strictSlash, | ||||
| 		regexp:      reg, | ||||
| 		reverse:     reverse.String(), | ||||
| 		varsN:       varsN, | ||||
| 		varsR:       varsR, | ||||
| 	}, nil | ||||
| } | ||||
|  | ||||
| // routeRegexp stores a regexp to match a host or path and information to | ||||
| // collect and validate route variables. | ||||
| type routeRegexp struct { | ||||
| 	// The unmodified template. | ||||
| 	template string | ||||
| 	// True for host match, false for path or query string match. | ||||
| 	matchHost bool | ||||
| 	// True for query string match, false for path and host match. | ||||
| 	matchQuery bool | ||||
| 	// The strictSlash value defined on the route, but disabled if PathPrefix was used. | ||||
| 	strictSlash bool | ||||
| 	// Expanded regexp. | ||||
| 	regexp *regexp.Regexp | ||||
| 	// Reverse template. | ||||
| 	reverse string | ||||
| 	// Variable names. | ||||
| 	varsN []string | ||||
| 	// Variable regexps (validators). | ||||
| 	varsR []*regexp.Regexp | ||||
| } | ||||
|  | ||||
| // Match matches the regexp against the URL host or path. | ||||
| func (r *routeRegexp) Match(req *http.Request, match *RouteMatch) bool { | ||||
| 	if !r.matchHost { | ||||
| 		if r.matchQuery { | ||||
| 			return r.regexp.MatchString(req.URL.RawQuery) | ||||
| 		} else { | ||||
| 			return r.regexp.MatchString(req.URL.Path) | ||||
| 		} | ||||
| 	} | ||||
| 	return r.regexp.MatchString(getHost(req)) | ||||
| } | ||||
|  | ||||
| // url builds a URL part using the given values. | ||||
| func (r *routeRegexp) url(values map[string]string) (string, error) { | ||||
| 	urlValues := make([]interface{}, len(r.varsN)) | ||||
| 	for k, v := range r.varsN { | ||||
| 		value, ok := values[v] | ||||
| 		if !ok { | ||||
| 			return "", fmt.Errorf("mux: missing route variable %q", v) | ||||
| 		} | ||||
| 		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 | ||||
| 		// individual variables. This is faster but to provide a good error | ||||
| 		// message, we check individual regexps if the URL doesn't match. | ||||
| 		for k, v := range r.varsN { | ||||
| 			if !r.varsR[k].MatchString(values[v]) { | ||||
| 				return "", fmt.Errorf( | ||||
| 					"mux: variable %q doesn't match, expected %q", values[v], | ||||
| 					r.varsR[k].String()) | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	return rv, nil | ||||
| } | ||||
|  | ||||
| // braceIndices returns the first level curly brace indices from a string. | ||||
| // It returns an error in case of unbalanced braces. | ||||
| func braceIndices(s string) ([]int, error) { | ||||
| 	var level, idx int | ||||
| 	idxs := make([]int, 0) | ||||
| 	for i := 0; i < len(s); i++ { | ||||
| 		switch s[i] { | ||||
| 		case '{': | ||||
| 			if level++; level == 1 { | ||||
| 				idx = i | ||||
| 			} | ||||
| 		case '}': | ||||
| 			if level--; level == 0 { | ||||
| 				idxs = append(idxs, idx, i+1) | ||||
| 			} else if level < 0 { | ||||
| 				return nil, fmt.Errorf("mux: unbalanced braces in %q", s) | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	if level != 0 { | ||||
| 		return nil, fmt.Errorf("mux: unbalanced braces in %q", s) | ||||
| 	} | ||||
| 	return idxs, nil | ||||
| } | ||||
|  | ||||
| // ---------------------------------------------------------------------------- | ||||
| // routeRegexpGroup | ||||
| // ---------------------------------------------------------------------------- | ||||
|  | ||||
| // routeRegexpGroup groups the route matchers that carry variables. | ||||
| type routeRegexpGroup struct { | ||||
| 	host    *routeRegexp | ||||
| 	path    *routeRegexp | ||||
| 	queries []*routeRegexp | ||||
| } | ||||
|  | ||||
| // setMatch extracts the variables from the URL once a route matches. | ||||
| func (v *routeRegexpGroup) setMatch(req *http.Request, m *RouteMatch, r *Route) { | ||||
| 	// Store host variables. | ||||
| 	if v.host != nil { | ||||
| 		hostVars := v.host.regexp.FindStringSubmatch(getHost(req)) | ||||
| 		if hostVars != nil { | ||||
| 			for k, v := range v.host.varsN { | ||||
| 				m.Vars[v] = hostVars[k+1] | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	// Store path variables. | ||||
| 	if v.path != nil { | ||||
| 		pathVars := v.path.regexp.FindStringSubmatch(req.URL.Path) | ||||
| 		if pathVars != nil { | ||||
| 			for k, v := range v.path.varsN { | ||||
| 				m.Vars[v] = pathVars[k+1] | ||||
| 			} | ||||
| 			// Check if we should redirect. | ||||
| 			if v.path.strictSlash { | ||||
| 				p1 := strings.HasSuffix(req.URL.Path, "/") | ||||
| 				p2 := strings.HasSuffix(v.path.template, "/") | ||||
| 				if p1 != p2 { | ||||
| 					u, _ := url.Parse(req.URL.String()) | ||||
| 					if p1 { | ||||
| 						u.Path = u.Path[:len(u.Path)-1] | ||||
| 					} else { | ||||
| 						u.Path += "/" | ||||
| 					} | ||||
| 					m.Handler = http.RedirectHandler(u.String(), 301) | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	// Store query string variables. | ||||
| 	rawQuery := req.URL.RawQuery | ||||
| 	for _, q := range v.queries { | ||||
| 		queryVars := q.regexp.FindStringSubmatch(rawQuery) | ||||
| 		if queryVars != nil { | ||||
| 			for k, v := range q.varsN { | ||||
| 				m.Vars[v] = queryVars[k+1] | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // getHost tries its best to return the request host. | ||||
| func getHost(r *http.Request) string { | ||||
| 	if r.URL.IsAbs() { | ||||
| 		return r.URL.Host | ||||
| 	} | ||||
| 	host := r.Host | ||||
| 	// Slice off any port information. | ||||
| 	if i := strings.Index(host, ":"); i != -1 { | ||||
| 		host = host[:i] | ||||
| 	} | ||||
| 	return host | ||||
|  | ||||
| } | ||||
							
								
								
									
										571
									
								
								vendor/github.com/gorilla/mux/route.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										571
									
								
								vendor/github.com/gorilla/mux/route.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,571 @@ | ||||
| // 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 mux | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"net/http" | ||||
| 	"net/url" | ||||
| 	"strings" | ||||
| ) | ||||
|  | ||||
| // Route stores information to match a request and build URLs. | ||||
| type Route struct { | ||||
| 	// Parent where the route was registered (a Router). | ||||
| 	parent parentRoute | ||||
| 	// Request handler for the route. | ||||
| 	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, this route never matches: it is only used to build URLs. | ||||
| 	buildOnly bool | ||||
| 	// The name used to build URLs. | ||||
| 	name string | ||||
| 	// Error resulted from building a route. | ||||
| 	err error | ||||
|  | ||||
| 	buildVarsFunc BuildVarsFunc | ||||
| } | ||||
|  | ||||
| // Match matches the route against the request. | ||||
| func (r *Route) Match(req *http.Request, match *RouteMatch) bool { | ||||
| 	if r.buildOnly || r.err != nil { | ||||
| 		return false | ||||
| 	} | ||||
| 	// Match everything. | ||||
| 	for _, m := range r.matchers { | ||||
| 		if matched := m.Match(req, match); !matched { | ||||
| 			return false | ||||
| 		} | ||||
| 	} | ||||
| 	// Yay, we have a match. Let's collect some info about it. | ||||
| 	if match.Route == nil { | ||||
| 		match.Route = r | ||||
| 	} | ||||
| 	if match.Handler == nil { | ||||
| 		match.Handler = r.handler | ||||
| 	} | ||||
| 	if match.Vars == nil { | ||||
| 		match.Vars = make(map[string]string) | ||||
| 	} | ||||
| 	// Set variables. | ||||
| 	if r.regexp != nil { | ||||
| 		r.regexp.setMatch(req, match, r) | ||||
| 	} | ||||
| 	return true | ||||
| } | ||||
|  | ||||
| // ---------------------------------------------------------------------------- | ||||
| // Route attributes | ||||
| // ---------------------------------------------------------------------------- | ||||
|  | ||||
| // GetError returns an error resulted from building the route, if any. | ||||
| func (r *Route) GetError() error { | ||||
| 	return r.err | ||||
| } | ||||
|  | ||||
| // BuildOnly sets the route to never match: it is only used to build URLs. | ||||
| func (r *Route) BuildOnly() *Route { | ||||
| 	r.buildOnly = true | ||||
| 	return r | ||||
| } | ||||
|  | ||||
| // Handler -------------------------------------------------------------------- | ||||
|  | ||||
| // Handler sets a handler for the route. | ||||
| func (r *Route) Handler(handler http.Handler) *Route { | ||||
| 	if r.err == nil { | ||||
| 		r.handler = handler | ||||
| 	} | ||||
| 	return r | ||||
| } | ||||
|  | ||||
| // HandlerFunc sets a handler function for the route. | ||||
| func (r *Route) HandlerFunc(f func(http.ResponseWriter, *http.Request)) *Route { | ||||
| 	return r.Handler(http.HandlerFunc(f)) | ||||
| } | ||||
|  | ||||
| // GetHandler returns the handler for the route, if any. | ||||
| func (r *Route) GetHandler() http.Handler { | ||||
| 	return r.handler | ||||
| } | ||||
|  | ||||
| // Name ----------------------------------------------------------------------- | ||||
|  | ||||
| // Name sets the name for the route, used to build URLs. | ||||
| // If the name was registered already it will be overwritten. | ||||
| func (r *Route) Name(name string) *Route { | ||||
| 	if r.name != "" { | ||||
| 		r.err = fmt.Errorf("mux: route already has name %q, can't set %q", | ||||
| 			r.name, name) | ||||
| 	} | ||||
| 	if r.err == nil { | ||||
| 		r.name = name | ||||
| 		r.getNamedRoutes()[name] = r | ||||
| 	} | ||||
| 	return r | ||||
| } | ||||
|  | ||||
| // GetName returns the name for the route, if any. | ||||
| func (r *Route) GetName() string { | ||||
| 	return r.name | ||||
| } | ||||
|  | ||||
| // ---------------------------------------------------------------------------- | ||||
| // Matchers | ||||
| // ---------------------------------------------------------------------------- | ||||
|  | ||||
| // matcher types try to match a request. | ||||
| type matcher interface { | ||||
| 	Match(*http.Request, *RouteMatch) bool | ||||
| } | ||||
|  | ||||
| // addMatcher adds a matcher to the route. | ||||
| func (r *Route) addMatcher(m matcher) *Route { | ||||
| 	if r.err == nil { | ||||
| 		r.matchers = append(r.matchers, m) | ||||
| 	} | ||||
| 	return r | ||||
| } | ||||
|  | ||||
| // addRegexpMatcher adds a host or path matcher and builder to a route. | ||||
| func (r *Route) addRegexpMatcher(tpl string, matchHost, matchPrefix, matchQuery bool) error { | ||||
| 	if r.err != nil { | ||||
| 		return r.err | ||||
| 	} | ||||
| 	r.regexp = r.getRegexpGroup() | ||||
| 	if !matchHost && !matchQuery { | ||||
| 		if len(tpl) == 0 || tpl[0] != '/' { | ||||
| 			return fmt.Errorf("mux: path must start with a slash, got %q", tpl) | ||||
| 		} | ||||
| 		if r.regexp.path != nil { | ||||
| 			tpl = strings.TrimRight(r.regexp.path.template, "/") + tpl | ||||
| 		} | ||||
| 	} | ||||
| 	rr, err := newRouteRegexp(tpl, matchHost, matchPrefix, matchQuery, r.strictSlash) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	for _, q := range r.regexp.queries { | ||||
| 		if err = uniqueVars(rr.varsN, q.varsN); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| 	if matchHost { | ||||
| 		if r.regexp.path != nil { | ||||
| 			if err = uniqueVars(rr.varsN, r.regexp.path.varsN); err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 		} | ||||
| 		r.regexp.host = rr | ||||
| 	} else { | ||||
| 		if r.regexp.host != nil { | ||||
| 			if err = uniqueVars(rr.varsN, r.regexp.host.varsN); err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 		} | ||||
| 		if matchQuery { | ||||
| 			r.regexp.queries = append(r.regexp.queries, rr) | ||||
| 		} else { | ||||
| 			r.regexp.path = rr | ||||
| 		} | ||||
| 	} | ||||
| 	r.addMatcher(rr) | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // Headers -------------------------------------------------------------------- | ||||
|  | ||||
| // headerMatcher matches the request against header values. | ||||
| type headerMatcher map[string]string | ||||
|  | ||||
| func (m headerMatcher) Match(r *http.Request, match *RouteMatch) bool { | ||||
| 	return matchMap(m, r.Header, true) | ||||
| } | ||||
|  | ||||
| // Headers adds a matcher for request header values. | ||||
| // It accepts a sequence of key/value pairs to be matched. For example: | ||||
| // | ||||
| //     r := mux.NewRouter() | ||||
| //     r.Headers("Content-Type", "application/json", | ||||
| //               "X-Requested-With", "XMLHttpRequest") | ||||
| // | ||||
| // The above route will only match if both request header values match. | ||||
| // | ||||
| // It the value is an empty string, it will match any value if the key is set. | ||||
| func (r *Route) Headers(pairs ...string) *Route { | ||||
| 	if r.err == nil { | ||||
| 		var headers map[string]string | ||||
| 		headers, r.err = mapFromPairs(pairs...) | ||||
| 		return r.addMatcher(headerMatcher(headers)) | ||||
| 	} | ||||
| 	return r | ||||
| } | ||||
|  | ||||
| // Host ----------------------------------------------------------------------- | ||||
|  | ||||
| // Host adds a matcher for the URL host. | ||||
| // It accepts a template with zero or more URL variables enclosed by {}. | ||||
| // Variables can define an optional regexp pattern to me matched: | ||||
| // | ||||
| // - {name} matches anything until the next dot. | ||||
| // | ||||
| // - {name:pattern} matches the given regexp pattern. | ||||
| // | ||||
| // For example: | ||||
| // | ||||
| //     r := mux.NewRouter() | ||||
| //     r.Host("www.domain.com") | ||||
| //     r.Host("{subdomain}.domain.com") | ||||
| //     r.Host("{subdomain:[a-z]+}.domain.com") | ||||
| // | ||||
| // Variable names must be unique in a given route. They can be retrieved | ||||
| // calling mux.Vars(request). | ||||
| func (r *Route) Host(tpl string) *Route { | ||||
| 	r.err = r.addRegexpMatcher(tpl, true, false, false) | ||||
| 	return r | ||||
| } | ||||
|  | ||||
| // MatcherFunc ---------------------------------------------------------------- | ||||
|  | ||||
| // MatcherFunc is the function signature used by custom matchers. | ||||
| type MatcherFunc func(*http.Request, *RouteMatch) bool | ||||
|  | ||||
| func (m MatcherFunc) Match(r *http.Request, match *RouteMatch) bool { | ||||
| 	return m(r, match) | ||||
| } | ||||
|  | ||||
| // MatcherFunc adds a custom function to be used as request matcher. | ||||
| func (r *Route) MatcherFunc(f MatcherFunc) *Route { | ||||
| 	return r.addMatcher(f) | ||||
| } | ||||
|  | ||||
| // Methods -------------------------------------------------------------------- | ||||
|  | ||||
| // methodMatcher matches the request against HTTP methods. | ||||
| type methodMatcher []string | ||||
|  | ||||
| func (m methodMatcher) Match(r *http.Request, match *RouteMatch) bool { | ||||
| 	return matchInArray(m, r.Method) | ||||
| } | ||||
|  | ||||
| // Methods adds a matcher for HTTP methods. | ||||
| // It accepts a sequence of one or more methods to be matched, e.g.: | ||||
| // "GET", "POST", "PUT". | ||||
| func (r *Route) Methods(methods ...string) *Route { | ||||
| 	for k, v := range methods { | ||||
| 		methods[k] = strings.ToUpper(v) | ||||
| 	} | ||||
| 	return r.addMatcher(methodMatcher(methods)) | ||||
| } | ||||
|  | ||||
| // Path ----------------------------------------------------------------------- | ||||
|  | ||||
| // Path adds a matcher for the URL path. | ||||
| // It accepts a template with zero or more URL variables enclosed by {}. The | ||||
| // template must start with a "/". | ||||
| // Variables can define an optional regexp pattern to me matched: | ||||
| // | ||||
| // - {name} matches anything until the next slash. | ||||
| // | ||||
| // - {name:pattern} matches the given regexp pattern. | ||||
| // | ||||
| // For example: | ||||
| // | ||||
| //     r := mux.NewRouter() | ||||
| //     r.Path("/products/").Handler(ProductsHandler) | ||||
| //     r.Path("/products/{key}").Handler(ProductsHandler) | ||||
| //     r.Path("/articles/{category}/{id:[0-9]+}"). | ||||
| //       Handler(ArticleHandler) | ||||
| // | ||||
| // Variable names must be unique in a given route. They can be retrieved | ||||
| // calling mux.Vars(request). | ||||
| func (r *Route) Path(tpl string) *Route { | ||||
| 	r.err = r.addRegexpMatcher(tpl, false, false, false) | ||||
| 	return r | ||||
| } | ||||
|  | ||||
| // PathPrefix ----------------------------------------------------------------- | ||||
|  | ||||
| // PathPrefix adds a matcher for the URL path prefix. This matches if the given | ||||
| // template is a prefix of the full URL path. See Route.Path() for details on | ||||
| // the tpl argument. | ||||
| // | ||||
| // Note that it does not treat slashes specially ("/foobar/" will be matched by | ||||
| // the prefix "/foo") so you may want to use a trailing slash here. | ||||
| // | ||||
| // Also note that the setting of Router.StrictSlash() has no effect on routes | ||||
| // with a PathPrefix matcher. | ||||
| func (r *Route) PathPrefix(tpl string) *Route { | ||||
| 	r.err = r.addRegexpMatcher(tpl, false, true, false) | ||||
| 	return r | ||||
| } | ||||
|  | ||||
| // Query ---------------------------------------------------------------------- | ||||
|  | ||||
| // Queries adds a matcher for URL query values. | ||||
| // It accepts a sequence of key/value pairs. Values may define variables. | ||||
| // For example: | ||||
| // | ||||
| //     r := mux.NewRouter() | ||||
| //     r.Queries("foo", "bar", "id", "{id:[0-9]+}") | ||||
| // | ||||
| // The above route will only match if the URL contains the defined queries | ||||
| // values, e.g.: ?foo=bar&id=42. | ||||
| // | ||||
| // It the value is an empty string, it will match any value if the key is set. | ||||
| // | ||||
| // Variables can define an optional regexp pattern to me matched: | ||||
| // | ||||
| // - {name} matches anything until the next slash. | ||||
| // | ||||
| // - {name:pattern} matches the given regexp pattern. | ||||
| func (r *Route) Queries(pairs ...string) *Route { | ||||
| 	length := len(pairs) | ||||
| 	if length%2 != 0 { | ||||
| 		r.err = fmt.Errorf( | ||||
| 			"mux: number of parameters must be multiple of 2, got %v", pairs) | ||||
| 		return nil | ||||
| 	} | ||||
| 	for i := 0; i < length; i += 2 { | ||||
| 		if r.err = r.addRegexpMatcher(pairs[i]+"="+pairs[i+1], false, true, true); r.err != nil { | ||||
| 			return r | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return r | ||||
| } | ||||
|  | ||||
| // Schemes -------------------------------------------------------------------- | ||||
|  | ||||
| // schemeMatcher matches the request against URL schemes. | ||||
| type schemeMatcher []string | ||||
|  | ||||
| func (m schemeMatcher) Match(r *http.Request, match *RouteMatch) bool { | ||||
| 	return matchInArray(m, r.URL.Scheme) | ||||
| } | ||||
|  | ||||
| // Schemes adds a matcher for URL schemes. | ||||
| // It accepts a sequence of schemes to be matched, e.g.: "http", "https". | ||||
| func (r *Route) Schemes(schemes ...string) *Route { | ||||
| 	for k, v := range schemes { | ||||
| 		schemes[k] = strings.ToLower(v) | ||||
| 	} | ||||
| 	return r.addMatcher(schemeMatcher(schemes)) | ||||
| } | ||||
|  | ||||
| // BuildVarsFunc -------------------------------------------------------------- | ||||
|  | ||||
| // BuildVarsFunc is the function signature used by custom build variable | ||||
| // functions (which can modify route variables before a route's URL is built). | ||||
| type BuildVarsFunc func(map[string]string) map[string]string | ||||
|  | ||||
| // BuildVarsFunc adds a custom function to be used to modify build variables | ||||
| // before a route's URL is built. | ||||
| func (r *Route) BuildVarsFunc(f BuildVarsFunc) *Route { | ||||
| 	r.buildVarsFunc = f | ||||
| 	return r | ||||
| } | ||||
|  | ||||
| // Subrouter ------------------------------------------------------------------ | ||||
|  | ||||
| // Subrouter creates a subrouter for the route. | ||||
| // | ||||
| // It will test the inner routes only if the parent route matched. For example: | ||||
| // | ||||
| //     r := mux.NewRouter() | ||||
| //     s := r.Host("www.domain.com").Subrouter() | ||||
| //     s.HandleFunc("/products/", ProductsHandler) | ||||
| //     s.HandleFunc("/products/{key}", ProductHandler) | ||||
| //     s.HandleFunc("/articles/{category}/{id:[0-9]+}"), ArticleHandler) | ||||
| // | ||||
| // Here, the routes registered in the subrouter won't be tested if the host | ||||
| // doesn't match. | ||||
| func (r *Route) Subrouter() *Router { | ||||
| 	router := &Router{parent: r, strictSlash: r.strictSlash} | ||||
| 	r.addMatcher(router) | ||||
| 	return router | ||||
| } | ||||
|  | ||||
| // ---------------------------------------------------------------------------- | ||||
| // URL building | ||||
| // ---------------------------------------------------------------------------- | ||||
|  | ||||
| // URL builds a URL for the route. | ||||
| // | ||||
| // It accepts a sequence of key/value pairs for the route variables. For | ||||
| // example, given this route: | ||||
| // | ||||
| //     r := mux.NewRouter() | ||||
| //     r.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler). | ||||
| //       Name("article") | ||||
| // | ||||
| // ...a URL for it can be built using: | ||||
| // | ||||
| //     url, err := r.Get("article").URL("category", "technology", "id", "42") | ||||
| // | ||||
| // ...which will return an url.URL with the following path: | ||||
| // | ||||
| //     "/articles/technology/42" | ||||
| // | ||||
| // This also works for host variables: | ||||
| // | ||||
| //     r := mux.NewRouter() | ||||
| //     r.Host("{subdomain}.domain.com"). | ||||
| //       HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler). | ||||
| //       Name("article") | ||||
| // | ||||
| //     // url.String() will be "http://news.domain.com/articles/technology/42" | ||||
| //     url, err := r.Get("article").URL("subdomain", "news", | ||||
| //                                      "category", "technology", | ||||
| //                                      "id", "42") | ||||
| // | ||||
| // All variables defined in the route are required, and their values must | ||||
| // conform to the corresponding patterns. | ||||
| func (r *Route) URL(pairs ...string) (*url.URL, error) { | ||||
| 	if r.err != nil { | ||||
| 		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...) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	var scheme, host, path string | ||||
| 	if r.regexp.host != nil { | ||||
| 		// Set a default scheme. | ||||
| 		scheme = "http" | ||||
| 		if host, err = r.regexp.host.url(values); err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 	} | ||||
| 	if r.regexp.path != nil { | ||||
| 		if path, err = r.regexp.path.url(values); err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 	} | ||||
| 	return &url.URL{ | ||||
| 		Scheme: scheme, | ||||
| 		Host:   host, | ||||
| 		Path:   path, | ||||
| 	}, nil | ||||
| } | ||||
|  | ||||
| // URLHost builds the host part of the URL for a route. See Route.URL(). | ||||
| // | ||||
| // The route must have a host defined. | ||||
| func (r *Route) URLHost(pairs ...string) (*url.URL, error) { | ||||
| 	if r.err != nil { | ||||
| 		return nil, r.err | ||||
| 	} | ||||
| 	if r.regexp == nil || r.regexp.host == nil { | ||||
| 		return nil, errors.New("mux: route doesn't have a host") | ||||
| 	} | ||||
| 	values, err := r.prepareVars(pairs...) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	host, err := r.regexp.host.url(values) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return &url.URL{ | ||||
| 		Scheme: "http", | ||||
| 		Host:   host, | ||||
| 	}, nil | ||||
| } | ||||
|  | ||||
| // URLPath builds the path part of the URL for a route. See Route.URL(). | ||||
| // | ||||
| // The route must have a path defined. | ||||
| func (r *Route) URLPath(pairs ...string) (*url.URL, error) { | ||||
| 	if r.err != nil { | ||||
| 		return nil, r.err | ||||
| 	} | ||||
| 	if r.regexp == nil || r.regexp.path == nil { | ||||
| 		return nil, errors.New("mux: route doesn't have a path") | ||||
| 	} | ||||
| 	values, err := r.prepareVars(pairs...) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	path, err := r.regexp.path.url(values) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return &url.URL{ | ||||
| 		Path: path, | ||||
| 	}, nil | ||||
| } | ||||
|  | ||||
| // prepareVars converts the route variable pairs into a map. If the route has a | ||||
| // BuildVarsFunc, it is invoked. | ||||
| func (r *Route) prepareVars(pairs ...string) (map[string]string, error) { | ||||
| 	m, err := mapFromPairs(pairs...) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return r.buildVars(m), nil | ||||
| } | ||||
|  | ||||
| func (r *Route) buildVars(m map[string]string) map[string]string { | ||||
| 	if r.parent != nil { | ||||
| 		m = r.parent.buildVars(m) | ||||
| 	} | ||||
| 	if r.buildVarsFunc != nil { | ||||
| 		m = r.buildVarsFunc(m) | ||||
| 	} | ||||
| 	return m | ||||
| } | ||||
|  | ||||
| // ---------------------------------------------------------------------------- | ||||
| // parentRoute | ||||
| // ---------------------------------------------------------------------------- | ||||
|  | ||||
| // parentRoute allows routes to know about parent host and path definitions. | ||||
| type parentRoute interface { | ||||
| 	getNamedRoutes() map[string]*Route | ||||
| 	getRegexpGroup() *routeRegexpGroup | ||||
| 	buildVars(map[string]string) map[string]string | ||||
| } | ||||
|  | ||||
| // 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 | ||||
| } | ||||
		Reference in New Issue
	
	Block a user