summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/gorilla/mux
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/gorilla/mux')
-rw-r--r--vendor/github.com/gorilla/mux/.travis.yml11
-rw-r--r--vendor/github.com/gorilla/mux/README.md299
-rw-r--r--vendor/github.com/gorilla/mux/doc.go7
-rw-r--r--vendor/github.com/gorilla/mux/middleware.go52
-rw-r--r--vendor/github.com/gorilla/mux/mux.go9
-rw-r--r--vendor/github.com/gorilla/mux/route.go10
-rw-r--r--vendor/github.com/gorilla/mux/test_helpers.go3
7 files changed, 265 insertions, 126 deletions
diff --git a/vendor/github.com/gorilla/mux/.travis.yml b/vendor/github.com/gorilla/mux/.travis.yml
index 3302233f3..ad0935dbd 100644
--- a/vendor/github.com/gorilla/mux/.travis.yml
+++ b/vendor/github.com/gorilla/mux/.travis.yml
@@ -3,11 +3,12 @@ sudo: false
matrix:
include:
- - go: 1.5
- - go: 1.6
- - go: 1.7
- - go: 1.8
- - go: 1.9
+ - go: 1.5.x
+ - go: 1.6.x
+ - go: 1.7.x
+ - go: 1.8.x
+ - go: 1.9.x
+ - go: 1.10.x
- go: tip
allow_failures:
- go: tip
diff --git a/vendor/github.com/gorilla/mux/README.md b/vendor/github.com/gorilla/mux/README.md
index f9b3103f0..e424397ac 100644
--- a/vendor/github.com/gorilla/mux/README.md
+++ b/vendor/github.com/gorilla/mux/README.md
@@ -1,5 +1,5 @@
-gorilla/mux
-===
+# gorilla/mux
+
[![GoDoc](https://godoc.org/github.com/gorilla/mux?status.svg)](https://godoc.org/github.com/gorilla/mux)
[![Build Status](https://travis-ci.org/gorilla/mux.svg?branch=master)](https://travis-ci.org/gorilla/mux)
[![Sourcegraph](https://sourcegraph.com/github.com/gorilla/mux/-/badge.svg)](https://sourcegraph.com/github.com/gorilla/mux?badge)
@@ -29,6 +29,7 @@ The name mux stands for "HTTP request multiplexer". Like the standard `http.Serv
* [Walking Routes](#walking-routes)
* [Graceful Shutdown](#graceful-shutdown)
* [Middleware](#middleware)
+* [Testing Handlers](#testing-handlers)
* [Full Example](#full-example)
---
@@ -178,70 +179,13 @@ s.HandleFunc("/{key}/", ProductHandler)
// "/products/{key}/details"
s.HandleFunc("/{key}/details", ProductDetailsHandler)
```
-### Listing Routes
-
-Routes on a mux can be listed using the Router.Walk method—useful for generating documentation:
-
-```go
-package main
-
-import (
- "fmt"
- "net/http"
- "strings"
-
- "github.com/gorilla/mux"
-)
-
-func handler(w http.ResponseWriter, r *http.Request) {
- return
-}
-func main() {
- r := mux.NewRouter()
- r.HandleFunc("/", handler)
- r.HandleFunc("/products", handler).Methods("POST")
- r.HandleFunc("/articles", handler).Methods("GET")
- r.HandleFunc("/articles/{id}", handler).Methods("GET", "PUT")
- r.HandleFunc("/authors", handler).Queries("surname", "{surname}")
- r.Walk(func(route *mux.Route, router *mux.Router, ancestors []*mux.Route) error {
- t, err := route.GetPathTemplate()
- if err != nil {
- return err
- }
- qt, err := route.GetQueriesTemplates()
- if err != nil {
- return err
- }
- // p will contain regular expression is compatible with regular expression in Perl, Python, and other languages.
- // for instance the regular expression for path '/articles/{id}' will be '^/articles/(?P<v0>[^/]+)$'
- p, err := route.GetPathRegexp()
- if err != nil {
- return err
- }
- // qr will contain a list of regular expressions with the same semantics as GetPathRegexp,
- // just applied to the Queries pairs instead, e.g., 'Queries("surname", "{surname}") will return
- // {"^surname=(?P<v0>.*)$}. Where each combined query pair will have an entry in the list.
- qr, err := route.GetQueriesRegexp()
- if err != nil {
- return err
- }
- m, err := route.GetMethods()
- if err != nil {
- return err
- }
- fmt.Println(strings.Join(m, ","), strings.Join(qt, ","), strings.Join(qr, ","), t, p)
- return nil
- })
- http.Handle("/", r)
-}
-```
### Static Files
Note that the path provided to `PathPrefix()` represents a "wildcard": calling
`PathPrefix("/static/").Handler(...)` means that the handler will be passed any
-request that matches "/static/*". This makes it easy to serve static files with mux:
+request that matches "/static/\*". This makes it easy to serve static files with mux:
```go
func main() {
@@ -348,41 +292,58 @@ The `Walk` function on `mux.Router` can be used to visit all of the routes that
the following prints all of the registered routes:
```go
-r := mux.NewRouter()
-r.HandleFunc("/", handler)
-r.HandleFunc("/products", handler).Methods("POST")
-r.HandleFunc("/articles", handler).Methods("GET")
-r.HandleFunc("/articles/{id}", handler).Methods("GET", "PUT")
-r.HandleFunc("/authors", handler).Queries("surname", "{surname}")
-r.Walk(func(route *mux.Route, router *mux.Router, ancestors []*mux.Route) error {
- t, err := route.GetPathTemplate()
- if err != nil {
- return err
- }
- qt, err := route.GetQueriesTemplates()
- if err != nil {
- return err
- }
- // p will contain a regular expression that is compatible with regular expressions in Perl, Python, and other languages.
- // For example, the regular expression for path '/articles/{id}' will be '^/articles/(?P<v0>[^/]+)$'.
- p, err := route.GetPathRegexp()
- if err != nil {
- return err
- }
- // qr will contain a list of regular expressions with the same semantics as GetPathRegexp,
- // just applied to the Queries pairs instead, e.g., 'Queries("surname", "{surname}") will return
- // {"^surname=(?P<v0>.*)$}. Where each combined query pair will have an entry in the list.
- qr, err := route.GetQueriesRegexp()
- if err != nil {
- return err
- }
- m, err := route.GetMethods()
- if err != nil {
- return err
- }
- fmt.Println(strings.Join(m, ","), strings.Join(qt, ","), strings.Join(qr, ","), t, p)
- return nil
-})
+package main
+
+import (
+ "fmt"
+ "net/http"
+ "strings"
+
+ "github.com/gorilla/mux"
+)
+
+func handler(w http.ResponseWriter, r *http.Request) {
+ return
+}
+
+func main() {
+ r := mux.NewRouter()
+ r.HandleFunc("/", handler)
+ r.HandleFunc("/products", handler).Methods("POST")
+ r.HandleFunc("/articles", handler).Methods("GET")
+ r.HandleFunc("/articles/{id}", handler).Methods("GET", "PUT")
+ r.HandleFunc("/authors", handler).Queries("surname", "{surname}")
+ err := r.Walk(func(route *mux.Route, router *mux.Router, ancestors []*mux.Route) error {
+ pathTemplate, err := route.GetPathTemplate()
+ if err == nil {
+ fmt.Println("ROUTE:", pathTemplate)
+ }
+ pathRegexp, err := route.GetPathRegexp()
+ if err == nil {
+ fmt.Println("Path regexp:", pathRegexp)
+ }
+ queriesTemplates, err := route.GetQueriesTemplates()
+ if err == nil {
+ fmt.Println("Queries templates:", strings.Join(queriesTemplates, ","))
+ }
+ queriesRegexps, err := route.GetQueriesRegexp()
+ if err == nil {
+ fmt.Println("Queries regexps:", strings.Join(queriesRegexps, ","))
+ }
+ methods, err := route.GetMethods()
+ if err == nil {
+ fmt.Println("Methods:", strings.Join(methods, ","))
+ }
+ fmt.Println()
+ return nil
+ })
+
+ if err != nil {
+ fmt.Println(err)
+ }
+
+ http.Handle("/", r)
+}
```
### Graceful Shutdown
@@ -399,6 +360,7 @@ import (
"net/http"
"os"
"os/signal"
+ "time"
"github.com/gorilla/mux"
)
@@ -410,7 +372,7 @@ func main() {
r := mux.NewRouter()
// Add your routes as needed
-
+
srv := &http.Server{
Addr: "0.0.0.0:8080",
// Good practice to set timeouts to avoid Slowloris attacks.
@@ -426,7 +388,7 @@ func main() {
log.Println(err)
}
}()
-
+
c := make(chan os.Signal, 1)
// We'll accept graceful shutdowns when quit via SIGINT (Ctrl+C)
// SIGKILL, SIGQUIT or SIGTERM (Ctrl+/) will not be caught.
@@ -436,7 +398,8 @@ func main() {
<-c
// Create a deadline to wait for.
- ctx, cancel := context.WithTimeout(ctx, wait)
+ ctx, cancel := context.WithTimeout(context.Background(), wait)
+ defer cancel()
// Doesn't block if no connections, but will otherwise wait
// until the timeout deadline.
srv.Shutdown(ctx)
@@ -464,7 +427,7 @@ Typically, the returned handler is a closure which does something with the http.
A very basic middleware which logs the URI of the request being handled could be written as:
```go
-func simpleMw(next http.Handler) http.Handler {
+func loggingMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Do stuff here
log.Println(r.RequestURI)
@@ -474,12 +437,12 @@ func simpleMw(next http.Handler) http.Handler {
}
```
-Middlewares can be added to a router using `Router.AddMiddlewareFunc()`:
+Middlewares can be added to a router using `Router.Use()`:
```go
r := mux.NewRouter()
r.HandleFunc("/", handler)
-r.AddMiddleware(simpleMw)
+r.Use(loggingMiddleware)
```
A more complex authentication middleware, which maps session token to users, could be written as:
@@ -502,7 +465,7 @@ func (amw *authenticationMiddleware) Populate() {
func (amw *authenticationMiddleware) Middleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
token := r.Header.Get("X-Session-Token")
-
+
if user, found := amw.tokenUsers[token]; found {
// We found the token in our map
log.Printf("Authenticated user %s\n", user)
@@ -510,7 +473,7 @@ func (amw *authenticationMiddleware) Middleware(next http.Handler) http.Handler
next.ServeHTTP(w, r)
} else {
// Write an error and stop the handler chain
- http.Error(w, "Forbidden", 403)
+ http.Error(w, "Forbidden", http.StatusForbidden)
}
})
}
@@ -523,10 +486,136 @@ r.HandleFunc("/", handler)
amw := authenticationMiddleware{}
amw.Populate()
-r.AddMiddlewareFunc(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. Middlewares _should_ write to `ResponseWriter` if they _are_ going to terminate the request, and they _should not_ write to `ResponseWriter` if they _are not_ going to terminate it.
+
+### Testing Handlers
+
+Testing handlers in a Go web application is straightforward, and _mux_ doesn't complicate this any further. Given two files: `endpoints.go` and `endpoints_test.go`, here's how we'd test an application using _mux_.
+
+First, our simple HTTP handler:
+
+```go
+// endpoints.go
+package main
+
+func HealthCheckHandler(w http.ResponseWriter, r *http.Request) {
+ // A very simple health check.
+ w.WriteHeader(http.StatusOK)
+ w.Header().Set("Content-Type", "application/json")
+
+ // In the future we could report back on the status of our DB, or our cache
+ // (e.g. Redis) by performing a simple PING, and include them in the response.
+ io.WriteString(w, `{"alive": true}`)
+}
+
+func main() {
+ r := mux.NewRouter()
+ r.HandleFunc("/health", HealthCheckHandler)
+
+ log.Fatal(http.ListenAndServe("localhost:8080", r))
+}
+```
+
+Our test code:
+
+```go
+// endpoints_test.go
+package main
+
+import (
+ "net/http"
+ "net/http/httptest"
+ "testing"
+)
+
+func TestHealthCheckHandler(t *testing.T) {
+ // Create a request to pass to our handler. We don't have any query parameters for now, so we'll
+ // pass 'nil' as the third parameter.
+ req, err := http.NewRequest("GET", "/health", nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ // We create a ResponseRecorder (which satisfies http.ResponseWriter) to record the response.
+ rr := httptest.NewRecorder()
+ handler := http.HandlerFunc(HealthCheckHandler)
+
+ // Our handlers satisfy http.Handler, so we can call their ServeHTTP method
+ // directly and pass in our Request and ResponseRecorder.
+ handler.ServeHTTP(rr, req)
+
+ // Check the status code is what we expect.
+ if status := rr.Code; status != http.StatusOK {
+ t.Errorf("handler returned wrong status code: got %v want %v",
+ status, http.StatusOK)
+ }
+
+ // Check the response body is what we expect.
+ expected := `{"alive": true}`
+ if rr.Body.String() != expected {
+ t.Errorf("handler returned unexpected body: got %v want %v",
+ rr.Body.String(), expected)
+ }
+}
+```
+
+In the case that our routes have [variables](#examples), we can pass those in the request. We could write
+[table-driven tests](https://dave.cheney.net/2013/06/09/writing-table-driven-tests-in-go) to test multiple
+possible route variables as needed.
+
+```go
+// endpoints.go
+func main() {
+ r := mux.NewRouter()
+ // A route with a route variable:
+ r.HandleFunc("/metrics/{type}", MetricsHandler)
+
+ log.Fatal(http.ListenAndServe("localhost:8080", r))
+}
```
-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. Middlewares *should* write to `ResponseWriter` if they *are* going to terminate the request, and they *should not* write to `ResponseWriter` if they *are not* going to terminate it.
+Our test file, with a table-driven test of `routeVariables`:
+
+```go
+// endpoints_test.go
+func TestMetricsHandler(t *testing.T) {
+ tt := []struct{
+ routeVariable string
+ shouldPass bool
+ }{
+ {"goroutines", true},
+ {"heap", true},
+ {"counters", true},
+ {"queries", true},
+ {"adhadaeqm3k", false},
+ }
+
+ for _, tc := range tt {
+ path := fmt.Sprintf("/metrics/%s", tc.routeVariable)
+ req, err := http.NewRequest("GET", path, nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ 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
+ router := mux.NewRouter()
+ router.HandleFunc("/metrics/{type}", MetricsHandler)
+ router.ServeHTTP(rr, req)
+
+ // In this case, our MetricsHandler returns a non-200 response
+ // for a route variable it doesn't know about.
+ if rr.Code == http.StatusOK && !tc.shouldPass {
+ t.Errorf("handler should have failed on routeVariable %s: got %v want %v",
+ tc.routeVariable, rr.Code, http.StatusOK)
+ }
+ }
+}
+```
## Full Example
diff --git a/vendor/github.com/gorilla/mux/doc.go b/vendor/github.com/gorilla/mux/doc.go
index 013f08898..38957deea 100644
--- a/vendor/github.com/gorilla/mux/doc.go
+++ b/vendor/github.com/gorilla/mux/doc.go
@@ -239,8 +239,7 @@ as well:
"category", "technology",
"id", "42")
-Since **vX.Y.Z**, mux supports the addition of middlewares to a [Router](https://godoc.org/github.com/gorilla/mux#Router), which are executed if a
-match is found (including subrouters). Middlewares are defined using the de facto standard type:
+Mux supports the addition of middlewares to a Router, which are executed in the order they are added if a match is found, including its subrouters. Middlewares are (typically) small pieces of code which take one request, do something with it, and pass it down to another middleware or the final handler. Some common use cases for middleware are request logging, header manipulation, or ResponseWriter hijacking.
type MiddlewareFunc func(http.Handler) http.Handler
@@ -261,7 +260,7 @@ Middlewares can be added to a router using `Router.Use()`:
r := mux.NewRouter()
r.HandleFunc("/", handler)
- r.AddMiddleware(simpleMw)
+ r.Use(simpleMw)
A more complex authentication middleware, which maps session token to users, could be written as:
@@ -288,7 +287,7 @@ A more complex authentication middleware, which maps session token to users, cou
log.Printf("Authenticated user %s\n", user)
next.ServeHTTP(w, r)
} else {
- http.Error(w, "Forbidden", 403)
+ http.Error(w, "Forbidden", http.StatusForbidden)
}
})
}
diff --git a/vendor/github.com/gorilla/mux/middleware.go b/vendor/github.com/gorilla/mux/middleware.go
index 8f898675e..ceb812cee 100644
--- a/vendor/github.com/gorilla/mux/middleware.go
+++ b/vendor/github.com/gorilla/mux/middleware.go
@@ -1,6 +1,9 @@
package mux
-import "net/http"
+import (
+ "net/http"
+ "strings"
+)
// MiddlewareFunc is a function which receives an http.Handler and returns another http.Handler.
// Typically, the returned handler is a closure which does something with the http.ResponseWriter and http.Request passed
@@ -12,17 +15,58 @@ type middleware interface {
Middleware(handler http.Handler) http.Handler
}
-// MiddlewareFunc also implements the middleware interface.
+// Middleware allows MiddlewareFunc to implement the middleware interface.
func (mw MiddlewareFunc) Middleware(handler http.Handler) http.Handler {
return mw(handler)
}
// Use appends a MiddlewareFunc to the chain. Middleware can be used to intercept or otherwise modify requests and/or responses, and are executed in the order that they are applied to the Router.
-func (r *Router) Use(mwf MiddlewareFunc) {
- r.middlewares = append(r.middlewares, mwf)
+func (r *Router) Use(mwf ...MiddlewareFunc) {
+ for _, fn := range mwf {
+ r.middlewares = append(r.middlewares, fn)
+ }
}
// useInterface appends a middleware to the chain. Middleware can be used to intercept or otherwise modify requests and/or responses, and are executed in the order that they are applied to the Router.
func (r *Router) useInterface(mw middleware) {
r.middlewares = append(r.middlewares, mw)
}
+
+// CORSMethodMiddleware sets the Access-Control-Allow-Methods response header
+// on a request, by matching routes based only on paths. It also handles
+// OPTIONS requests, by settings Access-Control-Allow-Methods, and then
+// returning without calling the next http handler.
+func CORSMethodMiddleware(r *Router) MiddlewareFunc {
+ return func(next http.Handler) http.Handler {
+ return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
+ var allMethods []string
+
+ err := r.Walk(func(route *Route, _ *Router, _ []*Route) error {
+ for _, m := range route.matchers {
+ if _, ok := m.(*routeRegexp); ok {
+ if m.Match(req, &RouteMatch{}) {
+ methods, err := route.GetMethods()
+ if err != nil {
+ return err
+ }
+
+ allMethods = append(allMethods, methods...)
+ }
+ break
+ }
+ }
+ return nil
+ })
+
+ if err == nil {
+ w.Header().Set("Access-Control-Allow-Methods", strings.Join(append(allMethods, "OPTIONS"), ","))
+
+ if req.Method == "OPTIONS" {
+ return
+ }
+ }
+
+ next.ServeHTTP(w, req)
+ })
+ }
+}
diff --git a/vendor/github.com/gorilla/mux/mux.go b/vendor/github.com/gorilla/mux/mux.go
index efabd2417..4bbafa51d 100644
--- a/vendor/github.com/gorilla/mux/mux.go
+++ b/vendor/github.com/gorilla/mux/mux.go
@@ -13,8 +13,11 @@ import (
)
var (
+ // ErrMethodMismatch is returned when the method in the request does not match
+ // the method defined against the route.
ErrMethodMismatch = errors.New("method is not allowed")
- ErrNotFound = errors.New("no matching route was found")
+ // ErrNotFound is returned when no route match is found.
+ ErrNotFound = errors.New("no matching route was found")
)
// NewRouter returns a new router instance.
@@ -95,9 +98,9 @@ func (r *Router) Match(req *http.Request, match *RouteMatch) bool {
if r.MethodNotAllowedHandler != nil {
match.Handler = r.MethodNotAllowedHandler
return true
- } else {
- return false
}
+
+ return false
}
// Closest match for a router (includes sub-routers)
diff --git a/vendor/github.com/gorilla/mux/route.go b/vendor/github.com/gorilla/mux/route.go
index 4ce098d4f..a591d7354 100644
--- a/vendor/github.com/gorilla/mux/route.go
+++ b/vendor/github.com/gorilla/mux/route.go
@@ -43,6 +43,8 @@ type Route struct {
buildVarsFunc BuildVarsFunc
}
+// SkipClean reports whether path cleaning is enabled for this route via
+// Router.SkipClean.
func (r *Route) SkipClean() bool {
return r.skipClean
}
@@ -622,7 +624,7 @@ func (r *Route) GetPathRegexp() (string, error) {
// route queries.
// This is useful for building simple REST API documentation and for instrumentation
// against third-party services.
-// An empty list will be returned if the route does not have queries.
+// An error will be returned if the route does not have queries.
func (r *Route) GetQueriesRegexp() ([]string, error) {
if r.err != nil {
return nil, r.err
@@ -641,7 +643,7 @@ func (r *Route) GetQueriesRegexp() ([]string, error) {
// query matching.
// This is useful for building simple REST API documentation and for instrumentation
// against third-party services.
-// An empty list will be returned if the route does not define queries.
+// An error will be returned if the route does not define queries.
func (r *Route) GetQueriesTemplates() ([]string, error) {
if r.err != nil {
return nil, r.err
@@ -659,7 +661,7 @@ func (r *Route) GetQueriesTemplates() ([]string, error) {
// GetMethods returns the methods the route matches against
// This is useful for building simple REST API documentation and for instrumentation
// against third-party services.
-// An empty list will be returned if route does not have methods.
+// An error will be returned if route does not have methods.
func (r *Route) GetMethods() ([]string, error) {
if r.err != nil {
return nil, r.err
@@ -669,7 +671,7 @@ func (r *Route) GetMethods() ([]string, error) {
return []string(methods), nil
}
}
- return nil, nil
+ return nil, errors.New("mux: route doesn't have methods")
}
// GetHostTemplate returns the template used to build the
diff --git a/vendor/github.com/gorilla/mux/test_helpers.go b/vendor/github.com/gorilla/mux/test_helpers.go
index 8b2c4a4c5..32ecffde4 100644
--- a/vendor/github.com/gorilla/mux/test_helpers.go
+++ b/vendor/github.com/gorilla/mux/test_helpers.go
@@ -7,7 +7,8 @@ package mux
import "net/http"
// SetURLVars sets the URL variables for the given request, to be accessed via
-// mux.Vars for testing route behaviour.
+// mux.Vars for testing route behaviour. Arguments are not modified, a shallow
+// copy is returned.
//
// This API should only be used for testing purposes; it provides a way to
// inject variables into the request context. Alternatively, URL variables