aboutsummaryrefslogtreecommitdiff
path: root/vendor/github.com/gorilla
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/gorilla')
-rw-r--r--vendor/github.com/gorilla/csrf/Gopkg.lock27
-rw-r--r--vendor/github.com/gorilla/csrf/Gopkg.toml34
-rw-r--r--vendor/github.com/gorilla/csrf/doc.go228
-rw-r--r--vendor/github.com/gorilla/handlers/handlers.go8
-rw-r--r--vendor/github.com/gorilla/mux/README.md71
-rw-r--r--vendor/github.com/gorilla/mux/doc.go12
-rw-r--r--vendor/github.com/gorilla/mux/mux.go48
-rw-r--r--vendor/github.com/gorilla/mux/regexp.go5
-rw-r--r--vendor/github.com/gorilla/mux/route.go91
-rw-r--r--vendor/github.com/gorilla/sessions/README.md6
-rw-r--r--vendor/github.com/gorilla/sessions/doc.go3
11 files changed, 384 insertions, 149 deletions
diff --git a/vendor/github.com/gorilla/csrf/Gopkg.lock b/vendor/github.com/gorilla/csrf/Gopkg.lock
new file mode 100644
index 0000000..5db9540
--- /dev/null
+++ b/vendor/github.com/gorilla/csrf/Gopkg.lock
@@ -0,0 +1,27 @@
+# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
+
+
+[[projects]]
+ name = "github.com/gorilla/context"
+ packages = ["."]
+ revision = "1ea25387ff6f684839d82767c1733ff4d4d15d0a"
+ version = "v1.1"
+
+[[projects]]
+ name = "github.com/gorilla/securecookie"
+ packages = ["."]
+ revision = "667fe4e3466a040b780561fe9b51a83a3753eefc"
+ version = "v1.1"
+
+[[projects]]
+ name = "github.com/pkg/errors"
+ packages = ["."]
+ revision = "645ef00459ed84a119197bfb8d8205042c6df63d"
+ version = "v0.8.0"
+
+[solve-meta]
+ analyzer-name = "dep"
+ analyzer-version = 1
+ inputs-digest = "1695686bc8fa0eb76df9fe8c5ca473686071ddcf795a0595a9465a03e8ac9bef"
+ solver-name = "gps-cdcl"
+ solver-version = 1
diff --git a/vendor/github.com/gorilla/csrf/Gopkg.toml b/vendor/github.com/gorilla/csrf/Gopkg.toml
new file mode 100644
index 0000000..02837b1
--- /dev/null
+++ b/vendor/github.com/gorilla/csrf/Gopkg.toml
@@ -0,0 +1,34 @@
+
+# Gopkg.toml example
+#
+# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md
+# for detailed Gopkg.toml documentation.
+#
+# required = ["github.com/user/thing/cmd/thing"]
+# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
+#
+# [[constraint]]
+# name = "github.com/user/project"
+# version = "1.0.0"
+#
+# [[constraint]]
+# name = "github.com/user/project2"
+# branch = "dev"
+# source = "github.com/myfork/project2"
+#
+# [[override]]
+# name = "github.com/x/y"
+# version = "2.4.0"
+
+
+[[constraint]]
+ name = "github.com/gorilla/context"
+ version = "1.1.0"
+
+[[constraint]]
+ name = "github.com/gorilla/securecookie"
+ version = "1.1.0"
+
+[[constraint]]
+ name = "github.com/pkg/errors"
+ version = "0.8.0"
diff --git a/vendor/github.com/gorilla/csrf/doc.go b/vendor/github.com/gorilla/csrf/doc.go
index 301abe0..3046cdc 100644
--- a/vendor/github.com/gorilla/csrf/doc.go
+++ b/vendor/github.com/gorilla/csrf/doc.go
@@ -4,13 +4,15 @@ prevention middleware for Go web applications & services.
It includes:
- * The `csrf.Protect` middleware/handler provides CSRF protection on routes
- attached to a router or a sub-router.
- * A `csrf.Token` function that provides the token to pass into your response,
- whether that be a HTML form or a JSON response body.
- * ... and a `csrf.TemplateField` helper that you can pass into your `html/template`
- templates to replace a `{{ .csrfField }}` template tag with a hidden input
- field.
+* The `csrf.Protect` middleware/handler provides CSRF protection on routes
+attached to a router or a sub-router.
+
+* A `csrf.Token` function that provides the token to pass into your response,
+whether that be a HTML form or a JSON response body.
+
+* ... and a `csrf.TemplateField` helper that you can pass into your `html/template`
+templates to replace a `{{ .csrfField }}` template tag with a hidden input
+field.
gorilla/csrf is easy to use: add the middleware to individual handlers with
the below:
@@ -31,66 +33,66 @@ validation.
Here's the common use-case: HTML forms you want to provide CSRF protection for,
in order to protect malicious POST requests being made:
- package main
-
- import (
- "fmt"
- "html/template"
- "net/http"
-
- "github.com/gorilla/csrf"
- "github.com/gorilla/mux"
- )
-
- var form = `
- <html>
- <head>
- <title>Sign Up!</title>
- </head>
- <body>
- <form method="POST" action="/signup/post" accept-charset="UTF-8">
- <input type="text" name="name">
- <input type="text" name="email">
- <!--
- The default template tag used by the CSRF middleware .
- This will be replaced with a hidden <input> field containing the
- masked CSRF token.
- -->
- {{ .csrfField }}
- <input type="submit" value="Sign up!">
- </form>
- </body>
- </html>
- `
-
- var t = template.Must(template.New("signup_form.tmpl").Parse(form))
-
- func main() {
- r := mux.NewRouter()
- r.HandleFunc("/signup", ShowSignupForm)
- // All POST requests without a valid token will return HTTP 403 Forbidden.
- r.HandleFunc("/signup/post", SubmitSignupForm)
-
- // Add the middleware to your router by wrapping it.
- http.ListenAndServe(":8000",
- csrf.Protect([]byte("32-byte-long-auth-key"))(r))
- // PS: Don't forget to pass csrf.Secure(false) if you're developing locally
- // over plain HTTP (just don't leave it on in production).
- }
-
- func ShowSignupForm(w http.ResponseWriter, r *http.Request) {
- // signup_form.tmpl just needs a {{ .csrfField }} template tag for
- // csrf.TemplateField to inject the CSRF token into. Easy!
- t.ExecuteTemplate(w, "signup_form.tmpl", map[string]interface{}{
- csrf.TemplateTag: csrf.TemplateField(r),
- })
- }
-
- func SubmitSignupForm(w http.ResponseWriter, r *http.Request) {
- // We can trust that requests making it this far have satisfied
- // our CSRF protection requirements.
- fmt.Fprintf(w, "%v\n", r.PostForm)
- }
+ package main
+
+ import (
+ "fmt"
+ "html/template"
+ "net/http"
+
+ "github.com/gorilla/csrf"
+ "github.com/gorilla/mux"
+ )
+
+ var form = `
+ <html>
+ <head>
+ <title>Sign Up!</title>
+ </head>
+ <body>
+ <form method="POST" action="/signup/post" accept-charset="UTF-8">
+ <input type="text" name="name">
+ <input type="text" name="email">
+ <!--
+ The default template tag used by the CSRF middleware .
+ This will be replaced with a hidden <input> field containing the
+ masked CSRF token.
+ -->
+ {{ .csrfField }}
+ <input type="submit" value="Sign up!">
+ </form>
+ </body>
+ </html>
+ `
+
+ var t = template.Must(template.New("signup_form.tmpl").Parse(form))
+
+ func main() {
+ r := mux.NewRouter()
+ r.HandleFunc("/signup", ShowSignupForm)
+ // All POST requests without a valid token will return HTTP 403 Forbidden.
+ r.HandleFunc("/signup/post", SubmitSignupForm)
+
+ // Add the middleware to your router by wrapping it.
+ http.ListenAndServe(":8000",
+ csrf.Protect([]byte("32-byte-long-auth-key"))(r))
+ // PS: Don't forget to pass csrf.Secure(false) if you're developing locally
+ // over plain HTTP (just don't leave it on in production).
+ }
+
+ func ShowSignupForm(w http.ResponseWriter, r *http.Request) {
+ // signup_form.tmpl just needs a {{ .csrfField }} template tag for
+ // csrf.TemplateField to inject the CSRF token into. Easy!
+ t.ExecuteTemplate(w, "signup_form.tmpl", map[string]interface{}{
+ csrf.TemplateTag: csrf.TemplateField(r),
+ })
+ }
+
+ func SubmitSignupForm(w http.ResponseWriter, r *http.Request) {
+ // We can trust that requests making it this far have satisfied
+ // our CSRF protection requirements.
+ fmt.Fprintf(w, "%v\n", r.PostForm)
+ }
Note that the CSRF middleware will (by necessity) consume the request body if the
token is passed via POST form values. If you need to consume this in your
@@ -101,39 +103,39 @@ You can also send the CSRF token in the response header. This approach is useful
if you're using a front-end JavaScript framework like Ember or Angular, or are
providing a JSON API:
- package main
+ package main
- import (
- "github.com/gorilla/csrf"
- "github.com/gorilla/mux"
- )
+ import (
+ "github.com/gorilla/csrf"
+ "github.com/gorilla/mux"
+ )
- func main() {
- r := mux.NewRouter()
+ func main() {
+ r := mux.NewRouter()
- api := r.PathPrefix("/api").Subrouter()
- api.HandleFunc("/user/:id", GetUser).Methods("GET")
+ api := r.PathPrefix("/api").Subrouter()
+ api.HandleFunc("/user/:id", GetUser).Methods("GET")
- http.ListenAndServe(":8000",
- csrf.Protect([]byte("32-byte-long-auth-key"))(r))
- }
+ http.ListenAndServe(":8000",
+ csrf.Protect([]byte("32-byte-long-auth-key"))(r))
+ }
- func GetUser(w http.ResponseWriter, r *http.Request) {
- // Authenticate the request, get the id from the route params,
- // and fetch the user from the DB, etc.
+ func GetUser(w http.ResponseWriter, r *http.Request) {
+ // Authenticate the request, get the id from the route params,
+ // and fetch the user from the DB, etc.
- // Get the token and pass it in the CSRF header. Our JSON-speaking client
- // or JavaScript framework can now read the header and return the token in
- // in its own "X-CSRF-Token" request header on the subsequent POST.
- w.Header().Set("X-CSRF-Token", csrf.Token(r))
- b, err := json.Marshal(user)
- if err != nil {
- http.Error(w, err.Error(), 500)
- return
- }
+ // Get the token and pass it in the CSRF header. Our JSON-speaking client
+ // or JavaScript framework can now read the header and return the token in
+ // in its own "X-CSRF-Token" request header on the subsequent POST.
+ w.Header().Set("X-CSRF-Token", csrf.Token(r))
+ b, err := json.Marshal(user)
+ if err != nil {
+ http.Error(w, err.Error(), 500)
+ return
+ }
- w.Write(b)
- }
+ w.Write(b)
+ }
If you're writing a client that's supposed to mimic browser behavior, make sure to
send back the CSRF cookie (the default name is _gorilla_csrf, but this can be changed
@@ -141,23 +143,29 @@ with the CookieName Option) along with either the X-CSRF-Token header or the gor
In addition: getting CSRF protection right is important, so here's some background:
- * This library generates unique-per-request (masked) tokens as a mitigation
- against the [BREACH attack](http://breachattack.com/).
- * The 'base' (unmasked) token is stored in the session, which means that
- multiple browser tabs won't cause a user problems as their per-request token
- is compared with the base token.
- * Operates on a "whitelist only" approach where safe (non-mutating) HTTP methods
- (GET, HEAD, OPTIONS, TRACE) are the *only* methods where token validation is not
- enforced.
- * The design is based on the battle-tested
- [Django](https://docs.djangoproject.com/en/1.8/ref/csrf/) and [Ruby on
- Rails](http://api.rubyonrails.org/classes/ActionController/RequestForgeryProtection.html)
- approaches.
- * Cookies are authenticated and based on the [securecookie](https://github.com/gorilla/securecookie)
- library. They're also Secure (issued over HTTPS only) and are HttpOnly
- by default, because sane defaults are important.
- * Go's `crypto/rand` library is used to generate the 32 byte (256 bit) tokens
- and the one-time-pad used for masking them.
+* This library generates unique-per-request (masked) tokens as a mitigation
+against the BREACH attack (http://breachattack.com/).
+
+* The 'base' (unmasked) token is stored in the session, which means that
+multiple browser tabs won't cause a user problems as their per-request token
+is compared with the base token.
+
+* Operates on a "whitelist only" approach where safe (non-mutating) HTTP methods
+(GET, HEAD, OPTIONS, TRACE) are the *only* methods where token validation is not
+enforced.
+
+* The design is based on the battle-tested Django
+(https://docs.djangoproject.com/en/1.8/ref/csrf/) and Ruby on Rails
+(http://api.rubyonrails.org/classes/ActionController/RequestForgeryProtection.html)
+approaches.
+
+* Cookies are authenticated and based on the securecookie
+(https://github.com/gorilla/securecookie) library. They're also Secure (issued
+over HTTPS only) and are HttpOnly by default, because sane defaults are
+important.
+
+* Go's `crypto/rand` library is used to generate the 32 byte (256 bit) tokens
+and the one-time-pad used for masking them.
This library does not seek to be adventurous.
diff --git a/vendor/github.com/gorilla/handlers/handlers.go b/vendor/github.com/gorilla/handlers/handlers.go
index 551f8ff..75db7f8 100644
--- a/vendor/github.com/gorilla/handlers/handlers.go
+++ b/vendor/github.com/gorilla/handlers/handlers.go
@@ -79,9 +79,9 @@ func (h combinedLoggingHandler) ServeHTTP(w http.ResponseWriter, req *http.Reque
}
func makeLogger(w http.ResponseWriter) loggingResponseWriter {
- var logger loggingResponseWriter = &responseLogger{w: w}
+ var logger loggingResponseWriter = &responseLogger{w: w, status: http.StatusOK}
if _, ok := w.(http.Hijacker); ok {
- logger = &hijackLogger{responseLogger{w: w}}
+ logger = &hijackLogger{responseLogger{w: w, status: http.StatusOK}}
}
h, ok1 := logger.(http.Hijacker)
c, ok2 := w.(http.CloseNotifier)
@@ -114,10 +114,6 @@ func (l *responseLogger) Header() http.Header {
}
func (l *responseLogger) Write(b []byte) (int, error) {
- if l.status == 0 {
- // The status will be StatusOK if WriteHeader has not been called yet
- l.status = http.StatusOK
- }
size, err := l.w.Write(b)
l.size += size
return size, err
diff --git a/vendor/github.com/gorilla/mux/README.md b/vendor/github.com/gorilla/mux/README.md
index cdab878..b096bf6 100644
--- a/vendor/github.com/gorilla/mux/README.md
+++ b/vendor/github.com/gorilla/mux/README.md
@@ -15,7 +15,7 @@ The name mux stands for "HTTP request multiplexer". Like the standard `http.Serv
* 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 and paths can have variables with an optional regular expression.
+* 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.
@@ -24,9 +24,9 @@ The name mux stands for "HTTP request multiplexer". Like the standard `http.Serv
* [Install](#install)
* [Examples](#examples)
* [Matching Routes](#matching-routes)
-* [Listing Routes](#listing-routes)
* [Static Files](#static-files)
* [Registered URLs](#registered-urls)
+* [Walking Routes](#walking-routes)
* [Full Example](#full-example)
---
@@ -135,6 +135,14 @@ r.HandleFunc("/products", ProductsHandler).
Schemes("http")
```
+Routes are tested in the order they were added to the router. If two routes match, the first one wins:
+
+```go
+r := mux.NewRouter()
+r.HandleFunc("/specific", specificHandler)
+r.PathPrefix("/").Handler(catchAllHandler)
+```
+
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.example.com`. Create a route for that host and get a "subrouter" from it:
@@ -168,7 +176,6 @@ 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:
@@ -179,6 +186,7 @@ package main
import (
"fmt"
"net/http"
+ "strings"
"github.com/gorilla/mux"
)
@@ -190,15 +198,25 @@ func handler(w http.ResponseWriter, r *http.Request) {
func main() {
r := mux.NewRouter()
r.HandleFunc("/", handler)
- r.HandleFunc("/products", handler)
- r.HandleFunc("/articles", handler)
- r.HandleFunc("/articles/{id}", handler)
+ r.HandleFunc("/products", handler).Methods("POST")
+ r.HandleFunc("/articles", handler).Methods("GET")
+ r.HandleFunc("/articles/{id}", handler).Methods("GET", "PUT")
r.Walk(func(route *mux.Route, router *mux.Router, ancestors []*mux.Route) error {
t, err := route.GetPathTemplate()
if err != nil {
return err
}
- fmt.Println(t)
+ // 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
+ }
+ m, err := route.GetMethods()
+ if err != nil {
+ return err
+ }
+ fmt.Println(strings.Join(m, ","), t, p)
return nil
})
http.Handle("/", r)
@@ -258,19 +276,21 @@ url, err := r.Get("article").URL("category", "technology", "id", "42")
"/articles/technology/42"
```
-This also works for host variables:
+This also works for host and query value variables:
```go
r := mux.NewRouter()
r.Host("{subdomain}.domain.com").
Path("/articles/{category}/{id:[0-9]+}").
+ Queries("filter", "{filter}").
HandlerFunc(ArticleHandler).
Name("article")
-// url.String() will be "http://news.domain.com/articles/technology/42"
+// url.String() will be "http://news.domain.com/articles/technology/42?filter=gorilla"
url, err := r.Get("article").URL("subdomain", "news",
"category", "technology",
- "id", "42")
+ "id", "42",
+ "filter", "gorilla")
```
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.
@@ -308,6 +328,37 @@ url, err := r.Get("article").URL("subdomain", "news",
"id", "42")
```
+### 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 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.Walk(func(route *mux.Route, router *mux.Router, ancestors []*mux.Route) error {
+ t, err := route.GetPathTemplate()
+ 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
+ }
+ m, err := route.GetMethods()
+ if err != nil {
+ return err
+ }
+ fmt.Println(strings.Join(m, ","), t, p)
+ return nil
+})
+```
+
## Full Example
Here's a complete, runnable example of a small `mux` based server:
diff --git a/vendor/github.com/gorilla/mux/doc.go b/vendor/github.com/gorilla/mux/doc.go
index 00daf4a..cce30b2 100644
--- a/vendor/github.com/gorilla/mux/doc.go
+++ b/vendor/github.com/gorilla/mux/doc.go
@@ -12,8 +12,8 @@ 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.
+ * 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
@@ -188,18 +188,20 @@ key/value pairs for the route variables. For the previous route, we would do:
"/articles/technology/42"
-This also works for host variables:
+This also works for host and query value variables:
r := mux.NewRouter()
r.Host("{subdomain}.domain.com").
Path("/articles/{category}/{id:[0-9]+}").
+ Queries("filter", "{filter}").
HandlerFunc(ArticleHandler).
Name("article")
- // url.String() will be "http://news.domain.com/articles/technology/42"
+ // url.String() will be "http://news.domain.com/articles/technology/42?filter=gorilla"
url, err := r.Get("article").URL("subdomain", "news",
"category", "technology",
- "id", "42")
+ "id", "42",
+ "filter", "gorilla")
All variables defined in the route are required, and their values must
conform to the corresponding patterns. These requirements guarantee that a
diff --git a/vendor/github.com/gorilla/mux/mux.go b/vendor/github.com/gorilla/mux/mux.go
index d66ec38..fb69196 100644
--- a/vendor/github.com/gorilla/mux/mux.go
+++ b/vendor/github.com/gorilla/mux/mux.go
@@ -13,6 +13,10 @@ import (
"strings"
)
+var (
+ ErrMethodMismatch = errors.New("method is not allowed")
+)
+
// NewRouter returns a new router instance.
func NewRouter() *Router {
return &Router{namedRoutes: make(map[string]*Route), KeepContext: false}
@@ -39,6 +43,10 @@ func NewRouter() *Router {
type Router struct {
// Configurable Handler to be used when no route matches.
NotFoundHandler http.Handler
+
+ // Configurable Handler to be used when the request method does not match the route.
+ MethodNotAllowedHandler http.Handler
+
// Parent route, if this is a subrouter.
parent parentRoute
// Routes to be matched, in order.
@@ -65,6 +73,11 @@ func (r *Router) Match(req *http.Request, match *RouteMatch) bool {
}
}
+ if match.MatchErr == ErrMethodMismatch && r.MethodNotAllowedHandler != nil {
+ match.Handler = r.MethodNotAllowedHandler
+ return true
+ }
+
// Closest match for a router (includes sub-routers)
if r.NotFoundHandler != nil {
match.Handler = r.NotFoundHandler
@@ -105,9 +118,15 @@ func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
req = setVars(req, match.Vars)
req = setCurrentRoute(req, match.Route)
}
+
+ if handler == nil && match.MatchErr == ErrMethodMismatch {
+ handler = methodNotAllowedHandler()
+ }
+
if handler == nil {
handler = http.NotFoundHandler()
}
+
if !r.KeepContext {
defer contextClear(req)
}
@@ -176,6 +195,13 @@ func (r *Router) UseEncodedPath() *Router {
// parentRoute
// ----------------------------------------------------------------------------
+func (r *Router) getBuildScheme() string {
+ if r.parent != nil {
+ return r.parent.getBuildScheme()
+ }
+ return ""
+}
+
// getNamedRoutes returns the map where named routes are registered.
func (r *Router) getNamedRoutes() map[string]*Route {
if r.namedRoutes == nil {
@@ -299,10 +325,6 @@ type WalkFunc func(route *Route, router *Router, ancestors []*Route) error
func (r *Router) walk(walkFn WalkFunc, ancestors []*Route) error {
for _, t := range r.routes {
- if t.regexp == nil || t.regexp.path == nil || t.regexp.path.template == "" {
- continue
- }
-
err := walkFn(t, r, ancestors)
if err == SkipRouter {
continue
@@ -312,10 +334,12 @@ func (r *Router) walk(walkFn WalkFunc, ancestors []*Route) error {
}
for _, sr := range t.matchers {
if h, ok := sr.(*Router); ok {
+ ancestors = append(ancestors, t)
err := h.walk(walkFn, ancestors)
if err != nil {
return err
}
+ ancestors = ancestors[:len(ancestors)-1]
}
}
if h, ok := t.handler.(*Router); ok {
@@ -339,6 +363,11 @@ type RouteMatch struct {
Route *Route
Handler http.Handler
Vars map[string]string
+
+ // MatchErr is set to appropriate matching error
+ // It is set to ErrMethodMismatch if there is a mismatch in
+ // the request method and route method
+ MatchErr error
}
type contextKey int
@@ -458,7 +487,7 @@ func mapFromPairsToString(pairs ...string) (map[string]string, error) {
return m, nil
}
-// mapFromPairsToRegex converts variadic string paramers to a
+// mapFromPairsToRegex converts variadic string parameters to a
// string to regex map.
func mapFromPairsToRegex(pairs ...string) (map[string]*regexp.Regexp, error) {
length, err := checkPairs(pairs...)
@@ -540,3 +569,12 @@ func matchMapWithRegex(toCheck map[string]*regexp.Regexp, toMatch map[string][]s
}
return true
}
+
+// methodNotAllowed replies to the request with an HTTP status code 405.
+func methodNotAllowed(w http.ResponseWriter, r *http.Request) {
+ w.WriteHeader(http.StatusMethodNotAllowed)
+}
+
+// methodNotAllowedHandler returns a simple request handler
+// that replies to each request with a status code 405.
+func methodNotAllowedHandler() http.Handler { return http.HandlerFunc(methodNotAllowed) }
diff --git a/vendor/github.com/gorilla/mux/regexp.go b/vendor/github.com/gorilla/mux/regexp.go
index 0189ad3..80d1f78 100644
--- a/vendor/github.com/gorilla/mux/regexp.go
+++ b/vendor/github.com/gorilla/mux/regexp.go
@@ -35,7 +35,7 @@ func newRouteRegexp(tpl string, matchHost, matchPrefix, matchQuery, strictSlash,
// Now let's parse it.
defaultPattern := "[^/]+"
if matchQuery {
- defaultPattern = "[^?&]*"
+ defaultPattern = ".*"
} else if matchHost {
defaultPattern = "[^.]+"
matchPrefix = false
@@ -178,6 +178,9 @@ func (r *routeRegexp) url(values map[string]string) (string, error) {
if !ok {
return "", fmt.Errorf("mux: missing route variable %q", v)
}
+ if r.matchQuery {
+ value = url.QueryEscape(value)
+ }
urlValues[k] = value
}
rv := fmt.Sprintf(r.reverse, urlValues...)
diff --git a/vendor/github.com/gorilla/mux/route.go b/vendor/github.com/gorilla/mux/route.go
index 5544c1f..6863adb 100644
--- a/vendor/github.com/gorilla/mux/route.go
+++ b/vendor/github.com/gorilla/mux/route.go
@@ -31,6 +31,8 @@ type Route struct {
skipClean bool
// If true, "/path/foo%2Fbar/to" will match the path "/path/{var}/to"
useEncodedPath bool
+ // The scheme used when building URLs.
+ buildScheme string
// If true, this route never matches: it is only used to build URLs.
buildOnly bool
// The name used to build URLs.
@@ -50,12 +52,27 @@ func (r *Route) Match(req *http.Request, match *RouteMatch) bool {
if r.buildOnly || r.err != nil {
return false
}
+
+ var matchErr error
+
// Match everything.
for _, m := range r.matchers {
if matched := m.Match(req, match); !matched {
+ if _, ok := m.(methodMatcher); ok {
+ matchErr = ErrMethodMismatch
+ continue
+ }
+ matchErr = nil
return false
}
}
+
+ if matchErr != nil {
+ match.MatchErr = matchErr
+ return false
+ }
+
+ match.MatchErr = nil
// Yay, we have a match. Let's collect some info about it.
if match.Route == nil {
match.Route = r
@@ -66,6 +83,7 @@ func (r *Route) Match(req *http.Request, match *RouteMatch) bool {
if match.Vars == nil {
match.Vars = make(map[string]string)
}
+
// Set variables.
if r.regexp != nil {
r.regexp.setMatch(req, match, r)
@@ -394,6 +412,9 @@ func (r *Route) Schemes(schemes ...string) *Route {
for k, v := range schemes {
schemes[k] = strings.ToLower(v)
}
+ if r.buildScheme == "" && len(schemes) > 0 {
+ r.buildScheme = schemes[0]
+ }
return r.addMatcher(schemeMatcher(schemes))
}
@@ -477,22 +498,33 @@ func (r *Route) URL(pairs ...string) (*url.URL, error) {
return nil, err
}
var scheme, host, path string
+ queries := make([]string, 0, len(r.regexp.queries))
if r.regexp.host != nil {
- // Set a default scheme.
- scheme = "http"
if host, err = r.regexp.host.url(values); err != nil {
return nil, err
}
+ scheme = "http"
+ if s := r.getBuildScheme(); s != "" {
+ scheme = s
+ }
}
if r.regexp.path != nil {
if path, err = r.regexp.path.url(values); err != nil {
return nil, err
}
}
+ for _, q := range r.regexp.queries {
+ var query string
+ if query, err = q.url(values); err != nil {
+ return nil, err
+ }
+ queries = append(queries, query)
+ }
return &url.URL{
- Scheme: scheme,
- Host: host,
- Path: path,
+ Scheme: scheme,
+ Host: host,
+ Path: path,
+ RawQuery: strings.Join(queries, "&"),
}, nil
}
@@ -514,10 +546,14 @@ func (r *Route) URLHost(pairs ...string) (*url.URL, error) {
if err != nil {
return nil, err
}
- return &url.URL{
+ u := &url.URL{
Scheme: "http",
Host: host,
- }, nil
+ }
+ if s := r.getBuildScheme(); s != "" {
+ u.Scheme = s
+ }
+ return u, nil
}
// URLPath builds the path part of the URL for a route. See Route.URL().
@@ -558,6 +594,36 @@ func (r *Route) GetPathTemplate() (string, error) {
return r.regexp.path.template, nil
}
+// GetPathRegexp returns the expanded regular expression used to match route path.
+// This is useful for building simple REST API documentation and for instrumentation
+// against third-party services.
+// An error will be returned if the route does not define a path.
+func (r *Route) GetPathRegexp() (string, error) {
+ if r.err != nil {
+ return "", r.err
+ }
+ if r.regexp == nil || r.regexp.path == nil {
+ return "", errors.New("mux: route does not have a path")
+ }
+ return r.regexp.path.regexp.String(), nil
+}
+
+// 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.
+func (r *Route) GetMethods() ([]string, error) {
+ if r.err != nil {
+ return nil, r.err
+ }
+ for _, m := range r.matchers {
+ if methods, ok := m.(methodMatcher); ok {
+ return []string(methods), nil
+ }
+ }
+ return nil, nil
+}
+
// GetHostTemplate returns the template used to build the
// route match.
// This is useful for building simple REST API documentation and for instrumentation
@@ -599,11 +665,22 @@ func (r *Route) buildVars(m map[string]string) map[string]string {
// parentRoute allows routes to know about parent host and path definitions.
type parentRoute interface {
+ getBuildScheme() string
getNamedRoutes() map[string]*Route
getRegexpGroup() *routeRegexpGroup
buildVars(map[string]string) map[string]string
}
+func (r *Route) getBuildScheme() string {
+ if r.buildScheme != "" {
+ return r.buildScheme
+ }
+ if r.parent != nil {
+ return r.parent.getBuildScheme()
+ }
+ return ""
+}
+
// getNamedRoutes returns the map where named routes are registered.
func (r *Route) getNamedRoutes() map[string]*Route {
if r.parent == nil {
diff --git a/vendor/github.com/gorilla/sessions/README.md b/vendor/github.com/gorilla/sessions/README.md
index ebc60d0..10eb7f0 100644
--- a/vendor/github.com/gorilla/sessions/README.md
+++ b/vendor/github.com/gorilla/sessions/README.md
@@ -44,14 +44,14 @@ Let's start with an example that shows the sessions API in a nutshell:
First we initialize a session store calling `NewCookieStore()` and passing a
secret key used to authenticate the session. Inside the handler, we call
-`store.Get()` to retrieve an existing session or a new one. Then we set some
-session values in session.Values, which is a `map[interface{}]interface{}`.
+`store.Get()` to retrieve an existing session or create a new one. Then we set
+some session values in session.Values, which is a `map[interface{}]interface{}`.
And finally we call `session.Save()` to save the session in the response.
Important Note: If you aren't using gorilla/mux, you need to wrap your handlers
with
[`context.ClearHandler`](http://www.gorillatoolkit.org/pkg/context#ClearHandler)
-as or else you will leak memory! An easy way to do this is to wrap the top-level
+or else you will leak memory! An easy way to do this is to wrap the top-level
mux when calling http.ListenAndServe:
```go
diff --git a/vendor/github.com/gorilla/sessions/doc.go b/vendor/github.com/gorilla/sessions/doc.go
index 668e05e..591d932 100644
--- a/vendor/github.com/gorilla/sessions/doc.go
+++ b/vendor/github.com/gorilla/sessions/doc.go
@@ -29,8 +29,7 @@ Let's start with an example that shows the sessions API in a nutshell:
var store = sessions.NewCookieStore([]byte("something-very-secret"))
func MyHandler(w http.ResponseWriter, r *http.Request) {
- // Get a session. We're ignoring the error resulted from decoding an
- // existing session: Get() always returns a session, even if empty.
+ // Get a session. Get() always returns a session, even if empty.
session, err := store.Get(r, "session-name")
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)