github.com/hellobchain/third_party@v0.0.0-20230331131523-deb0478a2e52/gorilla/mux/mux.go (about)

     1  // Copyright 2012 The Gorilla Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package mux
     6  
     7  import (
     8  	"errors"
     9  	"fmt"
    10  	"github.com/hellobchain/newcryptosm/http"
    11  
    12  	"path"
    13  	"regexp"
    14  )
    15  
    16  var (
    17  	// ErrMethodMismatch is returned when the method in the request does not match
    18  	// the method defined against the route.
    19  	ErrMethodMismatch = errors.New("method is not allowed")
    20  	// ErrNotFound is returned when no route match is found.
    21  	ErrNotFound = errors.New("no matching route was found")
    22  )
    23  
    24  // NewRouter returns a new router instance.
    25  func NewRouter() *Router {
    26  	return &Router{namedRoutes: make(map[string]*Route)}
    27  }
    28  
    29  // Router registers routes to be matched and dispatches a handler.
    30  //
    31  // It implements the http.Handler interface, so it can be registered to serve
    32  // requests:
    33  //
    34  //     var router = mux.NewRouter()
    35  //
    36  //     func main() {
    37  //         http.Handle("/", router)
    38  //     }
    39  //
    40  // Or, for Google App Engine, register it in a init() function:
    41  //
    42  //     func init() {
    43  //         http.Handle("/", router)
    44  //     }
    45  //
    46  // This will send all incoming requests to the router.
    47  type Router struct {
    48  	// Configurable Handler to be used when no route matches.
    49  	NotFoundHandler http.Handler
    50  
    51  	// Configurable Handler to be used when the request method does not match the route.
    52  	MethodNotAllowedHandler http.Handler
    53  
    54  	// Routes to be matched, in order.
    55  	routes []*Route
    56  
    57  	// Routes by name for URL building.
    58  	namedRoutes map[string]*Route
    59  
    60  	// If true, do not clear the request context after handling the request.
    61  	//
    62  	// Deprecated: No effect when go1.7+ is used, since the context is stored
    63  	// on the request itself.
    64  	KeepContext bool
    65  
    66  	// Slice of middlewares to be called after a match is found
    67  	middlewares []middleware
    68  
    69  	// configuration shared with `Route`
    70  	routeConf
    71  }
    72  
    73  // common route configuration shared between `Router` and `Route`
    74  type routeConf struct {
    75  	// If true, "/path/foo%2Fbar/to" will match the path "/path/{var}/to"
    76  	useEncodedPath bool
    77  
    78  	// If true, when the path pattern is "/path/", accessing "/path" will
    79  	// redirect to the former and vice versa.
    80  	strictSlash bool
    81  
    82  	// If true, when the path pattern is "/path//to", accessing "/path//to"
    83  	// will not redirect
    84  	skipClean bool
    85  
    86  	// Manager for the variables from host and path.
    87  	regexp routeRegexpGroup
    88  
    89  	// List of matchers.
    90  	matchers []matcher
    91  
    92  	// The scheme used when building URLs.
    93  	buildScheme string
    94  
    95  	buildVarsFunc BuildVarsFunc
    96  }
    97  
    98  // returns an effective deep copy of `routeConf`
    99  func copyRouteConf(r routeConf) routeConf {
   100  	c := r
   101  
   102  	if r.regexp.path != nil {
   103  		c.regexp.path = copyRouteRegexp(r.regexp.path)
   104  	}
   105  
   106  	if r.regexp.host != nil {
   107  		c.regexp.host = copyRouteRegexp(r.regexp.host)
   108  	}
   109  
   110  	c.regexp.queries = make([]*routeRegexp, 0, len(r.regexp.queries))
   111  	for _, q := range r.regexp.queries {
   112  		c.regexp.queries = append(c.regexp.queries, copyRouteRegexp(q))
   113  	}
   114  
   115  	c.matchers = make([]matcher, 0, len(r.matchers))
   116  	for _, m := range r.matchers {
   117  		c.matchers = append(c.matchers, m)
   118  	}
   119  
   120  	return c
   121  }
   122  
   123  func copyRouteRegexp(r *routeRegexp) *routeRegexp {
   124  	c := *r
   125  	return &c
   126  }
   127  
   128  // Match attempts to match the given request against the router's registered routes.
   129  //
   130  // If the request matches a route of this router or one of its subrouters the Route,
   131  // Handler, and Vars fields of the the match argument are filled and this function
   132  // returns true.
   133  //
   134  // If the request does not match any of this router's or its subrouters' routes
   135  // then this function returns false. If available, a reason for the match failure
   136  // will be filled in the match argument's MatchErr field. If the match failure type
   137  // (eg: not found) has a registered handler, the handler is assigned to the Handler
   138  // field of the match argument.
   139  func (r *Router) Match(req *http.Request, match *RouteMatch) bool {
   140  	for _, route := range r.routes {
   141  		if route.Match(req, match) {
   142  			// Build middleware chain if no error was found
   143  			if match.MatchErr == nil {
   144  				for i := len(r.middlewares) - 1; i >= 0; i-- {
   145  					match.Handler = r.middlewares[i].Middleware(match.Handler)
   146  				}
   147  			}
   148  			return true
   149  		}
   150  	}
   151  
   152  	if match.MatchErr == ErrMethodMismatch {
   153  		if r.MethodNotAllowedHandler != nil {
   154  			match.Handler = r.MethodNotAllowedHandler
   155  			return true
   156  		}
   157  
   158  		return false
   159  	}
   160  
   161  	// Closest match for a router (includes sub-routers)
   162  	if r.NotFoundHandler != nil {
   163  		match.Handler = r.NotFoundHandler
   164  		match.MatchErr = ErrNotFound
   165  		return true
   166  	}
   167  
   168  	match.MatchErr = ErrNotFound
   169  	return false
   170  }
   171  
   172  // ServeHTTP dispatches the handler registered in the matched route.
   173  //
   174  // When there is a match, the route variables can be retrieved calling
   175  // mux.Vars(request).
   176  func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
   177  	if !r.skipClean {
   178  		path := req.URL.Path
   179  		if r.useEncodedPath {
   180  			path = req.URL.EscapedPath()
   181  		}
   182  		// Clean path to canonical form and redirect.
   183  		if p := cleanPath(path); p != path {
   184  
   185  			// Added 3 lines (Philip Schlump) - It was dropping the query string and #whatever from query.
   186  			// This matches with fix in go 1.2 r.c. 4 for same problem.  Go Issue:
   187  			// http://code.google.com/p/go/issues/detail?id=5252
   188  			url := *req.URL
   189  			url.Path = p
   190  			p = url.String()
   191  
   192  			w.Header().Set("Location", p)
   193  			w.WriteHeader(http.StatusMovedPermanently)
   194  			return
   195  		}
   196  	}
   197  	var match RouteMatch
   198  	var handler http.Handler
   199  	if r.Match(req, &match) {
   200  		handler = match.Handler
   201  		req = setVars(req, match.Vars)
   202  		req = setCurrentRoute(req, match.Route)
   203  	}
   204  
   205  	if handler == nil && match.MatchErr == ErrMethodMismatch {
   206  		handler = methodNotAllowedHandler()
   207  	}
   208  
   209  	if handler == nil {
   210  		handler = http.NotFoundHandler()
   211  	}
   212  
   213  	handler.ServeHTTP(w, req)
   214  }
   215  
   216  // Get returns a route registered with the given name.
   217  func (r *Router) Get(name string) *Route {
   218  	return r.namedRoutes[name]
   219  }
   220  
   221  // GetRoute returns a route registered with the given name. This method
   222  // was renamed to Get() and remains here for backwards compatibility.
   223  func (r *Router) GetRoute(name string) *Route {
   224  	return r.namedRoutes[name]
   225  }
   226  
   227  // StrictSlash defines the trailing slash behavior for new routes. The initial
   228  // value is false.
   229  //
   230  // When true, if the route path is "/path/", accessing "/path" will perform a redirect
   231  // to the former and vice versa. In other words, your application will always
   232  // see the path as specified in the route.
   233  //
   234  // When false, if the route path is "/path", accessing "/path/" will not match
   235  // this route and vice versa.
   236  //
   237  // The re-direct is a HTTP 301 (Moved Permanently). Note that when this is set for
   238  // routes with a non-idempotent method (e.g. POST, PUT), the subsequent re-directed
   239  // request will be made as a GET by most clients. Use middleware or client settings
   240  // to modify this behaviour as needed.
   241  //
   242  // Special case: when a route sets a path prefix using the PathPrefix() method,
   243  // strict slash is ignored for that route because the redirect behavior can't
   244  // be determined from a prefix alone. However, any subrouters created from that
   245  // route inherit the original StrictSlash setting.
   246  func (r *Router) StrictSlash(value bool) *Router {
   247  	r.strictSlash = value
   248  	return r
   249  }
   250  
   251  // SkipClean defines the path cleaning behaviour for new routes. The initial
   252  // value is false. Users should be careful about which routes are not cleaned
   253  //
   254  // When true, if the route path is "/path//to", it will remain with the double
   255  // slash. This is helpful if you have a route like: /fetch/http://xkcd.com/534/
   256  //
   257  // When false, the path will be cleaned, so /fetch/http://xkcd.com/534/ will
   258  // become /fetch/http/xkcd.com/534
   259  func (r *Router) SkipClean(value bool) *Router {
   260  	r.skipClean = value
   261  	return r
   262  }
   263  
   264  // UseEncodedPath tells the router to match the encoded original path
   265  // to the routes.
   266  // For eg. "/path/foo%2Fbar/to" will match the path "/path/{var}/to".
   267  //
   268  // If not called, the router will match the unencoded path to the routes.
   269  // For eg. "/path/foo%2Fbar/to" will match the path "/path/foo/bar/to"
   270  func (r *Router) UseEncodedPath() *Router {
   271  	r.useEncodedPath = true
   272  	return r
   273  }
   274  
   275  // ----------------------------------------------------------------------------
   276  // Route factories
   277  // ----------------------------------------------------------------------------
   278  
   279  // NewRoute registers an empty route.
   280  func (r *Router) NewRoute() *Route {
   281  	// initialize a route with a copy of the parent router's configuration
   282  	route := &Route{routeConf: copyRouteConf(r.routeConf), namedRoutes: r.namedRoutes}
   283  	r.routes = append(r.routes, route)
   284  	return route
   285  }
   286  
   287  // Handle registers a new route with a matcher for the URL path.
   288  // See Route.Path() and Route.Handler().
   289  func (r *Router) Handle(path string, handler http.Handler) *Route {
   290  	return r.NewRoute().Path(path).Handler(handler)
   291  }
   292  
   293  // HandleFunc registers a new route with a matcher for the URL path.
   294  // See Route.Path() and Route.HandlerFunc().
   295  func (r *Router) HandleFunc(path string, f func(http.ResponseWriter,
   296  	*http.Request)) *Route {
   297  	return r.NewRoute().Path(path).HandlerFunc(f)
   298  }
   299  
   300  // Headers registers a new route with a matcher for request header values.
   301  // See Route.Headers().
   302  func (r *Router) Headers(pairs ...string) *Route {
   303  	return r.NewRoute().Headers(pairs...)
   304  }
   305  
   306  // Host registers a new route with a matcher for the URL host.
   307  // See Route.Host().
   308  func (r *Router) Host(tpl string) *Route {
   309  	return r.NewRoute().Host(tpl)
   310  }
   311  
   312  // MatcherFunc registers a new route with a custom matcher function.
   313  // See Route.MatcherFunc().
   314  func (r *Router) MatcherFunc(f MatcherFunc) *Route {
   315  	return r.NewRoute().MatcherFunc(f)
   316  }
   317  
   318  // Methods registers a new route with a matcher for HTTP methods.
   319  // See Route.Methods().
   320  func (r *Router) Methods(methods ...string) *Route {
   321  	return r.NewRoute().Methods(methods...)
   322  }
   323  
   324  // Path registers a new route with a matcher for the URL path.
   325  // See Route.Path().
   326  func (r *Router) Path(tpl string) *Route {
   327  	return r.NewRoute().Path(tpl)
   328  }
   329  
   330  // PathPrefix registers a new route with a matcher for the URL path prefix.
   331  // See Route.PathPrefix().
   332  func (r *Router) PathPrefix(tpl string) *Route {
   333  	return r.NewRoute().PathPrefix(tpl)
   334  }
   335  
   336  // Queries registers a new route with a matcher for URL query values.
   337  // See Route.Queries().
   338  func (r *Router) Queries(pairs ...string) *Route {
   339  	return r.NewRoute().Queries(pairs...)
   340  }
   341  
   342  // Schemes registers a new route with a matcher for URL schemes.
   343  // See Route.Schemes().
   344  func (r *Router) Schemes(schemes ...string) *Route {
   345  	return r.NewRoute().Schemes(schemes...)
   346  }
   347  
   348  // BuildVarsFunc registers a new route with a custom function for modifying
   349  // route variables before building a URL.
   350  func (r *Router) BuildVarsFunc(f BuildVarsFunc) *Route {
   351  	return r.NewRoute().BuildVarsFunc(f)
   352  }
   353  
   354  // Walk walks the router and all its sub-routers, calling walkFn for each route
   355  // in the tree. The routes are walked in the order they were added. Sub-routers
   356  // are explored depth-first.
   357  func (r *Router) Walk(walkFn WalkFunc) error {
   358  	return r.walk(walkFn, []*Route{})
   359  }
   360  
   361  // SkipRouter is used as a return value from WalkFuncs to indicate that the
   362  // router that walk is about to descend down to should be skipped.
   363  var SkipRouter = errors.New("skip this router")
   364  
   365  // WalkFunc is the type of the function called for each route visited by Walk.
   366  // At every invocation, it is given the current route, and the current router,
   367  // and a list of ancestor routes that lead to the current route.
   368  type WalkFunc func(route *Route, router *Router, ancestors []*Route) error
   369  
   370  func (r *Router) walk(walkFn WalkFunc, ancestors []*Route) error {
   371  	for _, t := range r.routes {
   372  		err := walkFn(t, r, ancestors)
   373  		if err == SkipRouter {
   374  			continue
   375  		}
   376  		if err != nil {
   377  			return err
   378  		}
   379  		for _, sr := range t.matchers {
   380  			if h, ok := sr.(*Router); ok {
   381  				ancestors = append(ancestors, t)
   382  				err := h.walk(walkFn, ancestors)
   383  				if err != nil {
   384  					return err
   385  				}
   386  				ancestors = ancestors[:len(ancestors)-1]
   387  			}
   388  		}
   389  		if h, ok := t.handler.(*Router); ok {
   390  			ancestors = append(ancestors, t)
   391  			err := h.walk(walkFn, ancestors)
   392  			if err != nil {
   393  				return err
   394  			}
   395  			ancestors = ancestors[:len(ancestors)-1]
   396  		}
   397  	}
   398  	return nil
   399  }
   400  
   401  // ----------------------------------------------------------------------------
   402  // Context
   403  // ----------------------------------------------------------------------------
   404  
   405  // RouteMatch stores information about a matched route.
   406  type RouteMatch struct {
   407  	Route   *Route
   408  	Handler http.Handler
   409  	Vars    map[string]string
   410  
   411  	// MatchErr is set to appropriate matching error
   412  	// It is set to ErrMethodMismatch if there is a mismatch in
   413  	// the request method and route method
   414  	MatchErr error
   415  }
   416  
   417  type contextKey int
   418  
   419  const (
   420  	varsKey contextKey = iota
   421  	routeKey
   422  )
   423  
   424  // Vars returns the route variables for the current request, if any.
   425  func Vars(r *http.Request) map[string]string {
   426  	if rv := contextGet(r, varsKey); rv != nil {
   427  		return rv.(map[string]string)
   428  	}
   429  	return nil
   430  }
   431  
   432  // CurrentRoute returns the matched route for the current request, if any.
   433  // This only works when called inside the handler of the matched route
   434  // because the matched route is stored in the request context which is cleared
   435  // after the handler returns, unless the KeepContext option is set on the
   436  // Router.
   437  func CurrentRoute(r *http.Request) *Route {
   438  	if rv := contextGet(r, routeKey); rv != nil {
   439  		return rv.(*Route)
   440  	}
   441  	return nil
   442  }
   443  
   444  func setVars(r *http.Request, val interface{}) *http.Request {
   445  	return contextSet(r, varsKey, val)
   446  }
   447  
   448  func setCurrentRoute(r *http.Request, val interface{}) *http.Request {
   449  	return contextSet(r, routeKey, val)
   450  }
   451  
   452  // ----------------------------------------------------------------------------
   453  // Helpers
   454  // ----------------------------------------------------------------------------
   455  
   456  // cleanPath returns the canonical path for p, eliminating . and .. elements.
   457  // Borrowed from the net/http package.
   458  func cleanPath(p string) string {
   459  	if p == "" {
   460  		return "/"
   461  	}
   462  	if p[0] != '/' {
   463  		p = "/" + p
   464  	}
   465  	np := path.Clean(p)
   466  	// path.Clean removes trailing slash except for root;
   467  	// put the trailing slash back if necessary.
   468  	if p[len(p)-1] == '/' && np != "/" {
   469  		np += "/"
   470  	}
   471  
   472  	return np
   473  }
   474  
   475  // uniqueVars returns an error if two slices contain duplicated strings.
   476  func uniqueVars(s1, s2 []string) error {
   477  	for _, v1 := range s1 {
   478  		for _, v2 := range s2 {
   479  			if v1 == v2 {
   480  				return fmt.Errorf("mux: duplicated route variable %q", v2)
   481  			}
   482  		}
   483  	}
   484  	return nil
   485  }
   486  
   487  // checkPairs returns the count of strings passed in, and an error if
   488  // the count is not an even number.
   489  func checkPairs(pairs ...string) (int, error) {
   490  	length := len(pairs)
   491  	if length%2 != 0 {
   492  		return length, fmt.Errorf(
   493  			"mux: number of parameters must be multiple of 2, got %v", pairs)
   494  	}
   495  	return length, nil
   496  }
   497  
   498  // mapFromPairsToString converts variadic string parameters to a
   499  // string to string map.
   500  func mapFromPairsToString(pairs ...string) (map[string]string, error) {
   501  	length, err := checkPairs(pairs...)
   502  	if err != nil {
   503  		return nil, err
   504  	}
   505  	m := make(map[string]string, length/2)
   506  	for i := 0; i < length; i += 2 {
   507  		m[pairs[i]] = pairs[i+1]
   508  	}
   509  	return m, nil
   510  }
   511  
   512  // mapFromPairsToRegex converts variadic string parameters to a
   513  // string to regex map.
   514  func mapFromPairsToRegex(pairs ...string) (map[string]*regexp.Regexp, error) {
   515  	length, err := checkPairs(pairs...)
   516  	if err != nil {
   517  		return nil, err
   518  	}
   519  	m := make(map[string]*regexp.Regexp, length/2)
   520  	for i := 0; i < length; i += 2 {
   521  		regex, err := regexp.Compile(pairs[i+1])
   522  		if err != nil {
   523  			return nil, err
   524  		}
   525  		m[pairs[i]] = regex
   526  	}
   527  	return m, nil
   528  }
   529  
   530  // matchInArray returns true if the given string value is in the array.
   531  func matchInArray(arr []string, value string) bool {
   532  	for _, v := range arr {
   533  		if v == value {
   534  			return true
   535  		}
   536  	}
   537  	return false
   538  }
   539  
   540  // matchMapWithString returns true if the given key/value pairs exist in a given map.
   541  func matchMapWithString(toCheck map[string]string, toMatch map[string][]string, canonicalKey bool) bool {
   542  	for k, v := range toCheck {
   543  		// Check if key exists.
   544  		if canonicalKey {
   545  			k = http.CanonicalHeaderKey(k)
   546  		}
   547  		if values := toMatch[k]; values == nil {
   548  			return false
   549  		} else if v != "" {
   550  			// If value was defined as an empty string we only check that the
   551  			// key exists. Otherwise we also check for equality.
   552  			valueExists := false
   553  			for _, value := range values {
   554  				if v == value {
   555  					valueExists = true
   556  					break
   557  				}
   558  			}
   559  			if !valueExists {
   560  				return false
   561  			}
   562  		}
   563  	}
   564  	return true
   565  }
   566  
   567  // matchMapWithRegex returns true if the given key/value pairs exist in a given map compiled against
   568  // the given regex
   569  func matchMapWithRegex(toCheck map[string]*regexp.Regexp, toMatch map[string][]string, canonicalKey bool) bool {
   570  	for k, v := range toCheck {
   571  		// Check if key exists.
   572  		if canonicalKey {
   573  			k = http.CanonicalHeaderKey(k)
   574  		}
   575  		if values := toMatch[k]; values == nil {
   576  			return false
   577  		} else if v != nil {
   578  			// If value was defined as an empty string we only check that the
   579  			// key exists. Otherwise we also check for equality.
   580  			valueExists := false
   581  			for _, value := range values {
   582  				if v.MatchString(value) {
   583  					valueExists = true
   584  					break
   585  				}
   586  			}
   587  			if !valueExists {
   588  				return false
   589  			}
   590  		}
   591  	}
   592  	return true
   593  }
   594  
   595  // methodNotAllowed replies to the request with an HTTP status code 405.
   596  func methodNotAllowed(w http.ResponseWriter, r *http.Request) {
   597  	w.WriteHeader(http.StatusMethodNotAllowed)
   598  }
   599  
   600  // methodNotAllowedHandler returns a simple request handler
   601  // that replies to each request with a status code 405.
   602  func methodNotAllowedHandler() http.Handler { return http.HandlerFunc(methodNotAllowed) }