Browse Source

vendor: github.com/gorilla/mux v1.8.1

full diff: https://github.com/gorilla/mux/compare/v1.8.0...v1.8.1

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Sebastiaan van Stijn 1 year ago
parent
commit
faa843fcef

+ 1 - 1
vendor.mod

@@ -48,7 +48,7 @@ require (
 	github.com/golang/protobuf v1.5.3
 	github.com/golang/protobuf v1.5.3
 	github.com/google/go-cmp v0.5.9
 	github.com/google/go-cmp v0.5.9
 	github.com/google/uuid v1.3.0
 	github.com/google/uuid v1.3.0
-	github.com/gorilla/mux v1.8.0
+	github.com/gorilla/mux v1.8.1
 	github.com/grpc-ecosystem/go-grpc-middleware v1.3.0
 	github.com/grpc-ecosystem/go-grpc-middleware v1.3.0
 	github.com/hashicorp/go-immutable-radix v1.3.1
 	github.com/hashicorp/go-immutable-radix v1.3.1
 	github.com/hashicorp/go-memdb v1.3.2
 	github.com/hashicorp/go-memdb v1.3.2

+ 2 - 1
vendor.sum

@@ -692,8 +692,9 @@ github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33/go.mod h1:Qkdc/uu
 github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
 github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
 github.com/gorilla/mux v1.7.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
 github.com/gorilla/mux v1.7.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
 github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
 github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
-github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
 github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
 github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
+github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
+github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
 github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
 github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
 github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
 github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
 github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
 github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=

+ 1 - 0
vendor/github.com/gorilla/mux/.gitignore

@@ -0,0 +1 @@
+coverage.coverprofile

+ 0 - 8
vendor/github.com/gorilla/mux/AUTHORS

@@ -1,8 +0,0 @@
-# This is the official list of gorilla/mux authors for copyright purposes.
-#
-# Please keep the list sorted.
-
-Google LLC (https://opensource.google.com/)
-Kamil Kisielk <kamil@kamilkisiel.net>
-Matt Silverlock <matt@eatsleeprepeat.net>
-Rodrigo Moraes (https://github.com/moraes)

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

@@ -1,4 +1,4 @@
-Copyright (c) 2012-2018 The Gorilla Authors. All rights reserved.
+Copyright (c) 2023 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

+ 34 - 0
vendor/github.com/gorilla/mux/Makefile

@@ -0,0 +1,34 @@
+GO_LINT=$(shell which golangci-lint 2> /dev/null || echo '')
+GO_LINT_URI=github.com/golangci/golangci-lint/cmd/golangci-lint@latest
+
+GO_SEC=$(shell which gosec 2> /dev/null || echo '')
+GO_SEC_URI=github.com/securego/gosec/v2/cmd/gosec@latest
+
+GO_VULNCHECK=$(shell which govulncheck 2> /dev/null || echo '')
+GO_VULNCHECK_URI=golang.org/x/vuln/cmd/govulncheck@latest
+
+.PHONY: golangci-lint
+golangci-lint:
+	$(if $(GO_LINT), ,go install $(GO_LINT_URI))
+	@echo "##### Running golangci-lint"
+	golangci-lint run -v
+	
+.PHONY: gosec
+gosec:
+	$(if $(GO_SEC), ,go install $(GO_SEC_URI))
+	@echo "##### Running gosec"
+	gosec ./...
+
+.PHONY: govulncheck
+govulncheck:
+	$(if $(GO_VULNCHECK), ,go install $(GO_VULNCHECK_URI))
+	@echo "##### Running govulncheck"
+	govulncheck ./...
+
+.PHONY: verify
+verify: golangci-lint gosec govulncheck
+
+.PHONY: test
+test:
+	@echo "##### Running tests"
+	go test -race -cover -coverprofile=coverage.coverprofile -covermode=atomic -v ./...

+ 34 - 27
vendor/github.com/gorilla/mux/README.md

@@ -1,12 +1,12 @@
 # gorilla/mux
 # gorilla/mux
 
 
-[![GoDoc](https://godoc.org/github.com/gorilla/mux?status.svg)](https://godoc.org/github.com/gorilla/mux)
-[![CircleCI](https://circleci.com/gh/gorilla/mux.svg?style=svg)](https://circleci.com/gh/gorilla/mux)
-[![Sourcegraph](https://sourcegraph.com/github.com/gorilla/mux/-/badge.svg)](https://sourcegraph.com/github.com/gorilla/mux?badge)
+![testing](https://github.com/gorilla/mux/actions/workflows/test.yml/badge.svg)
+[![codecov](https://codecov.io/github/gorilla/mux/branch/main/graph/badge.svg)](https://codecov.io/github/gorilla/mux)
+[![godoc](https://godoc.org/github.com/gorilla/mux?status.svg)](https://godoc.org/github.com/gorilla/mux)
+[![sourcegraph](https://sourcegraph.com/github.com/gorilla/mux/-/badge.svg)](https://sourcegraph.com/github.com/gorilla/mux?badge)
 
 
-![Gorilla Logo](https://cloud-cdn.questionable.services/gorilla-icon-64.png)
 
 
-https://www.gorillatoolkit.org/pkg/mux
+![Gorilla Logo](https://github.com/gorilla/.github/assets/53367916/d92caabf-98e0-473e-bfbf-ab554ba435e5)
 
 
 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.
@@ -247,32 +247,25 @@ type spaHandler struct {
 // file located at the index path on the SPA handler will be served. This
 // file located at the index path on the SPA handler will be served. This
 // is suitable behavior for serving an SPA (single page application).
 // is suitable behavior for serving an SPA (single page application).
 func (h spaHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
 func (h spaHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
-    // get the absolute path to prevent directory traversal
-	path, err := filepath.Abs(r.URL.Path)
-	if err != nil {
-        // if we failed to get the absolute path respond with a 400 bad request
-        // and stop
-		http.Error(w, err.Error(), http.StatusBadRequest)
-		return
-	}
-
-    // prepend the path with the path to the static directory
-	path = filepath.Join(h.staticPath, path)
+	// Join internally call path.Clean to prevent directory traversal
+	path := filepath.Join(h.staticPath, r.URL.Path)
 
 
-    // check whether a file exists at the given path
-	_, err = os.Stat(path)
-	if os.IsNotExist(err) {
-		// file does not exist, serve index.html
+	// check whether a file exists or is a directory at the given path
+	fi, err := os.Stat(path)
+	if os.IsNotExist(err) || fi.IsDir() {
+		// file does not exist or path is a directory, serve index.html
 		http.ServeFile(w, r, filepath.Join(h.staticPath, h.indexPath))
 		http.ServeFile(w, r, filepath.Join(h.staticPath, h.indexPath))
 		return
 		return
-	} else if err != nil {
-        // if we got an error (that wasn't that the file doesn't exist) stating the
-        // file, return a 500 internal server error and stop
+	}
+
+	if err != nil {
+		// if we got an error (that wasn't that the file doesn't exist) stating the
+		// file, return a 500 internal server error and stop
 		http.Error(w, err.Error(), http.StatusInternalServerError)
 		http.Error(w, err.Error(), http.StatusInternalServerError)
-		return
+        return
 	}
 	}
 
 
-    // otherwise, use http.FileServer to serve the static dir
+	// otherwise, use http.FileServer to serve the static file
 	http.FileServer(http.Dir(h.staticPath)).ServeHTTP(w, r)
 	http.FileServer(http.Dir(h.staticPath)).ServeHTTP(w, r)
 }
 }
 
 
@@ -375,6 +368,19 @@ url, err := r.Get("article").URL("subdomain", "news",
                                  "id", "42")
                                  "id", "42")
 ```
 ```
 
 
+To find all the required variables for a given route when calling `URL()`, the method `GetVarNames()` is available:
+```go
+r := mux.NewRouter()
+r.Host("{domain}").
+    Path("/{group}/{item_id}").
+    Queries("some_data1", "{some_data1}").
+    Queries("some_data2", "{some_data2}").
+    Name("article")
+
+// Will print [domain group item_id some_data1 some_data2] <nil>
+fmt.Println(r.Get("article").GetVarNames())
+
+```
 ### Walking Routes
 ### Walking Routes
 
 
 The `Walk` function on `mux.Router` can be used to visit all of the routes that are registered on a router. For example,
 The `Walk` function on `mux.Router` can be used to visit all of the routes that are registered on a router. For example,
@@ -572,7 +578,7 @@ func (amw *authenticationMiddleware) Middleware(next http.Handler) http.Handler
 r := mux.NewRouter()
 r := mux.NewRouter()
 r.HandleFunc("/", handler)
 r.HandleFunc("/", handler)
 
 
-amw := authenticationMiddleware{}
+amw := authenticationMiddleware{tokenUsers: make(map[string]string)}
 amw.Populate()
 amw.Populate()
 
 
 r.Use(amw.Middleware)
 r.Use(amw.Middleware)
@@ -758,7 +764,8 @@ func TestMetricsHandler(t *testing.T) {
 
 
         rr := httptest.NewRecorder()
         rr := httptest.NewRecorder()
 	
 	
-	// Need to create a router that we can pass the request through so that the vars will be added to the context
+	// To add the vars to the context, 
+	// we need to create a router through which we can pass the request.
 	router := mux.NewRouter()
 	router := mux.NewRouter()
         router.HandleFunc("/metrics/{type}", MetricsHandler)
         router.HandleFunc("/metrics/{type}", MetricsHandler)
         router.ServeHTTP(rr, req)
         router.ServeHTTP(rr, req)

+ 12 - 13
vendor/github.com/gorilla/mux/doc.go

@@ -10,18 +10,18 @@ http.ServeMux, mux.Router matches incoming requests against a list of
 registered routes and calls a handler for the route that matches the URL
 registered routes and calls a handler for the route that matches the URL
 or other conditions. The main features are:
 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, paths and query values 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.
+  - Requests can be matched based on URL host, path, path prefix, schemes,
+    header and query values, HTTP methods or using custom matchers.
+  - URL hosts, paths and query values 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:
 Let's start registering a couple of URL paths and handlers:
 
 
@@ -301,6 +301,5 @@ A more complex authentication middleware, which maps session token to users, cou
 	r.Use(amw.Middleware)
 	r.Use(amw.Middleware)
 
 
 Note: The handler chain will be stopped if your middleware doesn't call `next.ServeHTTP()` with the corresponding parameters. This can be used to abort a request if the middleware writer wants to.
 Note: The handler chain will be stopped if your middleware doesn't call `next.ServeHTTP()` with the corresponding parameters. This can be used to abort a request if the middleware writer wants to.
-
 */
 */
 package mux
 package mux

+ 9 - 7
vendor/github.com/gorilla/mux/mux.go

@@ -31,24 +31,26 @@ func NewRouter() *Router {
 // It implements the http.Handler interface, so it can be registered to serve
 // It implements the http.Handler interface, so it can be registered to serve
 // requests:
 // requests:
 //
 //
-//     var router = mux.NewRouter()
+//	var router = mux.NewRouter()
 //
 //
-//     func main() {
-//         http.Handle("/", router)
-//     }
+//	func main() {
+//	    http.Handle("/", router)
+//	}
 //
 //
 // Or, for Google App Engine, register it in a init() function:
 // Or, for Google App Engine, register it in a init() function:
 //
 //
-//     func init() {
-//         http.Handle("/", router)
-//     }
+//	func init() {
+//	    http.Handle("/", router)
+//	}
 //
 //
 // This will send all incoming requests to the router.
 // This will send all incoming requests to the router.
 type Router struct {
 type Router struct {
 	// Configurable Handler to be used when no route matches.
 	// Configurable Handler to be used when no route matches.
+	// This can be used to render your own 404 Not Found errors.
 	NotFoundHandler http.Handler
 	NotFoundHandler http.Handler
 
 
 	// 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.
+	// This can be used to render your own 405 Method Not Allowed errors.
 	MethodNotAllowedHandler http.Handler
 	MethodNotAllowedHandler http.Handler
 
 
 	// Routes to be matched, in order.
 	// Routes to be matched, in order.

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

@@ -22,10 +22,10 @@ type routeRegexpOptions struct {
 type regexpType int
 type regexpType int
 
 
 const (
 const (
-	regexpTypePath   regexpType = 0
-	regexpTypeHost   regexpType = 1
-	regexpTypePrefix regexpType = 2
-	regexpTypeQuery  regexpType = 3
+	regexpTypePath regexpType = iota
+	regexpTypeHost
+	regexpTypePrefix
+	regexpTypeQuery
 )
 )
 
 
 // newRouteRegexp parses a route template and returns a routeRegexp,
 // newRouteRegexp parses a route template and returns a routeRegexp,
@@ -195,7 +195,7 @@ func (r *routeRegexp) Match(req *http.Request, match *RouteMatch) bool {
 
 
 // url builds a URL part using the given values.
 // url builds a URL part using the given values.
 func (r *routeRegexp) url(values map[string]string) (string, error) {
 func (r *routeRegexp) url(values map[string]string) (string, error) {
-	urlValues := make([]interface{}, len(r.varsN), len(r.varsN))
+	urlValues := make([]interface{}, len(r.varsN))
 	for k, v := range r.varsN {
 	for k, v := range r.varsN {
 		value, ok := values[v]
 		value, ok := values[v]
 		if !ok {
 		if !ok {

+ 69 - 40
vendor/github.com/gorilla/mux/route.go

@@ -64,8 +64,18 @@ func (r *Route) Match(req *http.Request, match *RouteMatch) bool {
 				match.MatchErr = nil
 				match.MatchErr = nil
 			}
 			}
 
 
-			matchErr = nil
+			matchErr = nil // nolint:ineffassign
 			return false
 			return false
+		} else {
+			// Multiple routes may share the same path but use different HTTP methods. For instance:
+			// Route 1: POST "/users/{id}".
+			// Route 2: GET "/users/{id}", parameters: "id": "[0-9]+".
+			//
+			// The router must handle these cases correctly. For a GET request to "/users/abc" with "id" as "-2",
+			// The router should return a "Not Found" error as no route fully matches this request.
+			if match.MatchErr == ErrMethodMismatch {
+				match.MatchErr = nil
+			}
 		}
 		}
 	}
 	}
 
 
@@ -230,9 +240,9 @@ func (m headerMatcher) Match(r *http.Request, match *RouteMatch) bool {
 // Headers adds a matcher for request header values.
 // Headers adds a matcher for request header values.
 // It accepts a sequence of key/value pairs to be matched. For example:
 // 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")
+//	r := mux.NewRouter().NewRoute()
+//	r.Headers("Content-Type", "application/json",
+//	          "X-Requested-With", "XMLHttpRequest")
 //
 //
 // The above route will only match if both request header values match.
 // The above route will only match if both request header values match.
 // If the value is an empty string, it will match any value if the key is set.
 // If the value is an empty string, it will match any value if the key is set.
@@ -255,9 +265,9 @@ func (m headerRegexMatcher) Match(r *http.Request, match *RouteMatch) bool {
 // HeadersRegexp accepts a sequence of key/value pairs, where the value has regex
 // HeadersRegexp accepts a sequence of key/value pairs, where the value has regex
 // support. For example:
 // support. For example:
 //
 //
-//     r := mux.NewRouter()
-//     r.HeadersRegexp("Content-Type", "application/(text|json)",
-//               "X-Requested-With", "XMLHttpRequest")
+//	r := mux.NewRouter().NewRoute()
+//	r.HeadersRegexp("Content-Type", "application/(text|json)",
+//	          "X-Requested-With", "XMLHttpRequest")
 //
 //
 // The above route will only match if both the request header matches both regular expressions.
 // The above route will only match if both the request header matches both regular expressions.
 // If the value is an empty string, it will match any value if the key is set.
 // If the value is an empty string, it will match any value if the key is set.
@@ -283,10 +293,10 @@ func (r *Route) HeadersRegexp(pairs ...string) *Route {
 //
 //
 // For example:
 // For example:
 //
 //
-//     r := mux.NewRouter()
-//     r.Host("www.example.com")
-//     r.Host("{subdomain}.domain.com")
-//     r.Host("{subdomain:[a-z]+}.domain.com")
+//	r := mux.NewRouter().NewRoute()
+//	r.Host("www.example.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
 // Variable names must be unique in a given route. They can be retrieved
 // calling mux.Vars(request).
 // calling mux.Vars(request).
@@ -342,11 +352,11 @@ func (r *Route) Methods(methods ...string) *Route {
 //
 //
 // For example:
 // 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)
+//	r := mux.NewRouter().NewRoute()
+//	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
 // Variable names must be unique in a given route. They can be retrieved
 // calling mux.Vars(request).
 // calling mux.Vars(request).
@@ -377,8 +387,8 @@ func (r *Route) PathPrefix(tpl string) *Route {
 // It accepts a sequence of key/value pairs. Values may define variables.
 // It accepts a sequence of key/value pairs. Values may define variables.
 // For example:
 // For example:
 //
 //
-//     r := mux.NewRouter()
-//     r.Queries("foo", "bar", "id", "{id:[0-9]+}")
+//	r := mux.NewRouter().NewRoute()
+//	r.Queries("foo", "bar", "id", "{id:[0-9]+}")
 //
 //
 // The above route will only match if the URL contains the defined queries
 // The above route will only match if the URL contains the defined queries
 // values, e.g.: ?foo=bar&id=42.
 // values, e.g.: ?foo=bar&id=42.
@@ -473,11 +483,11 @@ func (r *Route) BuildVarsFunc(f BuildVarsFunc) *Route {
 //
 //
 // It will test the inner routes only if the parent route matched. For example:
 // It will test the inner routes only if the parent route matched. For example:
 //
 //
-//     r := mux.NewRouter()
-//     s := r.Host("www.example.com").Subrouter()
-//     s.HandleFunc("/products/", ProductsHandler)
-//     s.HandleFunc("/products/{key}", ProductHandler)
-//     s.HandleFunc("/articles/{category}/{id:[0-9]+}"), ArticleHandler)
+//	r := mux.NewRouter().NewRoute()
+//	s := r.Host("www.example.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
 // Here, the routes registered in the subrouter won't be tested if the host
 // doesn't match.
 // doesn't match.
@@ -497,36 +507,36 @@ func (r *Route) Subrouter() *Router {
 // It accepts a sequence of key/value pairs for the route variables. For
 // It accepts a sequence of key/value pairs for the route variables. For
 // example, given this route:
 // example, given this route:
 //
 //
-//     r := mux.NewRouter()
-//     r.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler).
-//       Name("article")
+//	r := mux.NewRouter()
+//	r.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler).
+//	  Name("article")
 //
 //
 // ...a URL for it can be built using:
 // ...a URL for it can be built using:
 //
 //
-//     url, err := r.Get("article").URL("category", "technology", "id", "42")
+//	url, err := r.Get("article").URL("category", "technology", "id", "42")
 //
 //
 // ...which will return an url.URL with the following path:
 // ...which will return an url.URL with the following path:
 //
 //
-//     "/articles/technology/42"
+//	"/articles/technology/42"
 //
 //
 // This also works for host variables:
 // This also works for host variables:
 //
 //
-//     r := mux.NewRouter()
-//     r.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler).
-//       Host("{subdomain}.domain.com").
-//       Name("article")
+//	r := mux.NewRouter()
+//	r.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler).
+//	  Host("{subdomain}.domain.com").
+//	  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")
+//	// url.String() will be "http://news.domain.com/articles/technology/42"
+//	url, err := r.Get("article").URL("subdomain", "news",
+//	                                 "category", "technology",
+//	                                 "id", "42")
 //
 //
 // The scheme of the resulting url will be the first argument that was passed to Schemes:
 // The scheme of the resulting url will be the first argument that was passed to Schemes:
 //
 //
-//     // url.String() will be "https://example.com"
-//     r := mux.NewRouter()
-//     url, err := r.Host("example.com")
-//                  .Schemes("https", "http").URL()
+//	// url.String() will be "https://example.com"
+//	r := mux.NewRouter().NewRoute()
+//	url, err := r.Host("example.com")
+//	             .Schemes("https", "http").URL()
 //
 //
 // All variables defined in the route are required, and their values must
 // All variables defined in the route are required, and their values must
 // conform to the corresponding patterns.
 // conform to the corresponding patterns.
@@ -718,6 +728,25 @@ func (r *Route) GetHostTemplate() (string, error) {
 	return r.regexp.host.template, nil
 	return r.regexp.host.template, nil
 }
 }
 
 
+// GetVarNames returns the names of all variables added by regexp matchers
+// These can be used to know which route variables should be passed into r.URL()
+func (r *Route) GetVarNames() ([]string, error) {
+	if r.err != nil {
+		return nil, r.err
+	}
+	var varNames []string
+	if r.regexp.host != nil {
+		varNames = append(varNames, r.regexp.host.varsN...)
+	}
+	if r.regexp.path != nil {
+		varNames = append(varNames, r.regexp.path.varsN...)
+	}
+	for _, regx := range r.regexp.queries {
+		varNames = append(varNames, regx.varsN...)
+	}
+	return varNames, nil
+}
+
 // prepareVars converts the route variable pairs into a map. If the route has a
 // prepareVars converts the route variable pairs into a map. If the route has a
 // BuildVarsFunc, it is invoked.
 // BuildVarsFunc, it is invoked.
 func (r *Route) prepareVars(pairs ...string) (map[string]string, error) {
 func (r *Route) prepareVars(pairs ...string) (map[string]string, error) {

+ 2 - 2
vendor/modules.txt

@@ -593,8 +593,8 @@ github.com/googleapis/gax-go/v2
 github.com/googleapis/gax-go/v2/apierror
 github.com/googleapis/gax-go/v2/apierror
 github.com/googleapis/gax-go/v2/apierror/internal/proto
 github.com/googleapis/gax-go/v2/apierror/internal/proto
 github.com/googleapis/gax-go/v2/internal
 github.com/googleapis/gax-go/v2/internal
-# github.com/gorilla/mux v1.8.0
-## explicit; go 1.12
+# github.com/gorilla/mux v1.8.1
+## explicit; go 1.20
 github.com/gorilla/mux
 github.com/gorilla/mux
 # github.com/grpc-ecosystem/go-grpc-middleware v1.3.0
 # github.com/grpc-ecosystem/go-grpc-middleware v1.3.0
 ## explicit; go 1.14
 ## explicit; go 1.14