From 973a591b92528ad487b7d80cc8241da80a72d868 Mon Sep 17 00:00:00 2001
From: ale <ale@incal.net>
Date: Fri, 17 Aug 2018 08:35:01 +0100
Subject: [PATCH] Update vendored deps

---
 vendor/github.com/gorilla/handlers/LICENSE    |  22 +
 vendor/github.com/gorilla/handlers/README.md  |  55 +++
 .../github.com/gorilla/handlers/canonical.go  |  74 ++++
 .../github.com/gorilla/handlers/compress.go   | 148 +++++++
 vendor/github.com/gorilla/handlers/cors.go    | 327 ++++++++++++++
 vendor/github.com/gorilla/handlers/doc.go     |   9 +
 .../github.com/gorilla/handlers/handlers.go   | 399 ++++++++++++++++++
 .../gorilla/handlers/handlers_go18.go         |  21 +
 .../gorilla/handlers/handlers_pre18.go        |   7 +
 .../gorilla/handlers/proxy_headers.go         | 120 ++++++
 .../github.com/gorilla/handlers/recovery.go   |  91 ++++
 vendor/golang.org/x/crypto/ed25519/ed25519.go |  60 ++-
 .../internal/edwards25519/edwards25519.go     |  22 +
 vendor/golang.org/x/crypto/pbkdf2/pbkdf2.go   |  77 ----
 vendor/golang.org/x/crypto/scrypt/scrypt.go   | 244 -----------
 vendor/golang.org/x/net/context/context.go    |  56 ---
 vendor/golang.org/x/net/context/go17.go       |  72 ----
 vendor/golang.org/x/net/context/go19.go       |  20 -
 vendor/golang.org/x/net/context/pre_go17.go   | 300 -------------
 vendor/golang.org/x/net/context/pre_go19.go   | 109 -----
 vendor/golang.org/x/{net => sync}/LICENSE     |   0
 vendor/golang.org/x/{net => sync}/PATENTS     |   0
 .../x/sync/singleflight/singleflight.go       | 111 +++++
 vendor/vendor.json                            |  52 +--
 24 files changed, 1476 insertions(+), 920 deletions(-)
 create mode 100644 vendor/github.com/gorilla/handlers/LICENSE
 create mode 100644 vendor/github.com/gorilla/handlers/README.md
 create mode 100644 vendor/github.com/gorilla/handlers/canonical.go
 create mode 100644 vendor/github.com/gorilla/handlers/compress.go
 create mode 100644 vendor/github.com/gorilla/handlers/cors.go
 create mode 100644 vendor/github.com/gorilla/handlers/doc.go
 create mode 100644 vendor/github.com/gorilla/handlers/handlers.go
 create mode 100644 vendor/github.com/gorilla/handlers/handlers_go18.go
 create mode 100644 vendor/github.com/gorilla/handlers/handlers_pre18.go
 create mode 100644 vendor/github.com/gorilla/handlers/proxy_headers.go
 create mode 100644 vendor/github.com/gorilla/handlers/recovery.go
 delete mode 100644 vendor/golang.org/x/crypto/pbkdf2/pbkdf2.go
 delete mode 100644 vendor/golang.org/x/crypto/scrypt/scrypt.go
 delete mode 100644 vendor/golang.org/x/net/context/context.go
 delete mode 100644 vendor/golang.org/x/net/context/go17.go
 delete mode 100644 vendor/golang.org/x/net/context/go19.go
 delete mode 100644 vendor/golang.org/x/net/context/pre_go17.go
 delete mode 100644 vendor/golang.org/x/net/context/pre_go19.go
 rename vendor/golang.org/x/{net => sync}/LICENSE (100%)
 rename vendor/golang.org/x/{net => sync}/PATENTS (100%)
 create mode 100644 vendor/golang.org/x/sync/singleflight/singleflight.go

diff --git a/vendor/github.com/gorilla/handlers/LICENSE b/vendor/github.com/gorilla/handlers/LICENSE
new file mode 100644
index 00000000..66ea3c8a
--- /dev/null
+++ b/vendor/github.com/gorilla/handlers/LICENSE
@@ -0,0 +1,22 @@
+Copyright (c) 2013 The Gorilla Handlers Authors. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+  Redistributions of source code must retain the above copyright notice, this
+  list of conditions and the following disclaimer.
+
+  Redistributions in binary form must reproduce the above copyright notice,
+  this list of conditions and the following disclaimer in the documentation
+  and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/vendor/github.com/gorilla/handlers/README.md b/vendor/github.com/gorilla/handlers/README.md
new file mode 100644
index 00000000..4a6895dc
--- /dev/null
+++ b/vendor/github.com/gorilla/handlers/README.md
@@ -0,0 +1,55 @@
+gorilla/handlers
+================
+[![GoDoc](https://godoc.org/github.com/gorilla/handlers?status.svg)](https://godoc.org/github.com/gorilla/handlers) [![Build Status](https://travis-ci.org/gorilla/handlers.svg?branch=master)](https://travis-ci.org/gorilla/handlers)
+[![Sourcegraph](https://sourcegraph.com/github.com/gorilla/handlers/-/badge.svg)](https://sourcegraph.com/github.com/gorilla/handlers?badge)
+
+
+Package handlers is a collection of handlers (aka "HTTP middleware") for use
+with Go's `net/http` package (or any framework supporting `http.Handler`), including:
+
+* [**LoggingHandler**](https://godoc.org/github.com/gorilla/handlers#LoggingHandler) for logging HTTP requests in the Apache [Common Log
+  Format](http://httpd.apache.org/docs/2.2/logs.html#common).
+* [**CombinedLoggingHandler**](https://godoc.org/github.com/gorilla/handlers#CombinedLoggingHandler) for logging HTTP requests in the Apache [Combined Log
+  Format](http://httpd.apache.org/docs/2.2/logs.html#combined) commonly used by
+  both Apache and nginx.
+* [**CompressHandler**](https://godoc.org/github.com/gorilla/handlers#CompressHandler) for gzipping responses.
+* [**ContentTypeHandler**](https://godoc.org/github.com/gorilla/handlers#ContentTypeHandler) for validating requests against a list of accepted
+  content types.
+* [**MethodHandler**](https://godoc.org/github.com/gorilla/handlers#MethodHandler) for matching HTTP methods against handlers in a
+  `map[string]http.Handler`
+* [**ProxyHeaders**](https://godoc.org/github.com/gorilla/handlers#ProxyHeaders) for populating `r.RemoteAddr` and `r.URL.Scheme` based on the
+  `X-Forwarded-For`, `X-Real-IP`, `X-Forwarded-Proto` and RFC7239 `Forwarded`
+  headers when running a Go server behind a HTTP reverse proxy.
+* [**CanonicalHost**](https://godoc.org/github.com/gorilla/handlers#CanonicalHost) for re-directing to the preferred host when handling multiple 
+  domains (i.e. multiple CNAME aliases).
+* [**RecoveryHandler**](https://godoc.org/github.com/gorilla/handlers#RecoveryHandler) for recovering from unexpected panics.
+
+Other handlers are documented [on the Gorilla
+website](http://www.gorillatoolkit.org/pkg/handlers).
+
+## Example
+
+A simple example using `handlers.LoggingHandler` and `handlers.CompressHandler`:
+
+```go
+import (
+    "net/http"
+    "github.com/gorilla/handlers"
+)
+
+func main() {
+    r := http.NewServeMux()
+
+    // Only log requests to our admin dashboard to stdout
+    r.Handle("/admin", handlers.LoggingHandler(os.Stdout, http.HandlerFunc(ShowAdminDashboard)))
+    r.HandleFunc("/", ShowIndex)
+
+    // Wrap our server with our gzip handler to gzip compress all responses.
+    http.ListenAndServe(":8000", handlers.CompressHandler(r))
+}
+```
+
+## License
+
+BSD licensed. See the included LICENSE file for details.
+
diff --git a/vendor/github.com/gorilla/handlers/canonical.go b/vendor/github.com/gorilla/handlers/canonical.go
new file mode 100644
index 00000000..8437fefc
--- /dev/null
+++ b/vendor/github.com/gorilla/handlers/canonical.go
@@ -0,0 +1,74 @@
+package handlers
+
+import (
+	"net/http"
+	"net/url"
+	"strings"
+)
+
+type canonical struct {
+	h      http.Handler
+	domain string
+	code   int
+}
+
+// CanonicalHost is HTTP middleware that re-directs requests to the canonical
+// domain. It accepts a domain and a status code (e.g. 301 or 302) and
+// re-directs clients to this domain. The existing request path is maintained.
+//
+// Note: If the provided domain is considered invalid by url.Parse or otherwise
+// returns an empty scheme or host, clients are not re-directed.
+//
+// Example:
+//
+//  r := mux.NewRouter()
+//  canonical := handlers.CanonicalHost("http://www.gorillatoolkit.org", 302)
+//  r.HandleFunc("/route", YourHandler)
+//
+//  log.Fatal(http.ListenAndServe(":7000", canonical(r)))
+//
+func CanonicalHost(domain string, code int) func(h http.Handler) http.Handler {
+	fn := func(h http.Handler) http.Handler {
+		return canonical{h, domain, code}
+	}
+
+	return fn
+}
+
+func (c canonical) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+	dest, err := url.Parse(c.domain)
+	if err != nil {
+		// Call the next handler if the provided domain fails to parse.
+		c.h.ServeHTTP(w, r)
+		return
+	}
+
+	if dest.Scheme == "" || dest.Host == "" {
+		// Call the next handler if the scheme or host are empty.
+		// Note that url.Parse won't fail on in this case.
+		c.h.ServeHTTP(w, r)
+		return
+	}
+
+	if !strings.EqualFold(cleanHost(r.Host), dest.Host) {
+		// Re-build the destination URL
+		dest := dest.Scheme + "://" + dest.Host + r.URL.Path
+		if r.URL.RawQuery != "" {
+			dest += "?" + r.URL.RawQuery
+		}
+		http.Redirect(w, r, dest, c.code)
+		return
+	}
+
+	c.h.ServeHTTP(w, r)
+}
+
+// cleanHost cleans invalid Host headers by stripping anything after '/' or ' '.
+// This is backported from Go 1.5 (in response to issue #11206) and attempts to
+// mitigate malformed Host headers that do not match the format in RFC7230.
+func cleanHost(in string) string {
+	if i := strings.IndexAny(in, " /"); i != -1 {
+		return in[:i]
+	}
+	return in
+}
diff --git a/vendor/github.com/gorilla/handlers/compress.go b/vendor/github.com/gorilla/handlers/compress.go
new file mode 100644
index 00000000..e8345d79
--- /dev/null
+++ b/vendor/github.com/gorilla/handlers/compress.go
@@ -0,0 +1,148 @@
+// Copyright 2013 The Gorilla Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package handlers
+
+import (
+	"compress/flate"
+	"compress/gzip"
+	"io"
+	"net/http"
+	"strings"
+)
+
+type compressResponseWriter struct {
+	io.Writer
+	http.ResponseWriter
+	http.Hijacker
+	http.Flusher
+	http.CloseNotifier
+}
+
+func (w *compressResponseWriter) WriteHeader(c int) {
+	w.ResponseWriter.Header().Del("Content-Length")
+	w.ResponseWriter.WriteHeader(c)
+}
+
+func (w *compressResponseWriter) Header() http.Header {
+	return w.ResponseWriter.Header()
+}
+
+func (w *compressResponseWriter) Write(b []byte) (int, error) {
+	h := w.ResponseWriter.Header()
+	if h.Get("Content-Type") == "" {
+		h.Set("Content-Type", http.DetectContentType(b))
+	}
+	h.Del("Content-Length")
+
+	return w.Writer.Write(b)
+}
+
+type flusher interface {
+	Flush() error
+}
+
+func (w *compressResponseWriter) Flush() {
+	// Flush compressed data if compressor supports it.
+	if f, ok := w.Writer.(flusher); ok {
+		f.Flush()
+	}
+	// Flush HTTP response.
+	if w.Flusher != nil {
+		w.Flusher.Flush()
+	}
+}
+
+// CompressHandler gzip compresses HTTP responses for clients that support it
+// via the 'Accept-Encoding' header.
+//
+// Compressing TLS traffic may leak the page contents to an attacker if the
+// page contains user input: http://security.stackexchange.com/a/102015/12208
+func CompressHandler(h http.Handler) http.Handler {
+	return CompressHandlerLevel(h, gzip.DefaultCompression)
+}
+
+// CompressHandlerLevel gzip compresses HTTP responses with specified compression level
+// for clients that support it via the 'Accept-Encoding' header.
+//
+// The compression level should be gzip.DefaultCompression, gzip.NoCompression,
+// or any integer value between gzip.BestSpeed and gzip.BestCompression inclusive.
+// gzip.DefaultCompression is used in case of invalid compression level.
+func CompressHandlerLevel(h http.Handler, level int) http.Handler {
+	if level < gzip.DefaultCompression || level > gzip.BestCompression {
+		level = gzip.DefaultCompression
+	}
+
+	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+	L:
+		for _, enc := range strings.Split(r.Header.Get("Accept-Encoding"), ",") {
+			switch strings.TrimSpace(enc) {
+			case "gzip":
+				w.Header().Set("Content-Encoding", "gzip")
+				w.Header().Add("Vary", "Accept-Encoding")
+
+				gw, _ := gzip.NewWriterLevel(w, level)
+				defer gw.Close()
+
+				h, hok := w.(http.Hijacker)
+				if !hok { /* w is not Hijacker... oh well... */
+					h = nil
+				}
+
+				f, fok := w.(http.Flusher)
+				if !fok {
+					f = nil
+				}
+
+				cn, cnok := w.(http.CloseNotifier)
+				if !cnok {
+					cn = nil
+				}
+
+				w = &compressResponseWriter{
+					Writer:         gw,
+					ResponseWriter: w,
+					Hijacker:       h,
+					Flusher:        f,
+					CloseNotifier:  cn,
+				}
+
+				break L
+			case "deflate":
+				w.Header().Set("Content-Encoding", "deflate")
+				w.Header().Add("Vary", "Accept-Encoding")
+
+				fw, _ := flate.NewWriter(w, level)
+				defer fw.Close()
+
+				h, hok := w.(http.Hijacker)
+				if !hok { /* w is not Hijacker... oh well... */
+					h = nil
+				}
+
+				f, fok := w.(http.Flusher)
+				if !fok {
+					f = nil
+				}
+
+				cn, cnok := w.(http.CloseNotifier)
+				if !cnok {
+					cn = nil
+				}
+
+				w = &compressResponseWriter{
+					Writer:         fw,
+					ResponseWriter: w,
+					Hijacker:       h,
+					Flusher:        f,
+					CloseNotifier:  cn,
+				}
+
+				break L
+			}
+		}
+
+		h.ServeHTTP(w, r)
+	})
+}
diff --git a/vendor/github.com/gorilla/handlers/cors.go b/vendor/github.com/gorilla/handlers/cors.go
new file mode 100644
index 00000000..1cf7581c
--- /dev/null
+++ b/vendor/github.com/gorilla/handlers/cors.go
@@ -0,0 +1,327 @@
+package handlers
+
+import (
+	"net/http"
+	"strconv"
+	"strings"
+)
+
+// CORSOption represents a functional option for configuring the CORS middleware.
+type CORSOption func(*cors) error
+
+type cors struct {
+	h                      http.Handler
+	allowedHeaders         []string
+	allowedMethods         []string
+	allowedOrigins         []string
+	allowedOriginValidator OriginValidator
+	exposedHeaders         []string
+	maxAge                 int
+	ignoreOptions          bool
+	allowCredentials       bool
+}
+
+// OriginValidator takes an origin string and returns whether or not that origin is allowed.
+type OriginValidator func(string) bool
+
+var (
+	defaultCorsMethods = []string{"GET", "HEAD", "POST"}
+	defaultCorsHeaders = []string{"Accept", "Accept-Language", "Content-Language", "Origin"}
+	// (WebKit/Safari v9 sends the Origin header by default in AJAX requests)
+)
+
+const (
+	corsOptionMethod           string = "OPTIONS"
+	corsAllowOriginHeader      string = "Access-Control-Allow-Origin"
+	corsExposeHeadersHeader    string = "Access-Control-Expose-Headers"
+	corsMaxAgeHeader           string = "Access-Control-Max-Age"
+	corsAllowMethodsHeader     string = "Access-Control-Allow-Methods"
+	corsAllowHeadersHeader     string = "Access-Control-Allow-Headers"
+	corsAllowCredentialsHeader string = "Access-Control-Allow-Credentials"
+	corsRequestMethodHeader    string = "Access-Control-Request-Method"
+	corsRequestHeadersHeader   string = "Access-Control-Request-Headers"
+	corsOriginHeader           string = "Origin"
+	corsVaryHeader             string = "Vary"
+	corsOriginMatchAll         string = "*"
+)
+
+func (ch *cors) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+	origin := r.Header.Get(corsOriginHeader)
+	if !ch.isOriginAllowed(origin) {
+		ch.h.ServeHTTP(w, r)
+		return
+	}
+
+	if r.Method == corsOptionMethod {
+		if ch.ignoreOptions {
+			ch.h.ServeHTTP(w, r)
+			return
+		}
+
+		if _, ok := r.Header[corsRequestMethodHeader]; !ok {
+			w.WriteHeader(http.StatusBadRequest)
+			return
+		}
+
+		method := r.Header.Get(corsRequestMethodHeader)
+		if !ch.isMatch(method, ch.allowedMethods) {
+			w.WriteHeader(http.StatusMethodNotAllowed)
+			return
+		}
+
+		requestHeaders := strings.Split(r.Header.Get(corsRequestHeadersHeader), ",")
+		allowedHeaders := []string{}
+		for _, v := range requestHeaders {
+			canonicalHeader := http.CanonicalHeaderKey(strings.TrimSpace(v))
+			if canonicalHeader == "" || ch.isMatch(canonicalHeader, defaultCorsHeaders) {
+				continue
+			}
+
+			if !ch.isMatch(canonicalHeader, ch.allowedHeaders) {
+				w.WriteHeader(http.StatusForbidden)
+				return
+			}
+
+			allowedHeaders = append(allowedHeaders, canonicalHeader)
+		}
+
+		if len(allowedHeaders) > 0 {
+			w.Header().Set(corsAllowHeadersHeader, strings.Join(allowedHeaders, ","))
+		}
+
+		if ch.maxAge > 0 {
+			w.Header().Set(corsMaxAgeHeader, strconv.Itoa(ch.maxAge))
+		}
+
+		if !ch.isMatch(method, defaultCorsMethods) {
+			w.Header().Set(corsAllowMethodsHeader, method)
+		}
+	} else {
+		if len(ch.exposedHeaders) > 0 {
+			w.Header().Set(corsExposeHeadersHeader, strings.Join(ch.exposedHeaders, ","))
+		}
+	}
+
+	if ch.allowCredentials {
+		w.Header().Set(corsAllowCredentialsHeader, "true")
+	}
+
+	if len(ch.allowedOrigins) > 1 {
+		w.Header().Set(corsVaryHeader, corsOriginHeader)
+	}
+
+	returnOrigin := origin
+	for _, o := range ch.allowedOrigins {
+		// A configuration of * is different than explicitly setting an allowed
+		// origin. Returning arbitrary origin headers an an access control allow
+		// origin header is unsafe and is not required by any use case.
+		if o == corsOriginMatchAll {
+			returnOrigin = "*"
+			break
+		}
+	}
+	w.Header().Set(corsAllowOriginHeader, returnOrigin)
+
+	if r.Method == corsOptionMethod {
+		return
+	}
+	ch.h.ServeHTTP(w, r)
+}
+
+// CORS provides Cross-Origin Resource Sharing middleware.
+// Example:
+//
+//  import (
+//      "net/http"
+//
+//      "github.com/gorilla/handlers"
+//      "github.com/gorilla/mux"
+//  )
+//
+//  func main() {
+//      r := mux.NewRouter()
+//      r.HandleFunc("/users", UserEndpoint)
+//      r.HandleFunc("/projects", ProjectEndpoint)
+//
+//      // Apply the CORS middleware to our top-level router, with the defaults.
+//      http.ListenAndServe(":8000", handlers.CORS()(r))
+//  }
+//
+func CORS(opts ...CORSOption) func(http.Handler) http.Handler {
+	return func(h http.Handler) http.Handler {
+		ch := parseCORSOptions(opts...)
+		ch.h = h
+		return ch
+	}
+}
+
+func parseCORSOptions(opts ...CORSOption) *cors {
+	ch := &cors{
+		allowedMethods: defaultCorsMethods,
+		allowedHeaders: defaultCorsHeaders,
+		allowedOrigins: []string{corsOriginMatchAll},
+	}
+
+	for _, option := range opts {
+		option(ch)
+	}
+
+	return ch
+}
+
+//
+// Functional options for configuring CORS.
+//
+
+// AllowedHeaders adds the provided headers to the list of allowed headers in a
+// CORS request.
+// This is an append operation so the headers Accept, Accept-Language,
+// and Content-Language are always allowed.
+// Content-Type must be explicitly declared if accepting Content-Types other than
+// application/x-www-form-urlencoded, multipart/form-data, or text/plain.
+func AllowedHeaders(headers []string) CORSOption {
+	return func(ch *cors) error {
+		for _, v := range headers {
+			normalizedHeader := http.CanonicalHeaderKey(strings.TrimSpace(v))
+			if normalizedHeader == "" {
+				continue
+			}
+
+			if !ch.isMatch(normalizedHeader, ch.allowedHeaders) {
+				ch.allowedHeaders = append(ch.allowedHeaders, normalizedHeader)
+			}
+		}
+
+		return nil
+	}
+}
+
+// AllowedMethods can be used to explicitly allow methods in the
+// Access-Control-Allow-Methods header.
+// This is a replacement operation so you must also
+// pass GET, HEAD, and POST if you wish to support those methods.
+func AllowedMethods(methods []string) CORSOption {
+	return func(ch *cors) error {
+		ch.allowedMethods = []string{}
+		for _, v := range methods {
+			normalizedMethod := strings.ToUpper(strings.TrimSpace(v))
+			if normalizedMethod == "" {
+				continue
+			}
+
+			if !ch.isMatch(normalizedMethod, ch.allowedMethods) {
+				ch.allowedMethods = append(ch.allowedMethods, normalizedMethod)
+			}
+		}
+
+		return nil
+	}
+}
+
+// AllowedOrigins sets the allowed origins for CORS requests, as used in the
+// 'Allow-Access-Control-Origin' HTTP header.
+// Note: Passing in a []string{"*"} will allow any domain.
+func AllowedOrigins(origins []string) CORSOption {
+	return func(ch *cors) error {
+		for _, v := range origins {
+			if v == corsOriginMatchAll {
+				ch.allowedOrigins = []string{corsOriginMatchAll}
+				return nil
+			}
+		}
+
+		ch.allowedOrigins = origins
+		return nil
+	}
+}
+
+// AllowedOriginValidator sets a function for evaluating allowed origins in CORS requests, represented by the
+// 'Allow-Access-Control-Origin' HTTP header.
+func AllowedOriginValidator(fn OriginValidator) CORSOption {
+	return func(ch *cors) error {
+		ch.allowedOriginValidator = fn
+		return nil
+	}
+}
+
+// ExposeHeaders can be used to specify headers that are available
+// and will not be stripped out by the user-agent.
+func ExposedHeaders(headers []string) CORSOption {
+	return func(ch *cors) error {
+		ch.exposedHeaders = []string{}
+		for _, v := range headers {
+			normalizedHeader := http.CanonicalHeaderKey(strings.TrimSpace(v))
+			if normalizedHeader == "" {
+				continue
+			}
+
+			if !ch.isMatch(normalizedHeader, ch.exposedHeaders) {
+				ch.exposedHeaders = append(ch.exposedHeaders, normalizedHeader)
+			}
+		}
+
+		return nil
+	}
+}
+
+// MaxAge determines the maximum age (in seconds) between preflight requests. A
+// maximum of 10 minutes is allowed. An age above this value will default to 10
+// minutes.
+func MaxAge(age int) CORSOption {
+	return func(ch *cors) error {
+		// Maximum of 10 minutes.
+		if age > 600 {
+			age = 600
+		}
+
+		ch.maxAge = age
+		return nil
+	}
+}
+
+// IgnoreOptions causes the CORS middleware to ignore OPTIONS requests, instead
+// passing them through to the next handler. This is useful when your application
+// or framework has a pre-existing mechanism for responding to OPTIONS requests.
+func IgnoreOptions() CORSOption {
+	return func(ch *cors) error {
+		ch.ignoreOptions = true
+		return nil
+	}
+}
+
+// AllowCredentials can be used to specify that the user agent may pass
+// authentication details along with the request.
+func AllowCredentials() CORSOption {
+	return func(ch *cors) error {
+		ch.allowCredentials = true
+		return nil
+	}
+}
+
+func (ch *cors) isOriginAllowed(origin string) bool {
+	if origin == "" {
+		return false
+	}
+
+	if ch.allowedOriginValidator != nil {
+		return ch.allowedOriginValidator(origin)
+	}
+
+	for _, allowedOrigin := range ch.allowedOrigins {
+		if allowedOrigin == origin || allowedOrigin == corsOriginMatchAll {
+			return true
+		}
+	}
+
+	return false
+}
+
+func (ch *cors) isMatch(needle string, haystack []string) bool {
+	for _, v := range haystack {
+		if v == needle {
+			return true
+		}
+	}
+
+	return false
+}
diff --git a/vendor/github.com/gorilla/handlers/doc.go b/vendor/github.com/gorilla/handlers/doc.go
new file mode 100644
index 00000000..944e5a8a
--- /dev/null
+++ b/vendor/github.com/gorilla/handlers/doc.go
@@ -0,0 +1,9 @@
+/*
+Package handlers is a collection of handlers (aka "HTTP middleware") for use
+with Go's net/http package (or any framework supporting http.Handler).
+
+The package includes handlers for logging in standardised formats, compressing
+HTTP responses, validating content types and other useful tools for manipulating
+requests and responses.
+*/
+package handlers
diff --git a/vendor/github.com/gorilla/handlers/handlers.go b/vendor/github.com/gorilla/handlers/handlers.go
new file mode 100644
index 00000000..75db7f87
--- /dev/null
+++ b/vendor/github.com/gorilla/handlers/handlers.go
@@ -0,0 +1,399 @@
+// Copyright 2013 The Gorilla Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package handlers
+
+import (
+	"bufio"
+	"fmt"
+	"io"
+	"net"
+	"net/http"
+	"net/url"
+	"sort"
+	"strconv"
+	"strings"
+	"time"
+	"unicode/utf8"
+)
+
+// MethodHandler is an http.Handler that dispatches to a handler whose key in the
+// MethodHandler's map matches the name of the HTTP request's method, eg: GET
+//
+// If the request's method is OPTIONS and OPTIONS is not a key in the map then
+// the handler responds with a status of 200 and sets the Allow header to a
+// comma-separated list of available methods.
+//
+// If the request's method doesn't match any of its keys the handler responds
+// with a status of HTTP 405 "Method Not Allowed" and sets the Allow header to a
+// comma-separated list of available methods.
+type MethodHandler map[string]http.Handler
+
+func (h MethodHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
+	if handler, ok := h[req.Method]; ok {
+		handler.ServeHTTP(w, req)
+	} else {
+		allow := []string{}
+		for k := range h {
+			allow = append(allow, k)
+		}
+		sort.Strings(allow)
+		w.Header().Set("Allow", strings.Join(allow, ", "))
+		if req.Method == "OPTIONS" {
+			w.WriteHeader(http.StatusOK)
+		} else {
+			http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
+		}
+	}
+}
+
+// loggingHandler is the http.Handler implementation for LoggingHandlerTo and its
+// friends
+type loggingHandler struct {
+	writer  io.Writer
+	handler http.Handler
+}
+
+// combinedLoggingHandler is the http.Handler implementation for LoggingHandlerTo
+// and its friends
+type combinedLoggingHandler struct {
+	writer  io.Writer
+	handler http.Handler
+}
+
+func (h loggingHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
+	t := time.Now()
+	logger := makeLogger(w)
+	url := *req.URL
+	h.handler.ServeHTTP(logger, req)
+	writeLog(h.writer, req, url, t, logger.Status(), logger.Size())
+}
+
+func (h combinedLoggingHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
+	t := time.Now()
+	logger := makeLogger(w)
+	url := *req.URL
+	h.handler.ServeHTTP(logger, req)
+	writeCombinedLog(h.writer, req, url, t, logger.Status(), logger.Size())
+}
+
+func makeLogger(w http.ResponseWriter) loggingResponseWriter {
+	var logger loggingResponseWriter = &responseLogger{w: w, status: http.StatusOK}
+	if _, ok := w.(http.Hijacker); ok {
+		logger = &hijackLogger{responseLogger{w: w, status: http.StatusOK}}
+	}
+	h, ok1 := logger.(http.Hijacker)
+	c, ok2 := w.(http.CloseNotifier)
+	if ok1 && ok2 {
+		return hijackCloseNotifier{logger, h, c}
+	}
+	if ok2 {
+		return &closeNotifyWriter{logger, c}
+	}
+	return logger
+}
+
+type commonLoggingResponseWriter interface {
+	http.ResponseWriter
+	http.Flusher
+	Status() int
+	Size() int
+}
+
+// responseLogger is wrapper of http.ResponseWriter that keeps track of its HTTP
+// status code and body size
+type responseLogger struct {
+	w      http.ResponseWriter
+	status int
+	size   int
+}
+
+func (l *responseLogger) Header() http.Header {
+	return l.w.Header()
+}
+
+func (l *responseLogger) Write(b []byte) (int, error) {
+	size, err := l.w.Write(b)
+	l.size += size
+	return size, err
+}
+
+func (l *responseLogger) WriteHeader(s int) {
+	l.w.WriteHeader(s)
+	l.status = s
+}
+
+func (l *responseLogger) Status() int {
+	return l.status
+}
+
+func (l *responseLogger) Size() int {
+	return l.size
+}
+
+func (l *responseLogger) Flush() {
+	f, ok := l.w.(http.Flusher)
+	if ok {
+		f.Flush()
+	}
+}
+
+type hijackLogger struct {
+	responseLogger
+}
+
+func (l *hijackLogger) Hijack() (net.Conn, *bufio.ReadWriter, error) {
+	h := l.responseLogger.w.(http.Hijacker)
+	conn, rw, err := h.Hijack()
+	if err == nil && l.responseLogger.status == 0 {
+		// The status will be StatusSwitchingProtocols if there was no error and
+		// WriteHeader has not been called yet
+		l.responseLogger.status = http.StatusSwitchingProtocols
+	}
+	return conn, rw, err
+}
+
+type closeNotifyWriter struct {
+	loggingResponseWriter
+	http.CloseNotifier
+}
+
+type hijackCloseNotifier struct {
+	loggingResponseWriter
+	http.Hijacker
+	http.CloseNotifier
+}
+
+const lowerhex = "0123456789abcdef"
+
+func appendQuoted(buf []byte, s string) []byte {
+	var runeTmp [utf8.UTFMax]byte
+	for width := 0; len(s) > 0; s = s[width:] {
+		r := rune(s[0])
+		width = 1
+		if r >= utf8.RuneSelf {
+			r, width = utf8.DecodeRuneInString(s)
+		}
+		if width == 1 && r == utf8.RuneError {
+			buf = append(buf, `\x`...)
+			buf = append(buf, lowerhex[s[0]>>4])
+			buf = append(buf, lowerhex[s[0]&0xF])
+			continue
+		}
+		if r == rune('"') || r == '\\' { // always backslashed
+			buf = append(buf, '\\')
+			buf = append(buf, byte(r))
+			continue
+		}
+		if strconv.IsPrint(r) {
+			n := utf8.EncodeRune(runeTmp[:], r)
+			buf = append(buf, runeTmp[:n]...)
+			continue
+		}
+		switch r {
+		case '\a':
+			buf = append(buf, `\a`...)
+		case '\b':
+			buf = append(buf, `\b`...)
+		case '\f':
+			buf = append(buf, `\f`...)
+		case '\n':
+			buf = append(buf, `\n`...)
+		case '\r':
+			buf = append(buf, `\r`...)
+		case '\t':
+			buf = append(buf, `\t`...)
+		case '\v':
+			buf = append(buf, `\v`...)
+		default:
+			switch {
+			case r < ' ':
+				buf = append(buf, `\x`...)
+				buf = append(buf, lowerhex[s[0]>>4])
+				buf = append(buf, lowerhex[s[0]&0xF])
+			case r > utf8.MaxRune:
+				r = 0xFFFD
+				fallthrough
+			case r < 0x10000:
+				buf = append(buf, `\u`...)
+				for s := 12; s >= 0; s -= 4 {
+					buf = append(buf, lowerhex[r>>uint(s)&0xF])
+				}
+			default:
+				buf = append(buf, `\U`...)
+				for s := 28; s >= 0; s -= 4 {
+					buf = append(buf, lowerhex[r>>uint(s)&0xF])
+				}
+			}
+		}
+	}
+	return buf
+
+}
+
+// buildCommonLogLine builds a log entry for req in Apache Common Log Format.
+// ts is the timestamp with which the entry should be logged.
+// status and size are used to provide the response HTTP status and size.
+func buildCommonLogLine(req *http.Request, url url.URL, ts time.Time, status int, size int) []byte {
+	username := "-"
+	if url.User != nil {
+		if name := url.User.Username(); name != "" {
+			username = name
+		}
+	}
+
+	host, _, err := net.SplitHostPort(req.RemoteAddr)
+
+	if err != nil {
+		host = req.RemoteAddr
+	}
+
+	uri := req.RequestURI
+
+	// Requests using the CONNECT method over HTTP/2.0 must use
+	// the authority field (aka r.Host) to identify the target.
+	// Refer: https://httpwg.github.io/specs/rfc7540.html#CONNECT
+	if req.ProtoMajor == 2 && req.Method == "CONNECT" {
+		uri = req.Host
+	}
+	if uri == "" {
+		uri = url.RequestURI()
+	}
+
+	buf := make([]byte, 0, 3*(len(host)+len(username)+len(req.Method)+len(uri)+len(req.Proto)+50)/2)
+	buf = append(buf, host...)
+	buf = append(buf, " - "...)
+	buf = append(buf, username...)
+	buf = append(buf, " ["...)
+	buf = append(buf, ts.Format("02/Jan/2006:15:04:05 -0700")...)
+	buf = append(buf, `] "`...)
+	buf = append(buf, req.Method...)
+	buf = append(buf, " "...)
+	buf = appendQuoted(buf, uri)
+	buf = append(buf, " "...)
+	buf = append(buf, req.Proto...)
+	buf = append(buf, `" `...)
+	buf = append(buf, strconv.Itoa(status)...)
+	buf = append(buf, " "...)
+	buf = append(buf, strconv.Itoa(size)...)
+	return buf
+}
+
+// writeLog writes a log entry for req to w in Apache Common Log Format.
+// ts is the timestamp with which the entry should be logged.
+// status and size are used to provide the response HTTP status and size.
+func writeLog(w io.Writer, req *http.Request, url url.URL, ts time.Time, status, size int) {
+	buf := buildCommonLogLine(req, url, ts, status, size)
+	buf = append(buf, '\n')
+	w.Write(buf)
+}
+
+// writeCombinedLog writes a log entry for req to w in Apache Combined Log Format.
+// ts is the timestamp with which the entry should be logged.
+// status and size are used to provide the response HTTP status and size.
+func writeCombinedLog(w io.Writer, req *http.Request, url url.URL, ts time.Time, status, size int) {
+	buf := buildCommonLogLine(req, url, ts, status, size)
+	buf = append(buf, ` "`...)
+	buf = appendQuoted(buf, req.Referer())
+	buf = append(buf, `" "`...)
+	buf = appendQuoted(buf, req.UserAgent())
+	buf = append(buf, '"', '\n')
+	w.Write(buf)
+}
+
+// CombinedLoggingHandler return a http.Handler that wraps h and logs requests to out in
+// Apache Combined Log Format.
+//
+// See http://httpd.apache.org/docs/2.2/logs.html#combined for a description of this format.
+//
+// LoggingHandler always sets the ident field of the log to -
+func CombinedLoggingHandler(out io.Writer, h http.Handler) http.Handler {
+	return combinedLoggingHandler{out, h}
+}
+
+// LoggingHandler return a http.Handler that wraps h and logs requests to out in
+// Apache Common Log Format (CLF).
+//
+// See http://httpd.apache.org/docs/2.2/logs.html#common for a description of this format.
+//
+// LoggingHandler always sets the ident field of the log to -
+//
+// Example:
+//
+//  r := mux.NewRouter()
+//  r.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
+//  	w.Write([]byte("This is a catch-all route"))
+//  })
+//  loggedRouter := handlers.LoggingHandler(os.Stdout, r)
+//  http.ListenAndServe(":1123", loggedRouter)
+//
+func LoggingHandler(out io.Writer, h http.Handler) http.Handler {
+	return loggingHandler{out, h}
+}
+
+// isContentType validates the Content-Type header matches the supplied
+// contentType. That is, its type and subtype match.
+func isContentType(h http.Header, contentType string) bool {
+	ct := h.Get("Content-Type")
+	if i := strings.IndexRune(ct, ';'); i != -1 {
+		ct = ct[0:i]
+	}
+	return ct == contentType
+}
+
+// ContentTypeHandler wraps and returns a http.Handler, validating the request
+// content type is compatible with the contentTypes list. It writes a HTTP 415
+// error if that fails.
+//
+// Only PUT, POST, and PATCH requests are considered.
+func ContentTypeHandler(h http.Handler, contentTypes ...string) http.Handler {
+	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+		if !(r.Method == "PUT" || r.Method == "POST" || r.Method == "PATCH") {
+			h.ServeHTTP(w, r)
+			return
+		}
+
+		for _, ct := range contentTypes {
+			if isContentType(r.Header, ct) {
+				h.ServeHTTP(w, r)
+				return
+			}
+		}
+		http.Error(w, fmt.Sprintf("Unsupported content type %q; expected one of %q", r.Header.Get("Content-Type"), contentTypes), http.StatusUnsupportedMediaType)
+	})
+}
+
+const (
+	// HTTPMethodOverrideHeader is a commonly used
+	// http header to override a request method.
+	HTTPMethodOverrideHeader = "X-HTTP-Method-Override"
+	// HTTPMethodOverrideFormKey is a commonly used
+	// HTML form key to override a request method.
+	HTTPMethodOverrideFormKey = "_method"
+)
+
+// HTTPMethodOverrideHandler wraps and returns a http.Handler which checks for
+// the X-HTTP-Method-Override header or the _method form key, and overrides (if
+// valid) request.Method with its value.
+//
+// This is especially useful for HTTP clients that don't support many http verbs.
+// It isn't secure to override e.g a GET to a POST, so only POST requests are
+// considered.  Likewise, the override method can only be a "write" method: PUT,
+// PATCH or DELETE.
+//
+// Form method takes precedence over header method.
+func HTTPMethodOverrideHandler(h http.Handler) http.Handler {
+	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+		if r.Method == "POST" {
+			om := r.FormValue(HTTPMethodOverrideFormKey)
+			if om == "" {
+				om = r.Header.Get(HTTPMethodOverrideHeader)
+			}
+			if om == "PUT" || om == "PATCH" || om == "DELETE" {
+				r.Method = om
+			}
+		}
+		h.ServeHTTP(w, r)
+	})
+}
diff --git a/vendor/github.com/gorilla/handlers/handlers_go18.go b/vendor/github.com/gorilla/handlers/handlers_go18.go
new file mode 100644
index 00000000..35eb8d4f
--- /dev/null
+++ b/vendor/github.com/gorilla/handlers/handlers_go18.go
@@ -0,0 +1,21 @@
+// +build go1.8
+
+package handlers
+
+import (
+	"fmt"
+	"net/http"
+)
+
+type loggingResponseWriter interface {
+	commonLoggingResponseWriter
+	http.Pusher
+}
+
+func (l *responseLogger) Push(target string, opts *http.PushOptions) error {
+	p, ok := l.w.(http.Pusher)
+	if !ok {
+		return fmt.Errorf("responseLogger does not implement http.Pusher")
+	}
+	return p.Push(target, opts)
+}
diff --git a/vendor/github.com/gorilla/handlers/handlers_pre18.go b/vendor/github.com/gorilla/handlers/handlers_pre18.go
new file mode 100644
index 00000000..197836ab
--- /dev/null
+++ b/vendor/github.com/gorilla/handlers/handlers_pre18.go
@@ -0,0 +1,7 @@
+// +build !go1.8
+
+package handlers
+
+type loggingResponseWriter interface {
+	commonLoggingResponseWriter
+}
diff --git a/vendor/github.com/gorilla/handlers/proxy_headers.go b/vendor/github.com/gorilla/handlers/proxy_headers.go
new file mode 100644
index 00000000..0be750fd
--- /dev/null
+++ b/vendor/github.com/gorilla/handlers/proxy_headers.go
@@ -0,0 +1,120 @@
+package handlers
+
+import (
+	"net/http"
+	"regexp"
+	"strings"
+)
+
+var (
+	// De-facto standard header keys.
+	xForwardedFor    = http.CanonicalHeaderKey("X-Forwarded-For")
+	xForwardedHost   = http.CanonicalHeaderKey("X-Forwarded-Host")
+	xForwardedProto  = http.CanonicalHeaderKey("X-Forwarded-Proto")
+	xForwardedScheme = http.CanonicalHeaderKey("X-Forwarded-Scheme")
+	xRealIP          = http.CanonicalHeaderKey("X-Real-IP")
+)
+
+var (
+	// RFC7239 defines a new "Forwarded: " header designed to replace the
+	// existing use of X-Forwarded-* headers.
+	// e.g. Forwarded: for=192.0.2.60;proto=https;by=203.0.113.43
+	forwarded = http.CanonicalHeaderKey("Forwarded")
+	// Allows for a sub-match of the first value after 'for=' to the next
+	// comma, semi-colon or space. The match is case-insensitive.
+	forRegex = regexp.MustCompile(`(?i)(?:for=)([^(;|,| )]+)`)
+	// Allows for a sub-match for the first instance of scheme (http|https)
+	// prefixed by 'proto='. The match is case-insensitive.
+	protoRegex = regexp.MustCompile(`(?i)(?:proto=)(https|http)`)
+)
+
+// ProxyHeaders inspects common reverse proxy headers and sets the corresponding
+// fields in the HTTP request struct. These are X-Forwarded-For and X-Real-IP
+// for the remote (client) IP address, X-Forwarded-Proto or X-Forwarded-Scheme
+// for the scheme (http|https) and the RFC7239 Forwarded header, which may
+// include both client IPs and schemes.
+//
+// NOTE: This middleware should only be used when behind a reverse
+// proxy like nginx, HAProxy or Apache. Reverse proxies that don't (or are
+// configured not to) strip these headers from client requests, or where these
+// headers are accepted "as is" from a remote client (e.g. when Go is not behind
+// a proxy), can manifest as a vulnerability if your application uses these
+// headers for validating the 'trustworthiness' of a request.
+func ProxyHeaders(h http.Handler) http.Handler {
+	fn := func(w http.ResponseWriter, r *http.Request) {
+		// Set the remote IP with the value passed from the proxy.
+		if fwd := getIP(r); fwd != "" {
+			r.RemoteAddr = fwd
+		}
+
+		// Set the scheme (proto) with the value passed from the proxy.
+		if scheme := getScheme(r); scheme != "" {
+			r.URL.Scheme = scheme
+		}
+		// Set the host with the value passed by the proxy
+		if r.Header.Get(xForwardedHost) != "" {
+			r.Host = r.Header.Get(xForwardedHost)
+		}
+		// Call the next handler in the chain.
+		h.ServeHTTP(w, r)
+	}
+
+	return http.HandlerFunc(fn)
+}
+
+// getIP retrieves the IP from the X-Forwarded-For, X-Real-IP and RFC7239
+// Forwarded headers (in that order).
+func getIP(r *http.Request) string {
+	var addr string
+
+	if fwd := r.Header.Get(xForwardedFor); fwd != "" {
+		// Only grab the first (client) address. Note that '192.168.0.1,
+		// 10.1.1.1' is a valid key for X-Forwarded-For where addresses after
+		// the first may represent forwarding proxies earlier in the chain.
+		s := strings.Index(fwd, ", ")
+		if s == -1 {
+			s = len(fwd)
+		}
+		addr = fwd[:s]
+	} else if fwd := r.Header.Get(xRealIP); fwd != "" {
+		// X-Real-IP should only contain one IP address (the client making the
+		// request).
+		addr = fwd
+	} else if fwd := r.Header.Get(forwarded); fwd != "" {
+		// match should contain at least two elements if the protocol was
+		// specified in the Forwarded header. The first element will always be
+		// the 'for=' capture, which we ignore. In the case of multiple IP
+		// addresses (for=8.8.8.8, 8.8.4.4,172.16.1.20 is valid) we only
+		// extract the first, which should be the client IP.
+		if match := forRegex.FindStringSubmatch(fwd); len(match) > 1 {
+			// IPv6 addresses in Forwarded headers are quoted-strings. We strip
+			// these quotes.
+			addr = strings.Trim(match[1], `"`)
+		}
+	}
+
+	return addr
+}
+
+// getScheme retrieves the scheme from the X-Forwarded-Proto and RFC7239
+// Forwarded headers (in that order).
+func getScheme(r *http.Request) string {
+	var scheme string
+
+	// Retrieve the scheme from X-Forwarded-Proto.
+	if proto := r.Header.Get(xForwardedProto); proto != "" {
+		scheme = strings.ToLower(proto)
+	} else if proto = r.Header.Get(xForwardedScheme); proto != "" {
+		scheme = strings.ToLower(proto)
+	} else if proto = r.Header.Get(forwarded); proto != "" {
+		// match should contain at least two elements if the protocol was
+		// specified in the Forwarded header. The first element will always be
+		// the 'proto=' capture, which we ignore. In the case of multiple proto
+		// parameters (invalid) we only extract the first.
+		if match := protoRegex.FindStringSubmatch(proto); len(match) > 1 {
+			scheme = strings.ToLower(match[1])
+		}
+	}
+
+	return scheme
+}
diff --git a/vendor/github.com/gorilla/handlers/recovery.go b/vendor/github.com/gorilla/handlers/recovery.go
new file mode 100644
index 00000000..b1be9dc8
--- /dev/null
+++ b/vendor/github.com/gorilla/handlers/recovery.go
@@ -0,0 +1,91 @@
+package handlers
+
+import (
+	"log"
+	"net/http"
+	"runtime/debug"
+)
+
+// RecoveryHandlerLogger is an interface used by the recovering handler to print logs.
+type RecoveryHandlerLogger interface {
+	Println(...interface{})
+}
+
+type recoveryHandler struct {
+	handler    http.Handler
+	logger     RecoveryHandlerLogger
+	printStack bool
+}
+
+// RecoveryOption provides a functional approach to define
+// configuration for a handler; such as setting the logging
+// whether or not to print strack traces on panic.
+type RecoveryOption func(http.Handler)
+
+func parseRecoveryOptions(h http.Handler, opts ...RecoveryOption) http.Handler {
+	for _, option := range opts {
+		option(h)
+	}
+
+	return h
+}
+
+// RecoveryHandler is HTTP middleware that recovers from a panic,
+// logs the panic, writes http.StatusInternalServerError, and
+// continues to the next handler.
+//
+// Example:
+//
+//  r := mux.NewRouter()
+//  r.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
+//  	panic("Unexpected error!")
+//  })
+//
+//  http.ListenAndServe(":1123", handlers.RecoveryHandler()(r))
+func RecoveryHandler(opts ...RecoveryOption) func(h http.Handler) http.Handler {
+	return func(h http.Handler) http.Handler {
+		r := &recoveryHandler{handler: h}
+		return parseRecoveryOptions(r, opts...)
+	}
+}
+
+// RecoveryLogger is a functional option to override
+// the default logger
+func RecoveryLogger(logger RecoveryHandlerLogger) RecoveryOption {
+	return func(h http.Handler) {
+		r := h.(*recoveryHandler)
+		r.logger = logger
+	}
+}
+
+// PrintRecoveryStack is a functional option to enable
+// or disable printing stack traces on panic.
+func PrintRecoveryStack(print bool) RecoveryOption {
+	return func(h http.Handler) {
+		r := h.(*recoveryHandler)
+		r.printStack = print
+	}
+}
+
+func (h recoveryHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
+	defer func() {
+		if err := recover(); err != nil {
+			w.WriteHeader(http.StatusInternalServerError)
+			h.log(err)
+		}
+	}()
+
+	h.handler.ServeHTTP(w, req)
+}
+
+func (h recoveryHandler) log(v ...interface{}) {
+	if h.logger != nil {
+		h.logger.Println(v...)
+	} else {
+		log.Println(v...)
+	}
+
+	if h.printStack {
+		debug.PrintStack()
+	}
+}
diff --git a/vendor/golang.org/x/crypto/ed25519/ed25519.go b/vendor/golang.org/x/crypto/ed25519/ed25519.go
index 16cd3854..d6f683ba 100644
--- a/vendor/golang.org/x/crypto/ed25519/ed25519.go
+++ b/vendor/golang.org/x/crypto/ed25519/ed25519.go
@@ -6,7 +6,10 @@
 // https://ed25519.cr.yp.to/.
 //
 // These functions are also compatible with the “Ed25519” function defined in
-// https://tools.ietf.org/html/draft-irtf-cfrg-eddsa-05.
+// RFC 8032. However, unlike RFC 8032's formulation, this package's private key
+// representation includes a public key suffix to make multiple signing
+// operations with the same key more efficient. This package refers to the RFC
+// 8032 private key as the “seed”.
 package ed25519
 
 // This code is a port of the public domain, “ref10” implementation of ed25519
@@ -31,6 +34,8 @@ const (
 	PrivateKeySize = 64
 	// SignatureSize is the size, in bytes, of signatures generated and verified by this package.
 	SignatureSize = 64
+	// SeedSize is the size, in bytes, of private key seeds. These are the private key representations used by RFC 8032.
+	SeedSize = 32
 )
 
 // PublicKey is the type of Ed25519 public keys.
@@ -46,6 +51,15 @@ func (priv PrivateKey) Public() crypto.PublicKey {
 	return PublicKey(publicKey)
 }
 
+// Seed returns the private key seed corresponding to priv. It is provided for
+// interoperability with RFC 8032. RFC 8032's private keys correspond to seeds
+// in this package.
+func (priv PrivateKey) Seed() []byte {
+	seed := make([]byte, SeedSize)
+	copy(seed, priv[:32])
+	return seed
+}
+
 // Sign signs the given message with priv.
 // Ed25519 performs two passes over messages to be signed and therefore cannot
 // handle pre-hashed messages. Thus opts.HashFunc() must return zero to
@@ -61,19 +75,33 @@ func (priv PrivateKey) Sign(rand io.Reader, message []byte, opts crypto.SignerOp
 
 // GenerateKey generates a public/private key pair using entropy from rand.
 // If rand is nil, crypto/rand.Reader will be used.
-func GenerateKey(rand io.Reader) (publicKey PublicKey, privateKey PrivateKey, err error) {
+func GenerateKey(rand io.Reader) (PublicKey, PrivateKey, error) {
 	if rand == nil {
 		rand = cryptorand.Reader
 	}
 
-	privateKey = make([]byte, PrivateKeySize)
-	publicKey = make([]byte, PublicKeySize)
-	_, err = io.ReadFull(rand, privateKey[:32])
-	if err != nil {
+	seed := make([]byte, SeedSize)
+	if _, err := io.ReadFull(rand, seed); err != nil {
 		return nil, nil, err
 	}
 
-	digest := sha512.Sum512(privateKey[:32])
+	privateKey := NewKeyFromSeed(seed)
+	publicKey := make([]byte, PublicKeySize)
+	copy(publicKey, privateKey[32:])
+
+	return publicKey, privateKey, nil
+}
+
+// NewKeyFromSeed calculates a private key from a seed. It will panic if
+// len(seed) is not SeedSize. This function is provided for interoperability
+// with RFC 8032. RFC 8032's private keys correspond to seeds in this
+// package.
+func NewKeyFromSeed(seed []byte) PrivateKey {
+	if l := len(seed); l != SeedSize {
+		panic("ed25519: bad seed length: " + strconv.Itoa(l))
+	}
+
+	digest := sha512.Sum512(seed)
 	digest[0] &= 248
 	digest[31] &= 127
 	digest[31] |= 64
@@ -85,10 +113,11 @@ func GenerateKey(rand io.Reader) (publicKey PublicKey, privateKey PrivateKey, er
 	var publicKeyBytes [32]byte
 	A.ToBytes(&publicKeyBytes)
 
+	privateKey := make([]byte, PrivateKeySize)
+	copy(privateKey, seed)
 	copy(privateKey[32:], publicKeyBytes[:])
-	copy(publicKey, publicKeyBytes[:])
 
-	return publicKey, privateKey, nil
+	return privateKey
 }
 
 // Sign signs the message with privateKey and returns a signature. It will
@@ -171,9 +200,16 @@ func Verify(publicKey PublicKey, message, sig []byte) bool {
 	edwards25519.ScReduce(&hReduced, &digest)
 
 	var R edwards25519.ProjectiveGroupElement
-	var b [32]byte
-	copy(b[:], sig[32:])
-	edwards25519.GeDoubleScalarMultVartime(&R, &hReduced, &A, &b)
+	var s [32]byte
+	copy(s[:], sig[32:])
+
+	// https://tools.ietf.org/html/rfc8032#section-5.1.7 requires that s be in
+	// the range [0, order) in order to prevent signature malleability.
+	if !edwards25519.ScMinimal(&s) {
+		return false
+	}
+
+	edwards25519.GeDoubleScalarMultVartime(&R, &hReduced, &A, &s)
 
 	var checkR [32]byte
 	R.ToBytes(&checkR)
diff --git a/vendor/golang.org/x/crypto/ed25519/internal/edwards25519/edwards25519.go b/vendor/golang.org/x/crypto/ed25519/internal/edwards25519/edwards25519.go
index 5f8b9947..fd03c252 100644
--- a/vendor/golang.org/x/crypto/ed25519/internal/edwards25519/edwards25519.go
+++ b/vendor/golang.org/x/crypto/ed25519/internal/edwards25519/edwards25519.go
@@ -4,6 +4,8 @@
 
 package edwards25519
 
+import "encoding/binary"
+
 // This code is a port of the public domain, “ref10” implementation of ed25519
 // from SUPERCOP.
 
@@ -1769,3 +1771,23 @@ func ScReduce(out *[32]byte, s *[64]byte) {
 	out[30] = byte(s11 >> 9)
 	out[31] = byte(s11 >> 17)
 }
+
+// order is the order of Curve25519 in little-endian form.
+var order = [4]uint64{0x5812631a5cf5d3ed, 0x14def9dea2f79cd6, 0, 0x1000000000000000}
+
+// ScMinimal returns true if the given scalar is less than the order of the
+// curve.
+func ScMinimal(scalar *[32]byte) bool {
+	for i := 3; ; i-- {
+		v := binary.LittleEndian.Uint64(scalar[i*8:])
+		if v > order[i] {
+			return false
+		} else if v < order[i] {
+			break
+		} else if i == 0 {
+			return false
+		}
+	}
+
+	return true
+}
diff --git a/vendor/golang.org/x/crypto/pbkdf2/pbkdf2.go b/vendor/golang.org/x/crypto/pbkdf2/pbkdf2.go
deleted file mode 100644
index 593f6530..00000000
--- a/vendor/golang.org/x/crypto/pbkdf2/pbkdf2.go
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright 2012 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-/*
-Package pbkdf2 implements the key derivation function PBKDF2 as defined in RFC
-2898 / PKCS #5 v2.0.
-
-A key derivation function is useful when encrypting data based on a password
-or any other not-fully-random data. It uses a pseudorandom function to derive
-a secure encryption key based on the password.
-
-While v2.0 of the standard defines only one pseudorandom function to use,
-HMAC-SHA1, the drafted v2.1 specification allows use of all five FIPS Approved
-Hash Functions SHA-1, SHA-224, SHA-256, SHA-384 and SHA-512 for HMAC. To
-choose, you can pass the `New` functions from the different SHA packages to
-pbkdf2.Key.
-*/
-package pbkdf2 // import "golang.org/x/crypto/pbkdf2"
-
-import (
-	"crypto/hmac"
-	"hash"
-)
-
-// Key derives a key from the password, salt and iteration count, returning a
-// []byte of length keylen that can be used as cryptographic key. The key is
-// derived based on the method described as PBKDF2 with the HMAC variant using
-// the supplied hash function.
-//
-// For example, to use a HMAC-SHA-1 based PBKDF2 key derivation function, you
-// can get a derived key for e.g. AES-256 (which needs a 32-byte key) by
-// doing:
-//
-// 	dk := pbkdf2.Key([]byte("some password"), salt, 4096, 32, sha1.New)
-//
-// Remember to get a good random salt. At least 8 bytes is recommended by the
-// RFC.
-//
-// Using a higher iteration count will increase the cost of an exhaustive
-// search but will also make derivation proportionally slower.
-func Key(password, salt []byte, iter, keyLen int, h func() hash.Hash) []byte {
-	prf := hmac.New(h, password)
-	hashLen := prf.Size()
-	numBlocks := (keyLen + hashLen - 1) / hashLen
-
-	var buf [4]byte
-	dk := make([]byte, 0, numBlocks*hashLen)
-	U := make([]byte, hashLen)
-	for block := 1; block <= numBlocks; block++ {
-		// N.B.: || means concatenation, ^ means XOR
-		// for each block T_i = U_1 ^ U_2 ^ ... ^ U_iter
-		// U_1 = PRF(password, salt || uint(i))
-		prf.Reset()
-		prf.Write(salt)
-		buf[0] = byte(block >> 24)
-		buf[1] = byte(block >> 16)
-		buf[2] = byte(block >> 8)
-		buf[3] = byte(block)
-		prf.Write(buf[:4])
-		dk = prf.Sum(dk)
-		T := dk[len(dk)-hashLen:]
-		copy(U, T)
-
-		// U_n = PRF(password, U_(n-1))
-		for n := 2; n <= iter; n++ {
-			prf.Reset()
-			prf.Write(U)
-			U = U[:0]
-			U = prf.Sum(U)
-			for x := range U {
-				T[x] ^= U[x]
-			}
-		}
-	}
-	return dk[:keyLen]
-}
diff --git a/vendor/golang.org/x/crypto/scrypt/scrypt.go b/vendor/golang.org/x/crypto/scrypt/scrypt.go
deleted file mode 100644
index 9b25b5ac..00000000
--- a/vendor/golang.org/x/crypto/scrypt/scrypt.go
+++ /dev/null
@@ -1,244 +0,0 @@
-// Copyright 2012 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package scrypt implements the scrypt key derivation function as defined in
-// Colin Percival's paper "Stronger Key Derivation via Sequential Memory-Hard
-// Functions" (https://www.tarsnap.com/scrypt/scrypt.pdf).
-package scrypt // import "golang.org/x/crypto/scrypt"
-
-import (
-	"crypto/sha256"
-	"errors"
-
-	"golang.org/x/crypto/pbkdf2"
-)
-
-const maxInt = int(^uint(0) >> 1)
-
-// blockCopy copies n numbers from src into dst.
-func blockCopy(dst, src []uint32, n int) {
-	copy(dst, src[:n])
-}
-
-// blockXOR XORs numbers from dst with n numbers from src.
-func blockXOR(dst, src []uint32, n int) {
-	for i, v := range src[:n] {
-		dst[i] ^= v
-	}
-}
-
-// salsaXOR applies Salsa20/8 to the XOR of 16 numbers from tmp and in,
-// and puts the result into both both tmp and out.
-func salsaXOR(tmp *[16]uint32, in, out []uint32) {
-	w0 := tmp[0] ^ in[0]
-	w1 := tmp[1] ^ in[1]
-	w2 := tmp[2] ^ in[2]
-	w3 := tmp[3] ^ in[3]
-	w4 := tmp[4] ^ in[4]
-	w5 := tmp[5] ^ in[5]
-	w6 := tmp[6] ^ in[6]
-	w7 := tmp[7] ^ in[7]
-	w8 := tmp[8] ^ in[8]
-	w9 := tmp[9] ^ in[9]
-	w10 := tmp[10] ^ in[10]
-	w11 := tmp[11] ^ in[11]
-	w12 := tmp[12] ^ in[12]
-	w13 := tmp[13] ^ in[13]
-	w14 := tmp[14] ^ in[14]
-	w15 := tmp[15] ^ in[15]
-
-	x0, x1, x2, x3, x4, x5, x6, x7, x8 := w0, w1, w2, w3, w4, w5, w6, w7, w8
-	x9, x10, x11, x12, x13, x14, x15 := w9, w10, w11, w12, w13, w14, w15
-
-	for i := 0; i < 8; i += 2 {
-		u := x0 + x12
-		x4 ^= u<<7 | u>>(32-7)
-		u = x4 + x0
-		x8 ^= u<<9 | u>>(32-9)
-		u = x8 + x4
-		x12 ^= u<<13 | u>>(32-13)
-		u = x12 + x8
-		x0 ^= u<<18 | u>>(32-18)
-
-		u = x5 + x1
-		x9 ^= u<<7 | u>>(32-7)
-		u = x9 + x5
-		x13 ^= u<<9 | u>>(32-9)
-		u = x13 + x9
-		x1 ^= u<<13 | u>>(32-13)
-		u = x1 + x13
-		x5 ^= u<<18 | u>>(32-18)
-
-		u = x10 + x6
-		x14 ^= u<<7 | u>>(32-7)
-		u = x14 + x10
-		x2 ^= u<<9 | u>>(32-9)
-		u = x2 + x14
-		x6 ^= u<<13 | u>>(32-13)
-		u = x6 + x2
-		x10 ^= u<<18 | u>>(32-18)
-
-		u = x15 + x11
-		x3 ^= u<<7 | u>>(32-7)
-		u = x3 + x15
-		x7 ^= u<<9 | u>>(32-9)
-		u = x7 + x3
-		x11 ^= u<<13 | u>>(32-13)
-		u = x11 + x7
-		x15 ^= u<<18 | u>>(32-18)
-
-		u = x0 + x3
-		x1 ^= u<<7 | u>>(32-7)
-		u = x1 + x0
-		x2 ^= u<<9 | u>>(32-9)
-		u = x2 + x1
-		x3 ^= u<<13 | u>>(32-13)
-		u = x3 + x2
-		x0 ^= u<<18 | u>>(32-18)
-
-		u = x5 + x4
-		x6 ^= u<<7 | u>>(32-7)
-		u = x6 + x5
-		x7 ^= u<<9 | u>>(32-9)
-		u = x7 + x6
-		x4 ^= u<<13 | u>>(32-13)
-		u = x4 + x7
-		x5 ^= u<<18 | u>>(32-18)
-
-		u = x10 + x9
-		x11 ^= u<<7 | u>>(32-7)
-		u = x11 + x10
-		x8 ^= u<<9 | u>>(32-9)
-		u = x8 + x11
-		x9 ^= u<<13 | u>>(32-13)
-		u = x9 + x8
-		x10 ^= u<<18 | u>>(32-18)
-
-		u = x15 + x14
-		x12 ^= u<<7 | u>>(32-7)
-		u = x12 + x15
-		x13 ^= u<<9 | u>>(32-9)
-		u = x13 + x12
-		x14 ^= u<<13 | u>>(32-13)
-		u = x14 + x13
-		x15 ^= u<<18 | u>>(32-18)
-	}
-	x0 += w0
-	x1 += w1
-	x2 += w2
-	x3 += w3
-	x4 += w4
-	x5 += w5
-	x6 += w6
-	x7 += w7
-	x8 += w8
-	x9 += w9
-	x10 += w10
-	x11 += w11
-	x12 += w12
-	x13 += w13
-	x14 += w14
-	x15 += w15
-
-	out[0], tmp[0] = x0, x0
-	out[1], tmp[1] = x1, x1
-	out[2], tmp[2] = x2, x2
-	out[3], tmp[3] = x3, x3
-	out[4], tmp[4] = x4, x4
-	out[5], tmp[5] = x5, x5
-	out[6], tmp[6] = x6, x6
-	out[7], tmp[7] = x7, x7
-	out[8], tmp[8] = x8, x8
-	out[9], tmp[9] = x9, x9
-	out[10], tmp[10] = x10, x10
-	out[11], tmp[11] = x11, x11
-	out[12], tmp[12] = x12, x12
-	out[13], tmp[13] = x13, x13
-	out[14], tmp[14] = x14, x14
-	out[15], tmp[15] = x15, x15
-}
-
-func blockMix(tmp *[16]uint32, in, out []uint32, r int) {
-	blockCopy(tmp[:], in[(2*r-1)*16:], 16)
-	for i := 0; i < 2*r; i += 2 {
-		salsaXOR(tmp, in[i*16:], out[i*8:])
-		salsaXOR(tmp, in[i*16+16:], out[i*8+r*16:])
-	}
-}
-
-func integer(b []uint32, r int) uint64 {
-	j := (2*r - 1) * 16
-	return uint64(b[j]) | uint64(b[j+1])<<32
-}
-
-func smix(b []byte, r, N int, v, xy []uint32) {
-	var tmp [16]uint32
-	x := xy
-	y := xy[32*r:]
-
-	j := 0
-	for i := 0; i < 32*r; i++ {
-		x[i] = uint32(b[j]) | uint32(b[j+1])<<8 | uint32(b[j+2])<<16 | uint32(b[j+3])<<24
-		j += 4
-	}
-	for i := 0; i < N; i += 2 {
-		blockCopy(v[i*(32*r):], x, 32*r)
-		blockMix(&tmp, x, y, r)
-
-		blockCopy(v[(i+1)*(32*r):], y, 32*r)
-		blockMix(&tmp, y, x, r)
-	}
-	for i := 0; i < N; i += 2 {
-		j := int(integer(x, r) & uint64(N-1))
-		blockXOR(x, v[j*(32*r):], 32*r)
-		blockMix(&tmp, x, y, r)
-
-		j = int(integer(y, r) & uint64(N-1))
-		blockXOR(y, v[j*(32*r):], 32*r)
-		blockMix(&tmp, y, x, r)
-	}
-	j = 0
-	for _, v := range x[:32*r] {
-		b[j+0] = byte(v >> 0)
-		b[j+1] = byte(v >> 8)
-		b[j+2] = byte(v >> 16)
-		b[j+3] = byte(v >> 24)
-		j += 4
-	}
-}
-
-// Key derives a key from the password, salt, and cost parameters, returning
-// a byte slice of length keyLen that can be used as cryptographic key.
-//
-// N is a CPU/memory cost parameter, which must be a power of two greater than 1.
-// r and p must satisfy r * p < 2³⁰. If the parameters do not satisfy the
-// limits, the function returns a nil byte slice and an error.
-//
-// For example, you can get a derived key for e.g. AES-256 (which needs a
-// 32-byte key) by doing:
-//
-//      dk, err := scrypt.Key([]byte("some password"), salt, 32768, 8, 1, 32)
-//
-// The recommended parameters for interactive logins as of 2017 are N=32768, r=8
-// and p=1. The parameters N, r, and p should be increased as memory latency and
-// CPU parallelism increases; consider setting N to the highest power of 2 you
-// can derive within 100 milliseconds. Remember to get a good random salt.
-func Key(password, salt []byte, N, r, p, keyLen int) ([]byte, error) {
-	if N <= 1 || N&(N-1) != 0 {
-		return nil, errors.New("scrypt: N must be > 1 and a power of 2")
-	}
-	if uint64(r)*uint64(p) >= 1<<30 || r > maxInt/128/p || r > maxInt/256 || N > maxInt/128/r {
-		return nil, errors.New("scrypt: parameters are too large")
-	}
-
-	xy := make([]uint32, 64*r)
-	v := make([]uint32, 32*N*r)
-	b := pbkdf2.Key(password, salt, 1, p*128*r, sha256.New)
-
-	for i := 0; i < p; i++ {
-		smix(b[i*128*r:], r, N, v, xy)
-	}
-
-	return pbkdf2.Key(password, b, 1, keyLen, sha256.New), nil
-}
diff --git a/vendor/golang.org/x/net/context/context.go b/vendor/golang.org/x/net/context/context.go
deleted file mode 100644
index a3c021d3..00000000
--- a/vendor/golang.org/x/net/context/context.go
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright 2014 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package context defines the Context type, which carries deadlines,
-// cancelation signals, and other request-scoped values across API boundaries
-// and between processes.
-// As of Go 1.7 this package is available in the standard library under the
-// name context.  https://golang.org/pkg/context.
-//
-// Incoming requests to a server should create a Context, and outgoing calls to
-// servers should accept a Context. The chain of function calls between must
-// propagate the Context, optionally replacing it with a modified copy created
-// using WithDeadline, WithTimeout, WithCancel, or WithValue.
-//
-// Programs that use Contexts should follow these rules to keep interfaces
-// consistent across packages and enable static analysis tools to check context
-// propagation:
-//
-// Do not store Contexts inside a struct type; instead, pass a Context
-// explicitly to each function that needs it. The Context should be the first
-// parameter, typically named ctx:
-//
-// 	func DoSomething(ctx context.Context, arg Arg) error {
-// 		// ... use ctx ...
-// 	}
-//
-// Do not pass a nil Context, even if a function permits it. Pass context.TODO
-// if you are unsure about which Context to use.
-//
-// Use context Values only for request-scoped data that transits processes and
-// APIs, not for passing optional parameters to functions.
-//
-// The same Context may be passed to functions running in different goroutines;
-// Contexts are safe for simultaneous use by multiple goroutines.
-//
-// See http://blog.golang.org/context for example code for a server that uses
-// Contexts.
-package context // import "golang.org/x/net/context"
-
-// Background returns a non-nil, empty Context. It is never canceled, has no
-// values, and has no deadline. It is typically used by the main function,
-// initialization, and tests, and as the top-level Context for incoming
-// requests.
-func Background() Context {
-	return background
-}
-
-// TODO returns a non-nil, empty Context. Code should use context.TODO when
-// it's unclear which Context to use or it is not yet available (because the
-// surrounding function has not yet been extended to accept a Context
-// parameter).  TODO is recognized by static analysis tools that determine
-// whether Contexts are propagated correctly in a program.
-func TODO() Context {
-	return todo
-}
diff --git a/vendor/golang.org/x/net/context/go17.go b/vendor/golang.org/x/net/context/go17.go
deleted file mode 100644
index d20f52b7..00000000
--- a/vendor/golang.org/x/net/context/go17.go
+++ /dev/null
@@ -1,72 +0,0 @@
-// Copyright 2016 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build go1.7
-
-package context
-
-import (
-	"context" // standard library's context, as of Go 1.7
-	"time"
-)
-
-var (
-	todo       = context.TODO()
-	background = context.Background()
-)
-
-// Canceled is the error returned by Context.Err when the context is canceled.
-var Canceled = context.Canceled
-
-// DeadlineExceeded is the error returned by Context.Err when the context's
-// deadline passes.
-var DeadlineExceeded = context.DeadlineExceeded
-
-// WithCancel returns a copy of parent with a new Done channel. The returned
-// context's Done channel is closed when the returned cancel function is called
-// or when the parent context's Done channel is closed, whichever happens first.
-//
-// Canceling this context releases resources associated with it, so code should
-// call cancel as soon as the operations running in this Context complete.
-func WithCancel(parent Context) (ctx Context, cancel CancelFunc) {
-	ctx, f := context.WithCancel(parent)
-	return ctx, CancelFunc(f)
-}
-
-// WithDeadline returns a copy of the parent context with the deadline adjusted
-// to be no later than d. If the parent's deadline is already earlier than d,
-// WithDeadline(parent, d) is semantically equivalent to parent. The returned
-// context's Done channel is closed when the deadline expires, when the returned
-// cancel function is called, or when the parent context's Done channel is
-// closed, whichever happens first.
-//
-// Canceling this context releases resources associated with it, so code should
-// call cancel as soon as the operations running in this Context complete.
-func WithDeadline(parent Context, deadline time.Time) (Context, CancelFunc) {
-	ctx, f := context.WithDeadline(parent, deadline)
-	return ctx, CancelFunc(f)
-}
-
-// WithTimeout returns WithDeadline(parent, time.Now().Add(timeout)).
-//
-// Canceling this context releases resources associated with it, so code should
-// call cancel as soon as the operations running in this Context complete:
-//
-// 	func slowOperationWithTimeout(ctx context.Context) (Result, error) {
-// 		ctx, cancel := context.WithTimeout(ctx, 100*time.Millisecond)
-// 		defer cancel()  // releases resources if slowOperation completes before timeout elapses
-// 		return slowOperation(ctx)
-// 	}
-func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) {
-	return WithDeadline(parent, time.Now().Add(timeout))
-}
-
-// WithValue returns a copy of parent in which the value associated with key is
-// val.
-//
-// Use context Values only for request-scoped data that transits processes and
-// APIs, not for passing optional parameters to functions.
-func WithValue(parent Context, key interface{}, val interface{}) Context {
-	return context.WithValue(parent, key, val)
-}
diff --git a/vendor/golang.org/x/net/context/go19.go b/vendor/golang.org/x/net/context/go19.go
deleted file mode 100644
index d88bd1db..00000000
--- a/vendor/golang.org/x/net/context/go19.go
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2017 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build go1.9
-
-package context
-
-import "context" // standard library's context, as of Go 1.7
-
-// A Context carries a deadline, a cancelation signal, and other values across
-// API boundaries.
-//
-// Context's methods may be called by multiple goroutines simultaneously.
-type Context = context.Context
-
-// A CancelFunc tells an operation to abandon its work.
-// A CancelFunc does not wait for the work to stop.
-// After the first call, subsequent calls to a CancelFunc do nothing.
-type CancelFunc = context.CancelFunc
diff --git a/vendor/golang.org/x/net/context/pre_go17.go b/vendor/golang.org/x/net/context/pre_go17.go
deleted file mode 100644
index 0f35592d..00000000
--- a/vendor/golang.org/x/net/context/pre_go17.go
+++ /dev/null
@@ -1,300 +0,0 @@
-// Copyright 2014 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build !go1.7
-
-package context
-
-import (
-	"errors"
-	"fmt"
-	"sync"
-	"time"
-)
-
-// An emptyCtx is never canceled, has no values, and has no deadline. It is not
-// struct{}, since vars of this type must have distinct addresses.
-type emptyCtx int
-
-func (*emptyCtx) Deadline() (deadline time.Time, ok bool) {
-	return
-}
-
-func (*emptyCtx) Done() <-chan struct{} {
-	return nil
-}
-
-func (*emptyCtx) Err() error {
-	return nil
-}
-
-func (*emptyCtx) Value(key interface{}) interface{} {
-	return nil
-}
-
-func (e *emptyCtx) String() string {
-	switch e {
-	case background:
-		return "context.Background"
-	case todo:
-		return "context.TODO"
-	}
-	return "unknown empty Context"
-}
-
-var (
-	background = new(emptyCtx)
-	todo       = new(emptyCtx)
-)
-
-// Canceled is the error returned by Context.Err when the context is canceled.
-var Canceled = errors.New("context canceled")
-
-// DeadlineExceeded is the error returned by Context.Err when the context's
-// deadline passes.
-var DeadlineExceeded = errors.New("context deadline exceeded")
-
-// WithCancel returns a copy of parent with a new Done channel. The returned
-// context's Done channel is closed when the returned cancel function is called
-// or when the parent context's Done channel is closed, whichever happens first.
-//
-// Canceling this context releases resources associated with it, so code should
-// call cancel as soon as the operations running in this Context complete.
-func WithCancel(parent Context) (ctx Context, cancel CancelFunc) {
-	c := newCancelCtx(parent)
-	propagateCancel(parent, c)
-	return c, func() { c.cancel(true, Canceled) }
-}
-
-// newCancelCtx returns an initialized cancelCtx.
-func newCancelCtx(parent Context) *cancelCtx {
-	return &cancelCtx{
-		Context: parent,
-		done:    make(chan struct{}),
-	}
-}
-
-// propagateCancel arranges for child to be canceled when parent is.
-func propagateCancel(parent Context, child canceler) {
-	if parent.Done() == nil {
-		return // parent is never canceled
-	}
-	if p, ok := parentCancelCtx(parent); ok {
-		p.mu.Lock()
-		if p.err != nil {
-			// parent has already been canceled
-			child.cancel(false, p.err)
-		} else {
-			if p.children == nil {
-				p.children = make(map[canceler]bool)
-			}
-			p.children[child] = true
-		}
-		p.mu.Unlock()
-	} else {
-		go func() {
-			select {
-			case <-parent.Done():
-				child.cancel(false, parent.Err())
-			case <-child.Done():
-			}
-		}()
-	}
-}
-
-// parentCancelCtx follows a chain of parent references until it finds a
-// *cancelCtx. This function understands how each of the concrete types in this
-// package represents its parent.
-func parentCancelCtx(parent Context) (*cancelCtx, bool) {
-	for {
-		switch c := parent.(type) {
-		case *cancelCtx:
-			return c, true
-		case *timerCtx:
-			return c.cancelCtx, true
-		case *valueCtx:
-			parent = c.Context
-		default:
-			return nil, false
-		}
-	}
-}
-
-// removeChild removes a context from its parent.
-func removeChild(parent Context, child canceler) {
-	p, ok := parentCancelCtx(parent)
-	if !ok {
-		return
-	}
-	p.mu.Lock()
-	if p.children != nil {
-		delete(p.children, child)
-	}
-	p.mu.Unlock()
-}
-
-// A canceler is a context type that can be canceled directly. The
-// implementations are *cancelCtx and *timerCtx.
-type canceler interface {
-	cancel(removeFromParent bool, err error)
-	Done() <-chan struct{}
-}
-
-// A cancelCtx can be canceled. When canceled, it also cancels any children
-// that implement canceler.
-type cancelCtx struct {
-	Context
-
-	done chan struct{} // closed by the first cancel call.
-
-	mu       sync.Mutex
-	children map[canceler]bool // set to nil by the first cancel call
-	err      error             // set to non-nil by the first cancel call
-}
-
-func (c *cancelCtx) Done() <-chan struct{} {
-	return c.done
-}
-
-func (c *cancelCtx) Err() error {
-	c.mu.Lock()
-	defer c.mu.Unlock()
-	return c.err
-}
-
-func (c *cancelCtx) String() string {
-	return fmt.Sprintf("%v.WithCancel", c.Context)
-}
-
-// cancel closes c.done, cancels each of c's children, and, if
-// removeFromParent is true, removes c from its parent's children.
-func (c *cancelCtx) cancel(removeFromParent bool, err error) {
-	if err == nil {
-		panic("context: internal error: missing cancel error")
-	}
-	c.mu.Lock()
-	if c.err != nil {
-		c.mu.Unlock()
-		return // already canceled
-	}
-	c.err = err
-	close(c.done)
-	for child := range c.children {
-		// NOTE: acquiring the child's lock while holding parent's lock.
-		child.cancel(false, err)
-	}
-	c.children = nil
-	c.mu.Unlock()
-
-	if removeFromParent {
-		removeChild(c.Context, c)
-	}
-}
-
-// WithDeadline returns a copy of the parent context with the deadline adjusted
-// to be no later than d. If the parent's deadline is already earlier than d,
-// WithDeadline(parent, d) is semantically equivalent to parent. The returned
-// context's Done channel is closed when the deadline expires, when the returned
-// cancel function is called, or when the parent context's Done channel is
-// closed, whichever happens first.
-//
-// Canceling this context releases resources associated with it, so code should
-// call cancel as soon as the operations running in this Context complete.
-func WithDeadline(parent Context, deadline time.Time) (Context, CancelFunc) {
-	if cur, ok := parent.Deadline(); ok && cur.Before(deadline) {
-		// The current deadline is already sooner than the new one.
-		return WithCancel(parent)
-	}
-	c := &timerCtx{
-		cancelCtx: newCancelCtx(parent),
-		deadline:  deadline,
-	}
-	propagateCancel(parent, c)
-	d := deadline.Sub(time.Now())
-	if d <= 0 {
-		c.cancel(true, DeadlineExceeded) // deadline has already passed
-		return c, func() { c.cancel(true, Canceled) }
-	}
-	c.mu.Lock()
-	defer c.mu.Unlock()
-	if c.err == nil {
-		c.timer = time.AfterFunc(d, func() {
-			c.cancel(true, DeadlineExceeded)
-		})
-	}
-	return c, func() { c.cancel(true, Canceled) }
-}
-
-// A timerCtx carries a timer and a deadline. It embeds a cancelCtx to
-// implement Done and Err. It implements cancel by stopping its timer then
-// delegating to cancelCtx.cancel.
-type timerCtx struct {
-	*cancelCtx
-	timer *time.Timer // Under cancelCtx.mu.
-
-	deadline time.Time
-}
-
-func (c *timerCtx) Deadline() (deadline time.Time, ok bool) {
-	return c.deadline, true
-}
-
-func (c *timerCtx) String() string {
-	return fmt.Sprintf("%v.WithDeadline(%s [%s])", c.cancelCtx.Context, c.deadline, c.deadline.Sub(time.Now()))
-}
-
-func (c *timerCtx) cancel(removeFromParent bool, err error) {
-	c.cancelCtx.cancel(false, err)
-	if removeFromParent {
-		// Remove this timerCtx from its parent cancelCtx's children.
-		removeChild(c.cancelCtx.Context, c)
-	}
-	c.mu.Lock()
-	if c.timer != nil {
-		c.timer.Stop()
-		c.timer = nil
-	}
-	c.mu.Unlock()
-}
-
-// WithTimeout returns WithDeadline(parent, time.Now().Add(timeout)).
-//
-// Canceling this context releases resources associated with it, so code should
-// call cancel as soon as the operations running in this Context complete:
-//
-// 	func slowOperationWithTimeout(ctx context.Context) (Result, error) {
-// 		ctx, cancel := context.WithTimeout(ctx, 100*time.Millisecond)
-// 		defer cancel()  // releases resources if slowOperation completes before timeout elapses
-// 		return slowOperation(ctx)
-// 	}
-func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) {
-	return WithDeadline(parent, time.Now().Add(timeout))
-}
-
-// WithValue returns a copy of parent in which the value associated with key is
-// val.
-//
-// Use context Values only for request-scoped data that transits processes and
-// APIs, not for passing optional parameters to functions.
-func WithValue(parent Context, key interface{}, val interface{}) Context {
-	return &valueCtx{parent, key, val}
-}
-
-// A valueCtx carries a key-value pair. It implements Value for that key and
-// delegates all other calls to the embedded Context.
-type valueCtx struct {
-	Context
-	key, val interface{}
-}
-
-func (c *valueCtx) String() string {
-	return fmt.Sprintf("%v.WithValue(%#v, %#v)", c.Context, c.key, c.val)
-}
-
-func (c *valueCtx) Value(key interface{}) interface{} {
-	if c.key == key {
-		return c.val
-	}
-	return c.Context.Value(key)
-}
diff --git a/vendor/golang.org/x/net/context/pre_go19.go b/vendor/golang.org/x/net/context/pre_go19.go
deleted file mode 100644
index b105f80b..00000000
--- a/vendor/golang.org/x/net/context/pre_go19.go
+++ /dev/null
@@ -1,109 +0,0 @@
-// Copyright 2014 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build !go1.9
-
-package context
-
-import "time"
-
-// A Context carries a deadline, a cancelation signal, and other values across
-// API boundaries.
-//
-// Context's methods may be called by multiple goroutines simultaneously.
-type Context interface {
-	// Deadline returns the time when work done on behalf of this context
-	// should be canceled. Deadline returns ok==false when no deadline is
-	// set. Successive calls to Deadline return the same results.
-	Deadline() (deadline time.Time, ok bool)
-
-	// Done returns a channel that's closed when work done on behalf of this
-	// context should be canceled. Done may return nil if this context can
-	// never be canceled. Successive calls to Done return the same value.
-	//
-	// WithCancel arranges for Done to be closed when cancel is called;
-	// WithDeadline arranges for Done to be closed when the deadline
-	// expires; WithTimeout arranges for Done to be closed when the timeout
-	// elapses.
-	//
-	// Done is provided for use in select statements:
-	//
-	//  // Stream generates values with DoSomething and sends them to out
-	//  // until DoSomething returns an error or ctx.Done is closed.
-	//  func Stream(ctx context.Context, out chan<- Value) error {
-	//  	for {
-	//  		v, err := DoSomething(ctx)
-	//  		if err != nil {
-	//  			return err
-	//  		}
-	//  		select {
-	//  		case <-ctx.Done():
-	//  			return ctx.Err()
-	//  		case out <- v:
-	//  		}
-	//  	}
-	//  }
-	//
-	// See http://blog.golang.org/pipelines for more examples of how to use
-	// a Done channel for cancelation.
-	Done() <-chan struct{}
-
-	// Err returns a non-nil error value after Done is closed. Err returns
-	// Canceled if the context was canceled or DeadlineExceeded if the
-	// context's deadline passed. No other values for Err are defined.
-	// After Done is closed, successive calls to Err return the same value.
-	Err() error
-
-	// Value returns the value associated with this context for key, or nil
-	// if no value is associated with key. Successive calls to Value with
-	// the same key returns the same result.
-	//
-	// Use context values only for request-scoped data that transits
-	// processes and API boundaries, not for passing optional parameters to
-	// functions.
-	//
-	// A key identifies a specific value in a Context. Functions that wish
-	// to store values in Context typically allocate a key in a global
-	// variable then use that key as the argument to context.WithValue and
-	// Context.Value. A key can be any type that supports equality;
-	// packages should define keys as an unexported type to avoid
-	// collisions.
-	//
-	// Packages that define a Context key should provide type-safe accessors
-	// for the values stores using that key:
-	//
-	// 	// Package user defines a User type that's stored in Contexts.
-	// 	package user
-	//
-	// 	import "golang.org/x/net/context"
-	//
-	// 	// User is the type of value stored in the Contexts.
-	// 	type User struct {...}
-	//
-	// 	// key is an unexported type for keys defined in this package.
-	// 	// This prevents collisions with keys defined in other packages.
-	// 	type key int
-	//
-	// 	// userKey is the key for user.User values in Contexts. It is
-	// 	// unexported; clients use user.NewContext and user.FromContext
-	// 	// instead of using this key directly.
-	// 	var userKey key = 0
-	//
-	// 	// NewContext returns a new Context that carries value u.
-	// 	func NewContext(ctx context.Context, u *User) context.Context {
-	// 		return context.WithValue(ctx, userKey, u)
-	// 	}
-	//
-	// 	// FromContext returns the User value stored in ctx, if any.
-	// 	func FromContext(ctx context.Context) (*User, bool) {
-	// 		u, ok := ctx.Value(userKey).(*User)
-	// 		return u, ok
-	// 	}
-	Value(key interface{}) interface{}
-}
-
-// A CancelFunc tells an operation to abandon its work.
-// A CancelFunc does not wait for the work to stop.
-// After the first call, subsequent calls to a CancelFunc do nothing.
-type CancelFunc func()
diff --git a/vendor/golang.org/x/net/LICENSE b/vendor/golang.org/x/sync/LICENSE
similarity index 100%
rename from vendor/golang.org/x/net/LICENSE
rename to vendor/golang.org/x/sync/LICENSE
diff --git a/vendor/golang.org/x/net/PATENTS b/vendor/golang.org/x/sync/PATENTS
similarity index 100%
rename from vendor/golang.org/x/net/PATENTS
rename to vendor/golang.org/x/sync/PATENTS
diff --git a/vendor/golang.org/x/sync/singleflight/singleflight.go b/vendor/golang.org/x/sync/singleflight/singleflight.go
new file mode 100644
index 00000000..9a4f8d59
--- /dev/null
+++ b/vendor/golang.org/x/sync/singleflight/singleflight.go
@@ -0,0 +1,111 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package singleflight provides a duplicate function call suppression
+// mechanism.
+package singleflight // import "golang.org/x/sync/singleflight"
+
+import "sync"
+
+// call is an in-flight or completed singleflight.Do call
+type call struct {
+	wg sync.WaitGroup
+
+	// These fields are written once before the WaitGroup is done
+	// and are only read after the WaitGroup is done.
+	val interface{}
+	err error
+
+	// These fields are read and written with the singleflight
+	// mutex held before the WaitGroup is done, and are read but
+	// not written after the WaitGroup is done.
+	dups  int
+	chans []chan<- Result
+}
+
+// Group represents a class of work and forms a namespace in
+// which units of work can be executed with duplicate suppression.
+type Group struct {
+	mu sync.Mutex       // protects m
+	m  map[string]*call // lazily initialized
+}
+
+// Result holds the results of Do, so they can be passed
+// on a channel.
+type Result struct {
+	Val    interface{}
+	Err    error
+	Shared bool
+}
+
+// Do executes and returns the results of the given function, making
+// sure that only one execution is in-flight for a given key at a
+// time. If a duplicate comes in, the duplicate caller waits for the
+// original to complete and receives the same results.
+// The return value shared indicates whether v was given to multiple callers.
+func (g *Group) Do(key string, fn func() (interface{}, error)) (v interface{}, err error, shared bool) {
+	g.mu.Lock()
+	if g.m == nil {
+		g.m = make(map[string]*call)
+	}
+	if c, ok := g.m[key]; ok {
+		c.dups++
+		g.mu.Unlock()
+		c.wg.Wait()
+		return c.val, c.err, true
+	}
+	c := new(call)
+	c.wg.Add(1)
+	g.m[key] = c
+	g.mu.Unlock()
+
+	g.doCall(c, key, fn)
+	return c.val, c.err, c.dups > 0
+}
+
+// DoChan is like Do but returns a channel that will receive the
+// results when they are ready.
+func (g *Group) DoChan(key string, fn func() (interface{}, error)) <-chan Result {
+	ch := make(chan Result, 1)
+	g.mu.Lock()
+	if g.m == nil {
+		g.m = make(map[string]*call)
+	}
+	if c, ok := g.m[key]; ok {
+		c.dups++
+		c.chans = append(c.chans, ch)
+		g.mu.Unlock()
+		return ch
+	}
+	c := &call{chans: []chan<- Result{ch}}
+	c.wg.Add(1)
+	g.m[key] = c
+	g.mu.Unlock()
+
+	go g.doCall(c, key, fn)
+
+	return ch
+}
+
+// doCall handles the single call for a key.
+func (g *Group) doCall(c *call, key string, fn func() (interface{}, error)) {
+	c.val, c.err = fn()
+	c.wg.Done()
+
+	g.mu.Lock()
+	delete(g.m, key)
+	for _, ch := range c.chans {
+		ch <- Result{c.val, c.err, c.dups > 0}
+	}
+	g.mu.Unlock()
+}
+
+// Forget tells the singleflight to forget about a key.  Future calls
+// to Do for this key will call the function rather than waiting for
+// an earlier call to complete.
+func (g *Group) Forget(key string) {
+	g.mu.Lock()
+	delete(g.m, key)
+	g.mu.Unlock()
+}
diff --git a/vendor/vendor.json b/vendor/vendor.json
index 928b89d3..a75080ac 100644
--- a/vendor/vendor.json
+++ b/vendor/vendor.json
@@ -74,6 +74,12 @@
 			"revision": "1e59b77b52bf8e4b449a57e6f79f21226d571845",
 			"revisionTime": "2017-11-13T18:07:20Z"
 		},
+		{
+			"checksumSHA1": "t1nayUUugNoJWht7p4cbKyWuk8Q=",
+			"path": "github.com/gorilla/handlers",
+			"revision": "90663712d74cb411cbef281bc1e08c19d1a76145",
+			"revisionTime": "2017-11-01T17:43:35Z"
+		},
 		{
 			"checksumSHA1": "D5EG5yMsbtHqKbzBVbxFMKEMDNY=",
 			"path": "github.com/lunixbochs/struc",
@@ -167,52 +173,38 @@
 		{
 			"checksumSHA1": "FwW3Vv4jW0Nv7V2SZC7x/Huj5M4=",
 			"path": "golang.org/x/crypto/argon2",
-			"revision": "a49355c7e3f8fe157a85be2f77e6e269a0f89602",
-			"revisionTime": "2018-06-20T09:14:27Z"
+			"revision": "aabede6cba87e37f413b3e60ebfc214f8eeca1b0",
+			"revisionTime": "2018-08-16T21:30:07Z"
 		},
 		{
 			"checksumSHA1": "ejjxT0+wDWWncfh0Rt3lSH4IbXQ=",
 			"path": "golang.org/x/crypto/blake2b",
-			"revision": "a49355c7e3f8fe157a85be2f77e6e269a0f89602",
-			"revisionTime": "2018-06-20T09:14:27Z"
+			"revision": "aabede6cba87e37f413b3e60ebfc214f8eeca1b0",
+			"revisionTime": "2018-08-16T21:30:07Z"
 		},
 		{
-			"checksumSHA1": "X6Q8nYb+KXh+64AKHwWOOcyijHQ=",
-			"origin": "git.autistici.org/id/go-sso/vendor/golang.org/x/crypto/ed25519",
+			"checksumSHA1": "2LpxYGSf068307b7bhAuVjvzLLc=",
 			"path": "golang.org/x/crypto/ed25519",
-			"revision": "dc62a1d65832c8a3f73e7a0cffb78ad0b4d3d8fc",
-			"revisionTime": "2018-02-18T15:46:43Z"
+			"revision": "aabede6cba87e37f413b3e60ebfc214f8eeca1b0",
+			"revisionTime": "2018-08-16T21:30:07Z"
 		},
 		{
-			"checksumSHA1": "LXFcVx8I587SnWmKycSDEq9yvK8=",
-			"origin": "git.autistici.org/id/go-sso/vendor/golang.org/x/crypto/ed25519/internal/edwards25519",
+			"checksumSHA1": "0JTAFXPkankmWcZGQJGScLDiaN8=",
 			"path": "golang.org/x/crypto/ed25519/internal/edwards25519",
-			"revision": "dc62a1d65832c8a3f73e7a0cffb78ad0b4d3d8fc",
-			"revisionTime": "2018-02-18T15:46:43Z"
-		},
-		{
-			"checksumSHA1": "1MGpGDQqnUoRpv7VEcQrXOBydXE=",
-			"path": "golang.org/x/crypto/pbkdf2",
-			"revision": "a49355c7e3f8fe157a85be2f77e6e269a0f89602",
-			"revisionTime": "2018-06-20T09:14:27Z"
-		},
-		{
-			"checksumSHA1": "sx1nQShs40UKtcJZNJuvYtGesaI=",
-			"path": "golang.org/x/crypto/scrypt",
-			"revision": "a49355c7e3f8fe157a85be2f77e6e269a0f89602",
-			"revisionTime": "2018-06-20T09:14:27Z"
+			"revision": "aabede6cba87e37f413b3e60ebfc214f8eeca1b0",
+			"revisionTime": "2018-08-16T21:30:07Z"
 		},
 		{
-			"checksumSHA1": "GtamqiJoL7PGHsN454AoffBFMa8=",
-			"path": "golang.org/x/net/context",
-			"revision": "c39426892332e1bb5ec0a434a079bf82f5d30c54",
-			"revisionTime": "2018-07-15T06:54:04Z"
+			"checksumSHA1": "VhUZFUuhLFSBFUfskMC4am5RIdc=",
+			"path": "golang.org/x/sync/singleflight",
+			"revision": "1d60e4601c6fd243af51cc01ddf169918a5407ca",
+			"revisionTime": "2018-03-14T17:21:19Z"
 		},
 		{
 			"checksumSHA1": "REkmyB368pIiip76LiqMLspgCRk=",
 			"path": "golang.org/x/sys/cpu",
-			"revision": "7138fd3d9dc8335c567ca206f4333fb75eb05d56",
-			"revisionTime": "2018-06-27T13:57:12Z"
+			"revision": "1c9583448a9c3aa0f9a6a5241bf73c0bd8aafded",
+			"revisionTime": "2018-08-15T07:37:39Z"
 		},
 		{
 			"checksumSHA1": "xsaHqy6/sonLV6xIxTNh4FfkWbU=",
-- 
GitLab