diff --git a/signature-jwt.go b/signature-jwt.go
index fc4ecce41..5a7b82f20 100644
--- a/signature-jwt.go
+++ b/signature-jwt.go
@@ -64,11 +64,13 @@ func (jwt *JWT) GenerateToken(accessKey string) (string, error) {
return "", fmt.Errorf("Invalid access key")
}
- token := jwtgo.New(jwtgo.SigningMethodHS512)
- // Token expires in 10hrs.
- token.Claims["exp"] = time.Now().Add(time.Hour * tokenExpires).Unix()
- token.Claims["iat"] = time.Now().Unix()
- token.Claims["sub"] = accessKey
+ tUTCNow := time.Now().UTC()
+ token := jwtgo.NewWithClaims(jwtgo.SigningMethodHS512, jwtgo.MapClaims{
+ // Token expires in 10hrs.
+ "exp": tUTCNow.Add(time.Hour * tokenExpires).Unix(),
+ "iat": tUTCNow.Unix(),
+ "sub": accessKey,
+ })
return token.SignedString([]byte(jwt.SecretAccessKey))
}
diff --git a/vendor/github.com/Sirupsen/logrus/CHANGELOG.md b/vendor/github.com/Sirupsen/logrus/CHANGELOG.md
index 78f98959b..f2c2bc211 100644
--- a/vendor/github.com/Sirupsen/logrus/CHANGELOG.md
+++ b/vendor/github.com/Sirupsen/logrus/CHANGELOG.md
@@ -1,3 +1,22 @@
+# 0.10.0
+
+* feature: Add a test hook (#180)
+* feature: `ParseLevel` is now case-insensitive (#326)
+* feature: `FieldLogger` interface that generalizes `Logger` and `Entry` (#308)
+* performance: avoid re-allocations on `WithFields` (#335)
+
+# 0.9.0
+
+* logrus/text_formatter: don't emit empty msg
+* logrus/hooks/airbrake: move out of main repository
+* logrus/hooks/sentry: move out of main repository
+* logrus/hooks/papertrail: move out of main repository
+* logrus/hooks/bugsnag: move out of main repository
+* logrus/core: run tests with `-race`
+* logrus/core: detect TTY based on `stderr`
+* logrus/core: support `WithError` on logger
+* logrus/core: Solaris support
+
# 0.8.7
* logrus/core: fix possible race (#216)
diff --git a/vendor/github.com/Sirupsen/logrus/README.md b/vendor/github.com/Sirupsen/logrus/README.md
index 6fa6e2062..ee8bd12be 100644
--- a/vendor/github.com/Sirupsen/logrus/README.md
+++ b/vendor/github.com/Sirupsen/logrus/README.md
@@ -1,4 +1,4 @@
-# Logrus [![Build Status](https://travis-ci.org/Sirupsen/logrus.svg?branch=master)](https://travis-ci.org/Sirupsen/logrus) [![godoc reference](https://godoc.org/github.com/Sirupsen/logrus?status.png)][godoc]
+# Logrus [![Build Status](https://travis-ci.org/Sirupsen/logrus.svg?branch=master)](https://travis-ci.org/Sirupsen/logrus) [![GoDoc](https://godoc.org/github.com/Sirupsen/logrus?status.svg)](https://godoc.org/github.com/Sirupsen/logrus)
Logrus is a structured logger for Go (golang), completely API compatible with
the standard library logger. [Godoc][godoc]. **Please note the Logrus API is not
@@ -12,7 +12,7 @@ plain text):
![Colored](http://i.imgur.com/PY7qMwd.png)
-With `log.Formatter = new(logrus.JSONFormatter)`, for easy parsing by logstash
+With `log.SetFormatter(&log.JSONFormatter{})`, for easy parsing by logstash
or Splunk:
```json
@@ -32,7 +32,7 @@ ocean","size":10,"time":"2014-03-10 19:57:38.562264131 -0400 EDT"}
"time":"2014-03-10 19:57:38.562543128 -0400 EDT"}
```
-With the default `log.Formatter = new(&log.TextFormatter{})` when a TTY is not
+With the default `log.SetFormatter(&log.TextFormatter{})` when a TTY is not
attached, the output is compatible with the
[logfmt](http://godoc.org/github.com/kr/logfmt) format:
@@ -75,17 +75,12 @@ package main
import (
"os"
log "github.com/Sirupsen/logrus"
- "github.com/Sirupsen/logrus/hooks/airbrake"
)
func init() {
// Log as JSON instead of the default ASCII formatter.
log.SetFormatter(&log.JSONFormatter{})
- // Use the Airbrake hook to report errors that have Error severity or above to
- // an exception tracker. You can create custom hooks, see the Hooks section.
- log.AddHook(airbrake.NewHook("https://example.com", "xyz", "development"))
-
// Output to stderr instead of stdout, could also be a file.
log.SetOutput(os.Stderr)
@@ -182,13 +177,16 @@ Logrus comes with [built-in hooks](hooks/). Add those, or your custom hook, in
```go
import (
log "github.com/Sirupsen/logrus"
- "github.com/Sirupsen/logrus/hooks/airbrake"
+ "gopkg.in/gemnasium/logrus-airbrake-hook.v2" // the package is named "aibrake"
logrus_syslog "github.com/Sirupsen/logrus/hooks/syslog"
"log/syslog"
)
func init() {
- log.AddHook(airbrake.NewHook("https://example.com", "xyz", "development"))
+
+ // Use the Airbrake hook to report errors that have Error severity or above to
+ // an exception tracker. You can create custom hooks, see the Hooks section.
+ log.AddHook(airbrake.NewHook(123, "xyz", "production"))
hook, err := logrus_syslog.NewSyslogHook("udp", "localhost:514", syslog.LOG_INFO, "")
if err != nil {
@@ -198,20 +196,21 @@ func init() {
}
}
```
-
+Note: Syslog hook also support connecting to local syslog (Ex. "/dev/log" or "/var/run/syslog" or "/var/run/log"). For the detail, please check the [syslog hook README](hooks/syslog/README.md).
| Hook | Description |
| ----- | ----------- |
-| [Airbrake](https://github.com/Sirupsen/logrus/blob/master/hooks/airbrake/airbrake.go) | Send errors to an exception tracking service compatible with the Airbrake API. Uses [`airbrake-go`](https://github.com/tobi/airbrake-go) behind the scenes. |
-| [Papertrail](https://github.com/Sirupsen/logrus/blob/master/hooks/papertrail/papertrail.go) | Send errors to the Papertrail hosted logging service via UDP. |
+| [Airbrake](https://github.com/gemnasium/logrus-airbrake-hook) | Send errors to the Airbrake API V3. Uses the official [`gobrake`](https://github.com/airbrake/gobrake) behind the scenes. |
+| [Airbrake "legacy"](https://github.com/gemnasium/logrus-airbrake-legacy-hook) | Send errors to an exception tracking service compatible with the Airbrake API V2. Uses [`airbrake-go`](https://github.com/tobi/airbrake-go) behind the scenes. |
+| [Papertrail](https://github.com/polds/logrus-papertrail-hook) | Send errors to the [Papertrail](https://papertrailapp.com) hosted logging service via UDP. |
| [Syslog](https://github.com/Sirupsen/logrus/blob/master/hooks/syslog/syslog.go) | Send errors to remote syslog server. Uses standard library `log/syslog` behind the scenes. |
-| [BugSnag](https://github.com/Sirupsen/logrus/blob/master/hooks/bugsnag/bugsnag.go) | Send errors to the Bugsnag exception tracking service. |
-| [Sentry](https://github.com/Sirupsen/logrus/blob/master/hooks/sentry/sentry.go) | Send errors to the Sentry error logging and aggregation service. |
+| [Bugsnag](https://github.com/Shopify/logrus-bugsnag/blob/master/bugsnag.go) | Send errors to the Bugsnag exception tracking service. |
+| [Sentry](https://github.com/evalphobia/logrus_sentry) | Send errors to the Sentry error logging and aggregation service. |
| [Hiprus](https://github.com/nubo/hiprus) | Send errors to a channel in hipchat. |
| [Logrusly](https://github.com/sebest/logrusly) | Send logs to [Loggly](https://www.loggly.com/) |
| [Slackrus](https://github.com/johntdyer/slackrus) | Hook for Slack chat. |
| [Journalhook](https://github.com/wercker/journalhook) | Hook for logging to `systemd-journald` |
-| [Graylog](https://github.com/gemnasium/logrus-hooks/tree/master/graylog) | Hook for logging to [Graylog](http://graylog2.org/) |
+| [Graylog](https://github.com/gemnasium/logrus-graylog-hook) | Hook for logging to [Graylog](http://graylog2.org/) |
| [Raygun](https://github.com/squirkle/logrus-raygun-hook) | Hook for logging to [Raygun.io](http://raygun.io/) |
| [LFShook](https://github.com/rifflock/lfshook) | Hook for logging to the local filesystem |
| [Honeybadger](https://github.com/agonzalezro/logrus_honeybadger) | Hook for sending exceptions to Honeybadger |
@@ -219,6 +218,17 @@ func init() {
| [Rollrus](https://github.com/heroku/rollrus) | Hook for sending errors to rollbar |
| [Fluentd](https://github.com/evalphobia/logrus_fluent) | Hook for logging to fluentd |
| [Mongodb](https://github.com/weekface/mgorus) | Hook for logging to mongodb |
+| [Influxus] (http://github.com/vlad-doru/influxus) | Hook for concurrently logging to [InfluxDB] (http://influxdata.com/) |
+| [InfluxDB](https://github.com/Abramovic/logrus_influxdb) | Hook for logging to influxdb |
+| [Octokit](https://github.com/dorajistyle/logrus-octokit-hook) | Hook for logging to github via octokit |
+| [DeferPanic](https://github.com/deferpanic/dp-logrus) | Hook for logging to DeferPanic |
+| [Redis-Hook](https://github.com/rogierlommers/logrus-redis-hook) | Hook for logging to a ELK stack (through Redis) |
+| [Amqp-Hook](https://github.com/vladoatanasov/logrus_amqp) | Hook for logging to Amqp broker (Like RabbitMQ) |
+| [KafkaLogrus](https://github.com/goibibo/KafkaLogrus) | Hook for logging to kafka |
+| [Typetalk](https://github.com/dragon3/logrus-typetalk-hook) | Hook for logging to [Typetalk](https://www.typetalk.in/) |
+| [ElasticSearch](https://github.com/sohlich/elogrus) | Hook for logging to ElasticSearch|
+| [Sumorus](https://github.com/doublefree/sumorus) | Hook for logging to [SumoLogic](https://www.sumologic.com/)|
+| [Logstash](https://github.com/bshuster-repo/logrus-logstash-hook) | Hook for logging to [Logstash](https://www.elastic.co/products/logstash) |
#### Level logging
@@ -296,15 +306,12 @@ The built-in logging formatters are:
field to `true`. To force no colored output even if there is a TTY set the
`DisableColors` field to `true`
* `logrus.JSONFormatter`. Logs fields as JSON.
-* `logrus_logstash.LogstashFormatter`. Logs fields as Logstash Events (http://logstash.net).
-
- ```go
- logrus.SetFormatter(&logrus_logstash.LogstashFormatter{Type: “application_name"})
- ```
Third party logging formatters:
-* [`zalgo`](https://github.com/aybabtme/logzalgo): invoking the P͉̫o̳̼̊w̖͈̰͎e̬͔̭͂r͚̼̹̲ ̫͓͉̳͈ō̠͕͖̚f̝͍̠ ͕̲̞͖͑Z̖̫̤̫ͪa͉̬͈̗l͖͎g̳̥o̰̥̅!̣͔̲̻͊̄ ̙̘̦̹̦.
+* [`logstash`](https://github.com/bshuster-repo/logrus-logstash-hook). Logs fields as [Logstash](http://logstash.net) Events.
+* [`prefixed`](https://github.com/x-cray/logrus-prefixed-formatter). Displays log entry source along with alternative layout.
+* [`zalgo`](https://github.com/aybabtme/logzalgo). Invoking the P͉̫o̳̼̊w̖͈̰͎e̬͔̭͂r͚̼̹̲ ̫͓͉̳͈ō̠͕͖̚f̝͍̠ ͕̲̞͖͑Z̖̫̤̫ͪa͉̬͈̗l͖͎g̳̥o̰̥̅!̣͔̲̻͊̄ ̙̘̦̹̦.
You can define your formatter by implementing the `Formatter` interface,
requiring a `Format` method. `Format` takes an `*Entry`. `entry.Data` is a
@@ -353,5 +360,27 @@ Log rotation is not provided with Logrus. Log rotation should be done by an
external program (like `logrotate(8)`) that can compress and delete old log
entries. It should not be a feature of the application-level logger.
+#### Tools
-[godoc]: https://godoc.org/github.com/Sirupsen/logrus
+| Tool | Description |
+| ---- | ----------- |
+|[Logrus Mate](https://github.com/gogap/logrus_mate)|Logrus mate is a tool for Logrus to manage loggers, you can initial logger's level, hook and formatter by config file, the logger will generated with different config at different environment.|
+
+#### Testing
+
+Logrus has a built in facility for asserting the presence of log messages. This is implemented through the `test` hook and provides:
+
+* decorators for existing logger (`test.NewLocal` and `test.NewGlobal`) which basically just add the `test` hook
+* a test logger (`test.NewNullLogger`) that just records log messages (and does not output any):
+
+```go
+logger, hook := NewNullLogger()
+logger.Error("Hello error")
+
+assert.Equal(1, len(hook.Entries))
+assert.Equal(logrus.ErrorLevel, hook.LastEntry().Level)
+assert.Equal("Hello error", hook.LastEntry().Message)
+
+hook.Reset()
+assert.Nil(hook.LastEntry())
+```
diff --git a/vendor/github.com/Sirupsen/logrus/entry.go b/vendor/github.com/Sirupsen/logrus/entry.go
index 9ae900bc5..89e966e7b 100644
--- a/vendor/github.com/Sirupsen/logrus/entry.go
+++ b/vendor/github.com/Sirupsen/logrus/entry.go
@@ -68,7 +68,7 @@ func (entry *Entry) WithField(key string, value interface{}) *Entry {
// Add a map of fields to the Entry.
func (entry *Entry) WithFields(fields Fields) *Entry {
- data := Fields{}
+ data := make(Fields, len(entry.Data)+len(fields))
for k, v := range entry.Data {
data[k] = v
}
diff --git a/vendor/github.com/Sirupsen/logrus/formatter.go b/vendor/github.com/Sirupsen/logrus/formatter.go
index 104d689f1..b5fbe934d 100644
--- a/vendor/github.com/Sirupsen/logrus/formatter.go
+++ b/vendor/github.com/Sirupsen/logrus/formatter.go
@@ -31,18 +31,15 @@ type Formatter interface {
// It's not exported because it's still using Data in an opinionated way. It's to
// avoid code duplication between the two default formatters.
func prefixFieldClashes(data Fields) {
- _, ok := data["time"]
- if ok {
- data["fields.time"] = data["time"]
+ if t, ok := data["time"]; ok {
+ data["fields.time"] = t
}
- _, ok = data["msg"]
- if ok {
- data["fields.msg"] = data["msg"]
+ if m, ok := data["msg"]; ok {
+ data["fields.msg"] = m
}
- _, ok = data["level"]
- if ok {
- data["fields.level"] = data["level"]
+ if l, ok := data["level"]; ok {
+ data["fields.level"] = l
}
}
diff --git a/vendor/github.com/Sirupsen/logrus/logger.go b/vendor/github.com/Sirupsen/logrus/logger.go
index fd9804c64..2fdb23176 100644
--- a/vendor/github.com/Sirupsen/logrus/logger.go
+++ b/vendor/github.com/Sirupsen/logrus/logger.go
@@ -64,6 +64,12 @@ func (logger *Logger) WithFields(fields Fields) *Entry {
return NewEntry(logger).WithFields(fields)
}
+// Add an error as single field to the log entry. All it does is call
+// `WithError` for the given `error`.
+func (logger *Logger) WithError(err error) *Entry {
+ return NewEntry(logger).WithError(err)
+}
+
func (logger *Logger) Debugf(format string, args ...interface{}) {
if logger.Level >= DebugLevel {
NewEntry(logger).Debugf(format, args...)
diff --git a/vendor/github.com/Sirupsen/logrus/logrus.go b/vendor/github.com/Sirupsen/logrus/logrus.go
index 0c09fbc26..e59669111 100644
--- a/vendor/github.com/Sirupsen/logrus/logrus.go
+++ b/vendor/github.com/Sirupsen/logrus/logrus.go
@@ -3,6 +3,7 @@ package logrus
import (
"fmt"
"log"
+ "strings"
)
// Fields type, used to pass to `WithFields`.
@@ -33,7 +34,7 @@ func (level Level) String() string {
// ParseLevel takes a string level and returns the Logrus log level constant.
func ParseLevel(lvl string) (Level, error) {
- switch lvl {
+ switch strings.ToLower(lvl) {
case "panic":
return PanicLevel, nil
case "fatal":
@@ -52,6 +53,16 @@ func ParseLevel(lvl string) (Level, error) {
return l, fmt.Errorf("not a valid logrus Level: %q", lvl)
}
+// A constant exposing all logging levels
+var AllLevels = []Level{
+ PanicLevel,
+ FatalLevel,
+ ErrorLevel,
+ WarnLevel,
+ InfoLevel,
+ DebugLevel,
+}
+
// These are the different logging levels. You can set the logging level to log
// on your instance of logger, obtained with `logrus.New()`.
const (
@@ -96,3 +107,37 @@ type StdLogger interface {
Panicf(string, ...interface{})
Panicln(...interface{})
}
+
+// The FieldLogger interface generalizes the Entry and Logger types
+type FieldLogger interface {
+ WithField(key string, value interface{}) *Entry
+ WithFields(fields Fields) *Entry
+ WithError(err error) *Entry
+
+ Debugf(format string, args ...interface{})
+ Infof(format string, args ...interface{})
+ Printf(format string, args ...interface{})
+ Warnf(format string, args ...interface{})
+ Warningf(format string, args ...interface{})
+ Errorf(format string, args ...interface{})
+ Fatalf(format string, args ...interface{})
+ Panicf(format string, args ...interface{})
+
+ Debug(args ...interface{})
+ Info(args ...interface{})
+ Print(args ...interface{})
+ Warn(args ...interface{})
+ Warning(args ...interface{})
+ Error(args ...interface{})
+ Fatal(args ...interface{})
+ Panic(args ...interface{})
+
+ Debugln(args ...interface{})
+ Infoln(args ...interface{})
+ Println(args ...interface{})
+ Warnln(args ...interface{})
+ Warningln(args ...interface{})
+ Errorln(args ...interface{})
+ Fatalln(args ...interface{})
+ Panicln(args ...interface{})
+}
diff --git a/vendor/github.com/Sirupsen/logrus/terminal_notwindows.go b/vendor/github.com/Sirupsen/logrus/terminal_notwindows.go
index 4bb537602..b343b3a37 100644
--- a/vendor/github.com/Sirupsen/logrus/terminal_notwindows.go
+++ b/vendor/github.com/Sirupsen/logrus/terminal_notwindows.go
@@ -12,9 +12,9 @@ import (
"unsafe"
)
-// IsTerminal returns true if the given file descriptor is a terminal.
+// IsTerminal returns true if stderr's file descriptor is a terminal.
func IsTerminal() bool {
- fd := syscall.Stdout
+ fd := syscall.Stderr
var termios Termios
_, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlReadTermios, uintptr(unsafe.Pointer(&termios)), 0, 0, 0)
return err == 0
diff --git a/vendor/github.com/Sirupsen/logrus/terminal_solaris.go b/vendor/github.com/Sirupsen/logrus/terminal_solaris.go
new file mode 100644
index 000000000..3e70bf7bf
--- /dev/null
+++ b/vendor/github.com/Sirupsen/logrus/terminal_solaris.go
@@ -0,0 +1,15 @@
+// +build solaris
+
+package logrus
+
+import (
+ "os"
+
+ "golang.org/x/sys/unix"
+)
+
+// IsTerminal returns true if the given file descriptor is a terminal.
+func IsTerminal() bool {
+ _, err := unix.IoctlGetTermios(int(os.Stdout.Fd()), unix.TCGETA)
+ return err == nil
+}
diff --git a/vendor/github.com/Sirupsen/logrus/terminal_windows.go b/vendor/github.com/Sirupsen/logrus/terminal_windows.go
index 2e09f6f7e..0146845d1 100644
--- a/vendor/github.com/Sirupsen/logrus/terminal_windows.go
+++ b/vendor/github.com/Sirupsen/logrus/terminal_windows.go
@@ -18,9 +18,9 @@ var (
procGetConsoleMode = kernel32.NewProc("GetConsoleMode")
)
-// IsTerminal returns true if the given file descriptor is a terminal.
+// IsTerminal returns true if stderr's file descriptor is a terminal.
func IsTerminal() bool {
- fd := syscall.Stdout
+ fd := syscall.Stderr
var st uint32
r, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, uintptr(fd), uintptr(unsafe.Pointer(&st)), 0)
return r != 0 && e == 0
diff --git a/vendor/github.com/Sirupsen/logrus/text_formatter.go b/vendor/github.com/Sirupsen/logrus/text_formatter.go
index 17cc29848..6afd0e031 100644
--- a/vendor/github.com/Sirupsen/logrus/text_formatter.go
+++ b/vendor/github.com/Sirupsen/logrus/text_formatter.go
@@ -84,7 +84,9 @@ func (f *TextFormatter) Format(entry *Entry) ([]byte, error) {
f.appendKeyValue(b, "time", entry.Time.Format(timestampFormat))
}
f.appendKeyValue(b, "level", entry.Level.String())
- f.appendKeyValue(b, "msg", entry.Message)
+ if entry.Message != "" {
+ f.appendKeyValue(b, "msg", entry.Message)
+ }
for _, key := range keys {
f.appendKeyValue(b, key, entry.Data[key])
}
@@ -126,10 +128,10 @@ func needsQuoting(text string) bool {
(ch >= 'A' && ch <= 'Z') ||
(ch >= '0' && ch <= '9') ||
ch == '-' || ch == '.') {
- return false
+ return true
}
}
- return true
+ return false
}
func (f *TextFormatter) appendKeyValue(b *bytes.Buffer, key string, value interface{}) {
@@ -139,14 +141,14 @@ func (f *TextFormatter) appendKeyValue(b *bytes.Buffer, key string, value interf
switch value := value.(type) {
case string:
- if needsQuoting(value) {
+ if !needsQuoting(value) {
b.WriteString(value)
} else {
fmt.Fprintf(b, "%q", value)
}
case error:
errmsg := value.Error()
- if needsQuoting(errmsg) {
+ if !needsQuoting(errmsg) {
b.WriteString(errmsg)
} else {
fmt.Fprintf(b, "%q", value)
diff --git a/vendor/github.com/Sirupsen/logrus/writer.go b/vendor/github.com/Sirupsen/logrus/writer.go
index 1e30b1c75..f74d2aa5f 100644
--- a/vendor/github.com/Sirupsen/logrus/writer.go
+++ b/vendor/github.com/Sirupsen/logrus/writer.go
@@ -7,18 +7,40 @@ import (
)
func (logger *Logger) Writer() *io.PipeWriter {
+ return logger.WriterLevel(InfoLevel)
+}
+
+func (logger *Logger) WriterLevel(level Level) *io.PipeWriter {
reader, writer := io.Pipe()
- go logger.writerScanner(reader)
+ var printFunc func(args ...interface{})
+ switch level {
+ case DebugLevel:
+ printFunc = logger.Debug
+ case InfoLevel:
+ printFunc = logger.Info
+ case WarnLevel:
+ printFunc = logger.Warn
+ case ErrorLevel:
+ printFunc = logger.Error
+ case FatalLevel:
+ printFunc = logger.Fatal
+ case PanicLevel:
+ printFunc = logger.Panic
+ default:
+ printFunc = logger.Print
+ }
+
+ go logger.writerScanner(reader, printFunc)
runtime.SetFinalizer(writer, writerFinalizer)
return writer
}
-func (logger *Logger) writerScanner(reader *io.PipeReader) {
+func (logger *Logger) writerScanner(reader *io.PipeReader, printFunc func(args ...interface{})) {
scanner := bufio.NewScanner(reader)
for scanner.Scan() {
- logger.Print(scanner.Text())
+ printFunc(scanner.Text())
}
if err := scanner.Err(); err != nil {
logger.Errorf("Error while reading from Writer: %s", err)
diff --git a/vendor/github.com/cheggaaa/pb/pb.go b/vendor/github.com/cheggaaa/pb/pb.go
index 97e7b9931..a5b0b40f4 100644
--- a/vendor/github.com/cheggaaa/pb/pb.go
+++ b/vendor/github.com/cheggaaa/pb/pb.go
@@ -13,7 +13,7 @@ import (
)
// Current version
-const Version = "1.0.2"
+const Version = "1.0.4"
const (
// Default refresh rate - 200ms
@@ -81,6 +81,7 @@ type ProgressBar struct {
Width int
ForceWidth bool
ManualUpdate bool
+ AutoStat bool
// Default width for the time box.
UnitsWidth int
@@ -115,6 +116,7 @@ func (pb *ProgressBar) Start() *ProgressBar {
if pb.Total == 0 {
pb.ShowTimeLeft = false
pb.ShowPercent = false
+ pb.AutoStat = false
}
if !pb.ManualUpdate {
pb.Update() // Initial printing of the bar before running the bar refresher.
@@ -128,6 +130,12 @@ func (pb *ProgressBar) Increment() int {
return pb.Add(1)
}
+// Get current value
+func (pb *ProgressBar) Get() int64 {
+ c := atomic.LoadInt64(&pb.current)
+ return c
+}
+
// Set current value
func (pb *ProgressBar) Set(current int) *ProgressBar {
return pb.Set64(int64(current))
@@ -242,6 +250,7 @@ func (pb *ProgressBar) Read(p []byte) (n int, err error) {
}
// Create new proxy reader over bar
+// Takes io.Reader or io.ReadCloser
func (pb *ProgressBar) NewProxyReader(r io.Reader) *Reader {
return &Reader{r, pb}
}
@@ -398,6 +407,14 @@ func (pb *ProgressBar) Update() {
pb.write(c)
pb.currentValue = c
}
+ if pb.AutoStat {
+ if c == 0 {
+ pb.startTime = time.Now()
+ pb.startValue = 0
+ } else if c >= pb.Total && pb.isFinish != true {
+ pb.Finish()
+ }
+ }
}
func (pb *ProgressBar) String() string {
diff --git a/vendor/github.com/cheggaaa/pb/reader.go b/vendor/github.com/cheggaaa/pb/reader.go
index 2d01125ca..9f3148b54 100644
--- a/vendor/github.com/cheggaaa/pb/reader.go
+++ b/vendor/github.com/cheggaaa/pb/reader.go
@@ -15,3 +15,11 @@ func (r *Reader) Read(p []byte) (n int, err error) {
r.bar.Add(n)
return
}
+
+// Close the reader when it implements io.Closer
+func (r *Reader) Close() (err error) {
+ if closer, ok := r.Reader.(io.Closer); ok {
+ return closer.Close()
+ }
+ return
+}
diff --git a/vendor/github.com/dgrijalva/jwt-go/MIGRATION_GUIDE.md b/vendor/github.com/dgrijalva/jwt-go/MIGRATION_GUIDE.md
new file mode 100644
index 000000000..fd62e9490
--- /dev/null
+++ b/vendor/github.com/dgrijalva/jwt-go/MIGRATION_GUIDE.md
@@ -0,0 +1,96 @@
+## Migration Guide from v2 -> v3
+
+Version 3 adds several new, frequently requested features. To do so, it introduces a few breaking changes. We've worked to keep these as minimal as possible. This guide explains the breaking changes and how you can quickly update your code.
+
+### `Token.Claims` is now an interface type
+
+The most requested feature from the 2.0 verison of this library was the ability to provide a custom type to the JSON parser for claims. This was implemented by introducing a new interface, `Claims`, to replace `map[string]interface{}`. We also included two concrete implementations of `Claims`: `MapClaims` and `StandardClaims`.
+
+`MapClaims` is an alias for `map[string]interface{}` with built in validation behavior. It is the default claims type when using `Parse`. The usage is unchanged except you must type cast the claims property.
+
+The old example for parsing a token looked like this..
+
+```go
+ if token, err := jwt.Parse(tokenString, keyLookupFunc); err == nil {
+ fmt.Printf("Token for user %v expires %v", token.Claims["user"], token.Claims["exp"])
+ }
+```
+
+is now directly mapped to...
+
+```go
+ if token, err := jwt.Parse(tokenString, keyLookupFunc); err == nil {
+ claims := token.Claims.(jwt.MapClaims)
+ fmt.Printf("Token for user %v expires %v", claims["user"], claims["exp"])
+ }
+```
+
+`StandardClaims` is designed to be embedded in your custom type. You can supply a custom claims type with the new `ParseWithClaims` function. Here's an example of using a custom claims type.
+
+```go
+ type MyCustomClaims struct {
+ User string
+ *StandardClaims
+ }
+
+ if token, err := jwt.ParseWithClaims(tokenString, &MyCustomClaims{}, keyLookupFunc); err == nil {
+ claims := token.Claims.(*MyCustomClaims)
+ fmt.Printf("Token for user %v expires %v", claims.User, claims.StandardClaims.ExpiresAt)
+ }
+```
+
+### `ParseFromRequest` has been moved
+
+To keep this library focused on the tokens without becoming overburdened with complex request processing logic, `ParseFromRequest` and its new companion `ParseFromRequestWithClaims` have been moved to a subpackage, `request`. The method signatues have also been augmented to receive a new argument: `Extractor`.
+
+`Extractors` do the work of picking the token string out of a request. The interface is simple and composable.
+
+This simple parsing example:
+
+```go
+ if token, err := jwt.ParseFromRequest(tokenString, req, keyLookupFunc); err == nil {
+ fmt.Printf("Token for user %v expires %v", token.Claims["user"], token.Claims["exp"])
+ }
+```
+
+is directly mapped to:
+
+```go
+ if token, err := request.ParseFromRequest(tokenString, request.OAuth2Extractor, req, keyLookupFunc); err == nil {
+ fmt.Printf("Token for user %v expires %v", token.Claims["user"], token.Claims["exp"])
+ }
+```
+
+There are several concrete `Extractor` types provided for your convenience:
+
+* `HeaderExtractor` will search a list of headers until one contains content.
+* `ArgumentExtractor` will search a list of keys in request query and form arguments until one contains content.
+* `MultiExtractor` will try a list of `Extractors` in order until one returns content.
+* `AuthorizationHeaderExtractor` will look in the `Authorization` header for a `Bearer` token.
+* `OAuth2Extractor` searches the places an OAuth2 token would be specified (per the spec): `Authorization` header and `access_token` argument
+* `PostExtractionFilter` wraps an `Extractor`, allowing you to process the content before it's parsed. A simple example is stripping the `Bearer ` text from a header
+
+
+### RSA signing methods no longer accept `[]byte` keys
+
+Due to a [critical vulnerability](https://auth0.com/blog/2015/03/31/critical-vulnerabilities-in-json-web-token-libraries/), we've decided the convenience of accepting `[]byte` instead of `rsa.PublicKey` or `rsa.PrivateKey` isn't worth the risk of misuse.
+
+To replace this behavior, we've added two helper methods: `ParseRSAPrivateKeyFromPEM(key []byte) (*rsa.PrivateKey, error)` and `ParseRSAPublicKeyFromPEM(key []byte) (*rsa.PublicKey, error)`. These are just simple helpers for unpacking PEM encoded PKCS1 and PKCS8 keys. If your keys are encoded any other way, all you need to do is convert them to the `crypto/rsa` package's types.
+
+```go
+ func keyLookupFunc(*Token) (interface{}, error) {
+ // Don't forget to validate the alg is what you expect:
+ if _, ok := token.Method.(*jwt.SigningMethodRSA); !ok {
+ return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"])
+ }
+
+ // Look up key
+ key, err := lookupPublicKey(token.Header["kid"])
+ if err != nil {
+ return nil, err
+ }
+
+ // Unpack key from PEM encoded PKCS8
+ return jwt.ParseRSAPublicKeyFromPEM(key)
+ }
+```
diff --git a/vendor/github.com/dgrijalva/jwt-go/README.md b/vendor/github.com/dgrijalva/jwt-go/README.md
index bf0100f4d..f48365faf 100644
--- a/vendor/github.com/dgrijalva/jwt-go/README.md
+++ b/vendor/github.com/dgrijalva/jwt-go/README.md
@@ -1,11 +1,16 @@
-A [go](http://www.golang.org) (or 'golang' for search engine friendliness) implementation of [JSON Web Tokens](http://self-issued.info/docs/draft-jones-json-web-token.html)
+A [go](http://www.golang.org) (or 'golang' for search engine friendliness) implementation of [JSON Web Tokens](http://self-issued.info/docs/draft-ietf-oauth-json-web-token.html)
[![Build Status](https://travis-ci.org/dgrijalva/jwt-go.svg?branch=master)](https://travis-ci.org/dgrijalva/jwt-go)
+**BREAKING CHANGES:*** Version 3.0.0 is here. It includes _a lot_ of changes including a few that break the API. We've tried to break as few things as possible, so there should just be a few type signature changes. A full list of breaking changes is available in `VERSION_HISTORY.md`. See `MIGRATION_GUIDE.md` for more information on updating your code.
+
**NOTICE:** A vulnerability in JWT was [recently published](https://auth0.com/blog/2015/03/31/critical-vulnerabilities-in-json-web-token-libraries/). As this library doesn't force users to validate the `alg` is what they expected, it's possible your usage is effected. There will be an update soon to remedy this, and it will likey require backwards-incompatible changes to the API. In the short term, please make sure your implementation verifies the `alg` is what you expect.
+
## What the heck is a JWT?
+JWT.io has [a great introduction](https://jwt.io/introduction) to JSON Web Tokens.
+
In short, it's a signed JSON object that does something useful (for example, authentication). It's commonly used for `Bearer` tokens in Oauth 2. A token is made of three parts, separated by `.`'s. The first two parts are JSON objects, that have been [base64url](http://tools.ietf.org/html/rfc4648) encoded. The last part is the signature, encoded the same way.
The first part is called the header. It contains the necessary information for verifying the last part, the signature. For example, which encryption method was used for signing and what key was used.
@@ -16,37 +21,13 @@ The part in the middle is the interesting bit. It's called the Claims and conta
This library supports the parsing and verification as well as the generation and signing of JWTs. Current supported signing algorithms are HMAC SHA, RSA, RSA-PSS, and ECDSA, though hooks are present for adding your own.
-## Parse and Verify
-
-Parsing and verifying tokens is pretty straight forward. You pass in the token and a function for looking up the key. This is done as a callback since you may need to parse the token to find out what signing method and key was used.
-
-```go
- token, err := jwt.Parse(myToken, func(token *jwt.Token) (interface{}, error) {
- // Don't forget to validate the alg is what you expect:
- if _, ok := token.Method.(*jwt.SigningMethodRSA); !ok {
- return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"])
- }
- return myLookupKey(token.Header["kid"]), nil
- })
-
- if err == nil && token.Valid {
- deliverGoodness("!")
- } else {
- deliverUtterRejection(":(")
- }
-```
-
-## Create a token
-
-```go
- // Create the token
- token := jwt.New(jwt.SigningMethodHS256)
- // Set some claims
- token.Claims["foo"] = "bar"
- token.Claims["exp"] = time.Now().Add(time.Hour * 72).Unix()
- // Sign and get the complete encoded token as a string
- tokenString, err := token.SignedString(mySigningKey)
-```
+## Examples
+
+See [the project documentation](https://godoc.org/github.com/dgrijalva/jwt-go) for examples of usage:
+
+* [Simple example of parsing and validating a token](https://godoc.org/github.com/dgrijalva/jwt-go#example-Parse--Hmac)
+* [Simple example of building and signing a token](https://godoc.org/github.com/dgrijalva/jwt-go#example-New--Hmac)
+* [Directory of Examples](https://godoc.org/github.com/dgrijalva/jwt-go#pkg-examples)
## Extensions
@@ -54,6 +35,12 @@ This library publishes all the necessary components for adding your own signing
Here's an example of an extension that integrates with the Google App Engine signing tools: https://github.com/someone1/gcp-jwt-go
+## Compliance
+
+This library was last reviewed to comply with [RTF 7519](http://www.rfc-editor.org/info/rfc7519) dated May 2015 with a few notable differences:
+
+* In order to protect against accidental use of [Unsecured JWTs](http://self-issued.info/docs/draft-ietf-oauth-json-web-token.html#UnsecuredJWT), tokens using `alg=none` will only be accepted if the constant `jwt.UnsafeAllowNoneSignatureType` is provided as the key.
+
## Project Status & Versioning
This library is considered production ready. Feedback and feature requests are appreciated. The API should be considered stable. There should be very few backwards-incompatible changes outside of major version updates (and only with good reason).
@@ -95,4 +82,4 @@ Without going too far down the rabbit hole, here's a description of the interact
Documentation can be found [on godoc.org](http://godoc.org/github.com/dgrijalva/jwt-go).
-The command line utility included in this project (cmd/jwt) provides a straightforward example of token creation and parsing as well as a useful tool for debugging your own integration. For a more http centric example, see [this gist](https://gist.github.com/cryptix/45c33ecf0ae54828e63b).
+The command line utility included in this project (cmd/jwt) provides a straightforward example of token creation and parsing as well as a useful tool for debugging your own integration. You'll also find several implementation examples in to documentation.
diff --git a/vendor/github.com/dgrijalva/jwt-go/VERSION_HISTORY.md b/vendor/github.com/dgrijalva/jwt-go/VERSION_HISTORY.md
index 9eb7ff9ca..b605b4509 100644
--- a/vendor/github.com/dgrijalva/jwt-go/VERSION_HISTORY.md
+++ b/vendor/github.com/dgrijalva/jwt-go/VERSION_HISTORY.md
@@ -1,5 +1,43 @@
## `jwt-go` Version History
+#### 3.0.0
+
+* **Compatibility Breaking Changes**: See MIGRATION_GUIDE.md for tips on updating your code
+ * Dropped support for `[]byte` keys when using RSA signing methods. This convenience feature could contribute to security vulnerabilities involving mismatched key types with signing methods.
+ * `ParseFromRequest` has been moved to `request` subpackage and usage has changed
+ * The `Claims` property on `Token` is now type `Claims` instead of `map[string]interface{}`. The default value is type `MapClaims`, which is an alias to `map[string]interface{}`. This makes it possible to use a custom type when decoding claims.
+* Other Additions and Changes
+ * Added `Claims` interface type to allow users to decode the claims into a custom type
+ * Added `ParseWithClaims`, which takes a third argument of type `Claims`. Use this function instead of `Parse` if you have a custom type you'd like to decode into.
+ * Dramatically improved the functionality and flexibility of `ParseFromRequest`, which is now in the `request` subpackage
+ * Added `ParseFromRequestWithClaims` which is the `FromRequest` equivalent of `ParseWithClaims`
+ * Added new interface type `Extractor`, which is used for extracting JWT strings from http requests. Used with `ParseFromRequest` and `ParseFromRequestWithClaims`.
+ * Added several new, more specific, validation errors to error type bitmask
+ * Moved examples from README to executable example files
+ * Signing method registry is now thread safe
+ * Added new property to `ValidationError`, which contains the raw error returned by calls made by parse/verify (such as those returned by keyfunc or json parser)
+
+#### 2.7.0
+
+This will likely be the last backwards compatible release before 3.0.0, excluding essential bug fixes.
+
+* Added new option `-show` to the `jwt` command that will just output the decoded token without verifying
+* Error text for expired tokens includes how long it's been expired
+* Fixed incorrect error returned from `ParseRSAPublicKeyFromPEM`
+* Documentation updates
+
+#### 2.6.0
+
+* Exposed inner error within ValidationError
+* Fixed validation errors when using UseJSONNumber flag
+* Added several unit tests
+
+#### 2.5.0
+
+* Added support for signing method none. You shouldn't use this. The API tries to make this clear.
+* Updated/fixed some documentation
+* Added more helpful error message when trying to parse tokens that begin with `BEARER `
+
#### 2.4.0
* Added new type, Parser, to allow for configuration of various parsing parameters
diff --git a/vendor/github.com/dgrijalva/jwt-go/claims.go b/vendor/github.com/dgrijalva/jwt-go/claims.go
new file mode 100644
index 000000000..f0228f02e
--- /dev/null
+++ b/vendor/github.com/dgrijalva/jwt-go/claims.go
@@ -0,0 +1,134 @@
+package jwt
+
+import (
+ "crypto/subtle"
+ "fmt"
+ "time"
+)
+
+// For a type to be a Claims object, it must just have a Valid method that determines
+// if the token is invalid for any supported reason
+type Claims interface {
+ Valid() error
+}
+
+// Structured version of Claims Section, as referenced at
+// https://tools.ietf.org/html/rfc7519#section-4.1
+// See examples for how to use this with your own claim types
+type StandardClaims struct {
+ Audience string `json:"aud,omitempty"`
+ ExpiresAt int64 `json:"exp,omitempty"`
+ Id string `json:"jti,omitempty"`
+ IssuedAt int64 `json:"iat,omitempty"`
+ Issuer string `json:"iss,omitempty"`
+ NotBefore int64 `json:"nbf,omitempty"`
+ Subject string `json:"sub,omitempty"`
+}
+
+// Validates time based claims "exp, iat, nbf".
+// There is no accounting for clock skew.
+// As well, if any of the above claims are not in the token, it will still
+// be considered a valid claim.
+func (c StandardClaims) Valid() error {
+ vErr := new(ValidationError)
+ now := TimeFunc().Unix()
+
+ // The claims below are optional, by default, so if they are set to the
+ // default value in Go, let's not fail the verification for them.
+ if c.VerifyExpiresAt(now, false) == false {
+ delta := time.Unix(now, 0).Sub(time.Unix(c.ExpiresAt, 0))
+ vErr.Inner = fmt.Errorf("token is expired by %v", delta)
+ vErr.Errors |= ValidationErrorExpired
+ }
+
+ if c.VerifyIssuedAt(now, false) == false {
+ vErr.Inner = fmt.Errorf("Token used before issued")
+ vErr.Errors |= ValidationErrorIssuedAt
+ }
+
+ if c.VerifyNotBefore(now, false) == false {
+ vErr.Inner = fmt.Errorf("token is not valid yet")
+ vErr.Errors |= ValidationErrorNotValidYet
+ }
+
+ if vErr.valid() {
+ return nil
+ }
+
+ return vErr
+}
+
+// Compares the aud claim against cmp.
+// If required is false, this method will return true if the value matches or is unset
+func (c *StandardClaims) VerifyAudience(cmp string, req bool) bool {
+ return verifyAud(c.Audience, cmp, req)
+}
+
+// Compares the exp claim against cmp.
+// If required is false, this method will return true if the value matches or is unset
+func (c *StandardClaims) VerifyExpiresAt(cmp int64, req bool) bool {
+ return verifyExp(c.ExpiresAt, cmp, req)
+}
+
+// Compares the iat claim against cmp.
+// If required is false, this method will return true if the value matches or is unset
+func (c *StandardClaims) VerifyIssuedAt(cmp int64, req bool) bool {
+ return verifyIat(c.IssuedAt, cmp, req)
+}
+
+// Compares the iss claim against cmp.
+// If required is false, this method will return true if the value matches or is unset
+func (c *StandardClaims) VerifyIssuer(cmp string, req bool) bool {
+ return verifyIss(c.Issuer, cmp, req)
+}
+
+// Compares the nbf claim against cmp.
+// If required is false, this method will return true if the value matches or is unset
+func (c *StandardClaims) VerifyNotBefore(cmp int64, req bool) bool {
+ return verifyNbf(c.NotBefore, cmp, req)
+}
+
+// ----- helpers
+
+func verifyAud(aud string, cmp string, required bool) bool {
+ if aud == "" {
+ return !required
+ }
+ if subtle.ConstantTimeCompare([]byte(aud), []byte(cmp)) != 0 {
+ return true
+ } else {
+ return false
+ }
+}
+
+func verifyExp(exp int64, now int64, required bool) bool {
+ if exp == 0 {
+ return !required
+ }
+ return now <= exp
+}
+
+func verifyIat(iat int64, now int64, required bool) bool {
+ if iat == 0 {
+ return !required
+ }
+ return now >= iat
+}
+
+func verifyIss(iss string, cmp string, required bool) bool {
+ if iss == "" {
+ return !required
+ }
+ if subtle.ConstantTimeCompare([]byte(iss), []byte(cmp)) != 0 {
+ return true
+ } else {
+ return false
+ }
+}
+
+func verifyNbf(nbf int64, now int64, required bool) bool {
+ if nbf == 0 {
+ return !required
+ }
+ return now >= nbf
+}
diff --git a/vendor/github.com/dgrijalva/jwt-go/ecdsa.go b/vendor/github.com/dgrijalva/jwt-go/ecdsa.go
index 0518ed106..2f59a2223 100644
--- a/vendor/github.com/dgrijalva/jwt-go/ecdsa.go
+++ b/vendor/github.com/dgrijalva/jwt-go/ecdsa.go
@@ -69,7 +69,7 @@ func (m *SigningMethodECDSA) Verify(signingString, signature string, key interfa
case *ecdsa.PublicKey:
ecdsaKey = k
default:
- return ErrInvalidKey
+ return ErrInvalidKeyType
}
if len(sig) != 2*m.KeySize {
@@ -103,7 +103,7 @@ func (m *SigningMethodECDSA) Sign(signingString string, key interface{}) (string
case *ecdsa.PrivateKey:
ecdsaKey = k
default:
- return "", ErrInvalidKey
+ return "", ErrInvalidKeyType
}
// Create the hasher
diff --git a/vendor/github.com/dgrijalva/jwt-go/ecdsa_test.go b/vendor/github.com/dgrijalva/jwt-go/ecdsa_test.go
deleted file mode 100644
index 753047b1e..000000000
--- a/vendor/github.com/dgrijalva/jwt-go/ecdsa_test.go
+++ /dev/null
@@ -1,100 +0,0 @@
-package jwt_test
-
-import (
- "crypto/ecdsa"
- "io/ioutil"
- "strings"
- "testing"
-
- "github.com/dgrijalva/jwt-go"
-)
-
-var ecdsaTestData = []struct {
- name string
- keys map[string]string
- tokenString string
- alg string
- claims map[string]interface{}
- valid bool
-}{
- {
- "Basic ES256",
- map[string]string{"private": "test/ec256-private.pem", "public": "test/ec256-public.pem"},
- "eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiJ9.eyJmb28iOiJiYXIifQ.feG39E-bn8HXAKhzDZq7yEAPWYDhZlwTn3sePJnU9VrGMmwdXAIEyoOnrjreYlVM_Z4N13eK9-TmMTWyfKJtHQ",
- "ES256",
- map[string]interface{}{"foo": "bar"},
- true,
- },
- {
- "Basic ES384",
- map[string]string{"private": "test/ec384-private.pem", "public": "test/ec384-public.pem"},
- "eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzM4NCJ9.eyJmb28iOiJiYXIifQ.ngAfKMbJUh0WWubSIYe5GMsA-aHNKwFbJk_wq3lq23aPp8H2anb1rRILIzVR0gUf4a8WzDtrzmiikuPWyCS6CN4-PwdgTk-5nehC7JXqlaBZU05p3toM3nWCwm_LXcld",
- "ES384",
- map[string]interface{}{"foo": "bar"},
- true,
- },
- {
- "Basic ES512",
- map[string]string{"private": "test/ec512-private.pem", "public": "test/ec512-public.pem"},
- "eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzUxMiJ9.eyJmb28iOiJiYXIifQ.AAU0TvGQOcdg2OvrwY73NHKgfk26UDekh9Prz-L_iWuTBIBqOFCWwwLsRiHB1JOddfKAls5do1W0jR_F30JpVd-6AJeTjGKA4C1A1H6gIKwRY0o_tFDIydZCl_lMBMeG5VNFAjO86-WCSKwc3hqaGkq1MugPRq_qrF9AVbuEB4JPLyL5",
- "ES512",
- map[string]interface{}{"foo": "bar"},
- true,
- },
- {
- "basic ES256 invalid: foo => bar",
- map[string]string{"private": "test/ec256-private.pem", "public": "test/ec256-public.pem"},
- "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJmb28iOiJiYXIifQ.MEQCIHoSJnmGlPaVQDqacx_2XlXEhhqtWceVopjomc2PJLtdAiAUTeGPoNYxZw0z8mgOnnIcjoxRuNDVZvybRZF3wR1l8W",
- "ES256",
- map[string]interface{}{"foo": "bar"},
- false,
- },
-}
-
-func TestECDSAVerify(t *testing.T) {
- for _, data := range ecdsaTestData {
- var err error
-
- key, _ := ioutil.ReadFile(data.keys["public"])
-
- var ecdsaKey *ecdsa.PublicKey
- if ecdsaKey, err = jwt.ParseECPublicKeyFromPEM(key); err != nil {
- t.Errorf("Unable to parse ECDSA public key: %v", err)
- }
-
- parts := strings.Split(data.tokenString, ".")
-
- method := jwt.GetSigningMethod(data.alg)
- err = method.Verify(strings.Join(parts[0:2], "."), parts[2], ecdsaKey)
- if data.valid && err != nil {
- t.Errorf("[%v] Error while verifying key: %v", data.name, err)
- }
- if !data.valid && err == nil {
- t.Errorf("[%v] Invalid key passed validation", data.name)
- }
- }
-}
-
-func TestECDSASign(t *testing.T) {
- for _, data := range ecdsaTestData {
- var err error
- key, _ := ioutil.ReadFile(data.keys["private"])
-
- var ecdsaKey *ecdsa.PrivateKey
- if ecdsaKey, err = jwt.ParseECPrivateKeyFromPEM(key); err != nil {
- t.Errorf("Unable to parse ECDSA private key: %v", err)
- }
-
- if data.valid {
- parts := strings.Split(data.tokenString, ".")
- method := jwt.GetSigningMethod(data.alg)
- sig, err := method.Sign(strings.Join(parts[0:2], "."), ecdsaKey)
- if err != nil {
- t.Errorf("[%v] Error signing token: %v", data.name, err)
- }
- if sig == parts[2] {
- t.Errorf("[%v] Identical signatures\nbefore:\n%v\nafter:\n%v", data.name, parts[2], sig)
- }
- }
- }
-}
diff --git a/vendor/github.com/dgrijalva/jwt-go/errors.go b/vendor/github.com/dgrijalva/jwt-go/errors.go
index e9e788ff9..662df19d4 100644
--- a/vendor/github.com/dgrijalva/jwt-go/errors.go
+++ b/vendor/github.com/dgrijalva/jwt-go/errors.go
@@ -6,9 +6,9 @@ import (
// Error constants
var (
- ErrInvalidKey = errors.New("key is invalid or of invalid type")
- ErrHashUnavailable = errors.New("the requested hash function is unavailable")
- ErrNoTokenInRequest = errors.New("no token present in request")
+ ErrInvalidKey = errors.New("key is invalid")
+ ErrInvalidKeyType = errors.New("key is of invalid type")
+ ErrHashUnavailable = errors.New("the requested hash function is unavailable")
)
// The errors that might occur when parsing and validating a token
@@ -16,22 +16,42 @@ const (
ValidationErrorMalformed uint32 = 1 << iota // Token is malformed
ValidationErrorUnverifiable // Token could not be verified because of signing problems
ValidationErrorSignatureInvalid // Signature validation failed
- ValidationErrorExpired // Exp validation failed
- ValidationErrorNotValidYet // NBF validation failed
+
+ // Standard Claim validation errors
+ ValidationErrorAudience // AUD validation failed
+ ValidationErrorExpired // EXP validation failed
+ ValidationErrorIssuedAt // IAT validation failed
+ ValidationErrorIssuer // ISS validation failed
+ ValidationErrorNotValidYet // NBF validation failed
+ ValidationErrorId // JTI validation failed
+ ValidationErrorClaimsInvalid // Generic claims validation error
)
+// Helper for constructing a ValidationError with a string error message
+func NewValidationError(errorText string, errorFlags uint32) *ValidationError {
+ return &ValidationError{
+ text: errorText,
+ Errors: errorFlags,
+ }
+}
+
// The error from Parse if token is not valid
type ValidationError struct {
- err string
+ Inner error // stores the error returned by external dependencies, i.e.: KeyFunc
Errors uint32 // bitfield. see ValidationError... constants
+ text string // errors that do not have a valid error just have text
}
// Validation error is an error type
func (e ValidationError) Error() string {
- if e.err == "" {
+ if e.Inner != nil {
+ return e.Inner.Error()
+ } else if e.text != "" {
+ return e.text
+ } else {
return "token is invalid"
}
- return e.err
+ return e.Inner.Error()
}
// No errors
diff --git a/vendor/github.com/dgrijalva/jwt-go/example_test.go b/vendor/github.com/dgrijalva/jwt-go/example_test.go
deleted file mode 100644
index edb48e4db..000000000
--- a/vendor/github.com/dgrijalva/jwt-go/example_test.go
+++ /dev/null
@@ -1,52 +0,0 @@
-package jwt_test
-
-import (
- "fmt"
- "github.com/dgrijalva/jwt-go"
- "time"
-)
-
-func ExampleParse(myToken string, myLookupKey func(interface{}) (interface{}, error)) {
- token, err := jwt.Parse(myToken, func(token *jwt.Token) (interface{}, error) {
- return myLookupKey(token.Header["kid"])
- })
-
- if err == nil && token.Valid {
- fmt.Println("Your token is valid. I like your style.")
- } else {
- fmt.Println("This token is terrible! I cannot accept this.")
- }
-}
-
-func ExampleNew(mySigningKey []byte) (string, error) {
- // Create the token
- token := jwt.New(jwt.SigningMethodHS256)
- // Set some claims
- token.Claims["foo"] = "bar"
- token.Claims["exp"] = time.Now().Add(time.Hour * 72).Unix()
- // Sign and get the complete encoded token as a string
- tokenString, err := token.SignedString(mySigningKey)
- return tokenString, err
-}
-
-func ExampleParse_errorChecking(myToken string, myLookupKey func(interface{}) (interface{}, error)) {
- token, err := jwt.Parse(myToken, func(token *jwt.Token) (interface{}, error) {
- return myLookupKey(token.Header["kid"])
- })
-
- if token.Valid {
- fmt.Println("You look nice today")
- } else if ve, ok := err.(*jwt.ValidationError); ok {
- if ve.Errors&jwt.ValidationErrorMalformed != 0 {
- fmt.Println("That's not even a token")
- } else if ve.Errors&(jwt.ValidationErrorExpired|jwt.ValidationErrorNotValidYet) != 0 {
- // Token is either expired or not active yet
- fmt.Println("Timing is everything")
- } else {
- fmt.Println("Couldn't handle this token:", err)
- }
- } else {
- fmt.Println("Couldn't handle this token:", err)
- }
-
-}
diff --git a/vendor/github.com/dgrijalva/jwt-go/hmac.go b/vendor/github.com/dgrijalva/jwt-go/hmac.go
index 192e625fd..c22991925 100644
--- a/vendor/github.com/dgrijalva/jwt-go/hmac.go
+++ b/vendor/github.com/dgrijalva/jwt-go/hmac.go
@@ -49,7 +49,7 @@ func (m *SigningMethodHMAC) Verify(signingString, signature string, key interfac
// Verify the key is the right type
keyBytes, ok := key.([]byte)
if !ok {
- return ErrInvalidKey
+ return ErrInvalidKeyType
}
// Decode signature, for comparison
diff --git a/vendor/github.com/dgrijalva/jwt-go/hmac_test.go b/vendor/github.com/dgrijalva/jwt-go/hmac_test.go
deleted file mode 100644
index c7e114f4f..000000000
--- a/vendor/github.com/dgrijalva/jwt-go/hmac_test.go
+++ /dev/null
@@ -1,91 +0,0 @@
-package jwt_test
-
-import (
- "github.com/dgrijalva/jwt-go"
- "io/ioutil"
- "strings"
- "testing"
-)
-
-var hmacTestData = []struct {
- name string
- tokenString string
- alg string
- claims map[string]interface{}
- valid bool
-}{
- {
- "web sample",
- "eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ.dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk",
- "HS256",
- map[string]interface{}{"iss": "joe", "exp": 1300819380, "http://example.com/is_root": true},
- true,
- },
- {
- "HS384",
- "eyJhbGciOiJIUzM4NCIsInR5cCI6IkpXVCJ9.eyJleHAiOjEuMzAwODE5MzhlKzA5LCJodHRwOi8vZXhhbXBsZS5jb20vaXNfcm9vdCI6dHJ1ZSwiaXNzIjoiam9lIn0.KWZEuOD5lbBxZ34g7F-SlVLAQ_r5KApWNWlZIIMyQVz5Zs58a7XdNzj5_0EcNoOy",
- "HS384",
- map[string]interface{}{"iss": "joe", "exp": 1300819380, "http://example.com/is_root": true},
- true,
- },
- {
- "HS512",
- "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJleHAiOjEuMzAwODE5MzhlKzA5LCJodHRwOi8vZXhhbXBsZS5jb20vaXNfcm9vdCI6dHJ1ZSwiaXNzIjoiam9lIn0.CN7YijRX6Aw1n2jyI2Id1w90ja-DEMYiWixhYCyHnrZ1VfJRaFQz1bEbjjA5Fn4CLYaUG432dEYmSbS4Saokmw",
- "HS512",
- map[string]interface{}{"iss": "joe", "exp": 1300819380, "http://example.com/is_root": true},
- true,
- },
- {
- "web sample: invalid",
- "eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ.dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXo",
- "HS256",
- map[string]interface{}{"iss": "joe", "exp": 1300819380, "http://example.com/is_root": true},
- false,
- },
-}
-
-// Sample data from http://tools.ietf.org/html/draft-jones-json-web-signature-04#appendix-A.1
-var hmacTestKey, _ = ioutil.ReadFile("test/hmacTestKey")
-
-func TestHMACVerify(t *testing.T) {
- for _, data := range hmacTestData {
- parts := strings.Split(data.tokenString, ".")
-
- method := jwt.GetSigningMethod(data.alg)
- err := method.Verify(strings.Join(parts[0:2], "."), parts[2], hmacTestKey)
- if data.valid && err != nil {
- t.Errorf("[%v] Error while verifying key: %v", data.name, err)
- }
- if !data.valid && err == nil {
- t.Errorf("[%v] Invalid key passed validation", data.name)
- }
- }
-}
-
-func TestHMACSign(t *testing.T) {
- for _, data := range hmacTestData {
- if data.valid {
- parts := strings.Split(data.tokenString, ".")
- method := jwt.GetSigningMethod(data.alg)
- sig, err := method.Sign(strings.Join(parts[0:2], "."), hmacTestKey)
- if err != nil {
- t.Errorf("[%v] Error signing token: %v", data.name, err)
- }
- if sig != parts[2] {
- t.Errorf("[%v] Incorrect signature.\nwas:\n%v\nexpecting:\n%v", data.name, sig, parts[2])
- }
- }
- }
-}
-
-func BenchmarkHS256Signing(b *testing.B) {
- benchmarkSigning(b, jwt.SigningMethodHS256, hmacTestKey)
-}
-
-func BenchmarkHS384Signing(b *testing.B) {
- benchmarkSigning(b, jwt.SigningMethodHS384, hmacTestKey)
-}
-
-func BenchmarkHS512Signing(b *testing.B) {
- benchmarkSigning(b, jwt.SigningMethodHS512, hmacTestKey)
-}
diff --git a/vendor/github.com/dgrijalva/jwt-go/map_claims.go b/vendor/github.com/dgrijalva/jwt-go/map_claims.go
new file mode 100644
index 000000000..291213c46
--- /dev/null
+++ b/vendor/github.com/dgrijalva/jwt-go/map_claims.go
@@ -0,0 +1,94 @@
+package jwt
+
+import (
+ "encoding/json"
+ "errors"
+ // "fmt"
+)
+
+// Claims type that uses the map[string]interface{} for JSON decoding
+// This is the default claims type if you don't supply one
+type MapClaims map[string]interface{}
+
+// Compares the aud claim against cmp.
+// If required is false, this method will return true if the value matches or is unset
+func (m MapClaims) VerifyAudience(cmp string, req bool) bool {
+ aud, _ := m["aud"].(string)
+ return verifyAud(aud, cmp, req)
+}
+
+// Compares the exp claim against cmp.
+// If required is false, this method will return true if the value matches or is unset
+func (m MapClaims) VerifyExpiresAt(cmp int64, req bool) bool {
+ switch exp := m["exp"].(type) {
+ case float64:
+ return verifyExp(int64(exp), cmp, req)
+ case json.Number:
+ v, _ := exp.Int64()
+ return verifyExp(v, cmp, req)
+ }
+ return req == false
+}
+
+// Compares the iat claim against cmp.
+// If required is false, this method will return true if the value matches or is unset
+func (m MapClaims) VerifyIssuedAt(cmp int64, req bool) bool {
+ switch iat := m["iat"].(type) {
+ case float64:
+ return verifyIat(int64(iat), cmp, req)
+ case json.Number:
+ v, _ := iat.Int64()
+ return verifyIat(v, cmp, req)
+ }
+ return req == false
+}
+
+// Compares the iss claim against cmp.
+// If required is false, this method will return true if the value matches or is unset
+func (m MapClaims) VerifyIssuer(cmp string, req bool) bool {
+ iss, _ := m["iss"].(string)
+ return verifyIss(iss, cmp, req)
+}
+
+// Compares the nbf claim against cmp.
+// If required is false, this method will return true if the value matches or is unset
+func (m MapClaims) VerifyNotBefore(cmp int64, req bool) bool {
+ switch nbf := m["nbf"].(type) {
+ case float64:
+ return verifyNbf(int64(nbf), cmp, req)
+ case json.Number:
+ v, _ := nbf.Int64()
+ return verifyNbf(v, cmp, req)
+ }
+ return req == false
+}
+
+// Validates time based claims "exp, iat, nbf".
+// There is no accounting for clock skew.
+// As well, if any of the above claims are not in the token, it will still
+// be considered a valid claim.
+func (m MapClaims) Valid() error {
+ vErr := new(ValidationError)
+ now := TimeFunc().Unix()
+
+ if m.VerifyExpiresAt(now, false) == false {
+ vErr.Inner = errors.New("Token is expired")
+ vErr.Errors |= ValidationErrorExpired
+ }
+
+ if m.VerifyIssuedAt(now, false) == false {
+ vErr.Inner = errors.New("Token used before issued")
+ vErr.Errors |= ValidationErrorIssuedAt
+ }
+
+ if m.VerifyNotBefore(now, false) == false {
+ vErr.Inner = errors.New("Token is not valid yet")
+ vErr.Errors |= ValidationErrorNotValidYet
+ }
+
+ if vErr.valid() {
+ return nil
+ }
+
+ return vErr
+}
diff --git a/vendor/github.com/dgrijalva/jwt-go/none.go b/vendor/github.com/dgrijalva/jwt-go/none.go
new file mode 100644
index 000000000..f04d189d0
--- /dev/null
+++ b/vendor/github.com/dgrijalva/jwt-go/none.go
@@ -0,0 +1,52 @@
+package jwt
+
+// Implements the none signing method. This is required by the spec
+// but you probably should never use it.
+var SigningMethodNone *signingMethodNone
+
+const UnsafeAllowNoneSignatureType unsafeNoneMagicConstant = "none signing method allowed"
+
+var NoneSignatureTypeDisallowedError error
+
+type signingMethodNone struct{}
+type unsafeNoneMagicConstant string
+
+func init() {
+ SigningMethodNone = &signingMethodNone{}
+ NoneSignatureTypeDisallowedError = NewValidationError("'none' signature type is not allowed", ValidationErrorSignatureInvalid)
+
+ RegisterSigningMethod(SigningMethodNone.Alg(), func() SigningMethod {
+ return SigningMethodNone
+ })
+}
+
+func (m *signingMethodNone) Alg() string {
+ return "none"
+}
+
+// Only allow 'none' alg type if UnsafeAllowNoneSignatureType is specified as the key
+func (m *signingMethodNone) Verify(signingString, signature string, key interface{}) (err error) {
+ // Key must be UnsafeAllowNoneSignatureType to prevent accidentally
+ // accepting 'none' signing method
+ if _, ok := key.(unsafeNoneMagicConstant); !ok {
+ return NoneSignatureTypeDisallowedError
+ }
+ // If signing method is none, signature must be an empty string
+ if signature != "" {
+ return NewValidationError(
+ "'none' signing method with non-empty signature",
+ ValidationErrorSignatureInvalid,
+ )
+ }
+
+ // Accept 'none' signing method.
+ return nil
+}
+
+// Only allow 'none' signing if UnsafeAllowNoneSignatureType is specified as the key
+func (m *signingMethodNone) Sign(signingString string, key interface{}) (string, error) {
+ if _, ok := key.(unsafeNoneMagicConstant); ok {
+ return "", nil
+ }
+ return "", NoneSignatureTypeDisallowedError
+}
diff --git a/vendor/github.com/dgrijalva/jwt-go/parser.go b/vendor/github.com/dgrijalva/jwt-go/parser.go
index 3fc27bfed..7bf1c4ea0 100644
--- a/vendor/github.com/dgrijalva/jwt-go/parser.go
+++ b/vendor/github.com/dgrijalva/jwt-go/parser.go
@@ -8,50 +8,68 @@ import (
)
type Parser struct {
- ValidMethods []string // If populated, only these methods will be considered valid
- UseJSONNumber bool // Use JSON Number format in JSON decoder
+ ValidMethods []string // If populated, only these methods will be considered valid
+ UseJSONNumber bool // Use JSON Number format in JSON decoder
+ SkipClaimsValidation bool // Skip claims validation during token parsing
}
// Parse, validate, and return a token.
// keyFunc will receive the parsed token and should return the key for validating.
// If everything is kosher, err will be nil
func (p *Parser) Parse(tokenString string, keyFunc Keyfunc) (*Token, error) {
+ return p.ParseWithClaims(tokenString, MapClaims{}, keyFunc)
+}
+
+func (p *Parser) ParseWithClaims(tokenString string, claims Claims, keyFunc Keyfunc) (*Token, error) {
parts := strings.Split(tokenString, ".")
if len(parts) != 3 {
- return nil, &ValidationError{err: "token contains an invalid number of segments", Errors: ValidationErrorMalformed}
+ return nil, NewValidationError("token contains an invalid number of segments", ValidationErrorMalformed)
}
var err error
token := &Token{Raw: tokenString}
+
// parse Header
var headerBytes []byte
if headerBytes, err = DecodeSegment(parts[0]); err != nil {
- return token, &ValidationError{err: err.Error(), Errors: ValidationErrorMalformed}
+ if strings.HasPrefix(strings.ToLower(tokenString), "bearer ") {
+ return token, NewValidationError("tokenstring should not contain 'bearer '", ValidationErrorMalformed)
+ }
+ return token, &ValidationError{Inner: err, Errors: ValidationErrorMalformed}
}
if err = json.Unmarshal(headerBytes, &token.Header); err != nil {
- return token, &ValidationError{err: err.Error(), Errors: ValidationErrorMalformed}
+ return token, &ValidationError{Inner: err, Errors: ValidationErrorMalformed}
}
// parse Claims
var claimBytes []byte
+ token.Claims = claims
+
if claimBytes, err = DecodeSegment(parts[1]); err != nil {
- return token, &ValidationError{err: err.Error(), Errors: ValidationErrorMalformed}
+ return token, &ValidationError{Inner: err, Errors: ValidationErrorMalformed}
}
dec := json.NewDecoder(bytes.NewBuffer(claimBytes))
if p.UseJSONNumber {
dec.UseNumber()
}
- if err = dec.Decode(&token.Claims); err != nil {
- return token, &ValidationError{err: err.Error(), Errors: ValidationErrorMalformed}
+ // JSON Decode. Special case for map type to avoid weird pointer behavior
+ if c, ok := token.Claims.(MapClaims); ok {
+ err = dec.Decode(&c)
+ } else {
+ err = dec.Decode(&claims)
+ }
+ // Handle decode error
+ if err != nil {
+ return token, &ValidationError{Inner: err, Errors: ValidationErrorMalformed}
}
// Lookup signature method
if method, ok := token.Header["alg"].(string); ok {
if token.Method = GetSigningMethod(method); token.Method == nil {
- return token, &ValidationError{err: "signing method (alg) is unavailable.", Errors: ValidationErrorUnverifiable}
+ return token, NewValidationError("signing method (alg) is unavailable.", ValidationErrorUnverifiable)
}
} else {
- return token, &ValidationError{err: "signing method (alg) is unspecified.", Errors: ValidationErrorUnverifiable}
+ return token, NewValidationError("signing method (alg) is unspecified.", ValidationErrorUnverifiable)
}
// Verify signing method is in the required set
@@ -66,7 +84,7 @@ func (p *Parser) Parse(tokenString string, keyFunc Keyfunc) (*Token, error) {
}
if !signingMethodValid {
// signing method is not in the listed set
- return token, &ValidationError{err: fmt.Sprintf("signing method %v is invalid", alg), Errors: ValidationErrorSignatureInvalid}
+ return token, NewValidationError(fmt.Sprintf("signing method %v is invalid", alg), ValidationErrorSignatureInvalid)
}
}
@@ -74,33 +92,33 @@ func (p *Parser) Parse(tokenString string, keyFunc Keyfunc) (*Token, error) {
var key interface{}
if keyFunc == nil {
// keyFunc was not provided. short circuiting validation
- return token, &ValidationError{err: "no Keyfunc was provided.", Errors: ValidationErrorUnverifiable}
+ return token, NewValidationError("no Keyfunc was provided.", ValidationErrorUnverifiable)
}
if key, err = keyFunc(token); err != nil {
// keyFunc returned an error
- return token, &ValidationError{err: err.Error(), Errors: ValidationErrorUnverifiable}
+ return token, &ValidationError{Inner: err, Errors: ValidationErrorUnverifiable}
}
- // Check expiration times
vErr := &ValidationError{}
- now := TimeFunc().Unix()
- if exp, ok := token.Claims["exp"].(float64); ok {
- if now > int64(exp) {
- vErr.err = "token is expired"
- vErr.Errors |= ValidationErrorExpired
- }
- }
- if nbf, ok := token.Claims["nbf"].(float64); ok {
- if now < int64(nbf) {
- vErr.err = "token is not valid yet"
- vErr.Errors |= ValidationErrorNotValidYet
+
+ // Validate Claims
+ if !p.SkipClaimsValidation {
+ if err := token.Claims.Valid(); err != nil {
+
+ // If the Claims Valid returned an error, check if it is a validation error,
+ // If it was another error type, create a ValidationError with a generic ClaimsInvalid flag set
+ if e, ok := err.(*ValidationError); !ok {
+ vErr = &ValidationError{Inner: err, Errors: ValidationErrorClaimsInvalid}
+ } else {
+ vErr = e
+ }
}
}
// Perform validation
token.Signature = parts[2]
if err = token.Method.Verify(strings.Join(parts[0:2], "."), token.Signature, key); err != nil {
- vErr.err = err.Error()
+ vErr.Inner = err
vErr.Errors |= ValidationErrorSignatureInvalid
}
diff --git a/vendor/github.com/dgrijalva/jwt-go/parser_test.go b/vendor/github.com/dgrijalva/jwt-go/parser_test.go
deleted file mode 100644
index 9115017b8..000000000
--- a/vendor/github.com/dgrijalva/jwt-go/parser_test.go
+++ /dev/null
@@ -1,239 +0,0 @@
-package jwt_test
-
-import (
- "encoding/json"
- "fmt"
- "github.com/dgrijalva/jwt-go"
- "io/ioutil"
- "net/http"
- "reflect"
- "testing"
- "time"
-)
-
-var (
- jwtTestDefaultKey []byte
- defaultKeyFunc jwt.Keyfunc = func(t *jwt.Token) (interface{}, error) { return jwtTestDefaultKey, nil }
- emptyKeyFunc jwt.Keyfunc = func(t *jwt.Token) (interface{}, error) { return nil, nil }
- errorKeyFunc jwt.Keyfunc = func(t *jwt.Token) (interface{}, error) { return nil, fmt.Errorf("error loading key") }
- nilKeyFunc jwt.Keyfunc = nil
-)
-
-var jwtTestData = []struct {
- name string
- tokenString string
- keyfunc jwt.Keyfunc
- claims map[string]interface{}
- valid bool
- errors uint32
- parser *jwt.Parser
-}{
- {
- "basic",
- "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJmb28iOiJiYXIifQ.FhkiHkoESI_cG3NPigFrxEk9Z60_oXrOT2vGm9Pn6RDgYNovYORQmmA0zs1AoAOf09ly2Nx2YAg6ABqAYga1AcMFkJljwxTT5fYphTuqpWdy4BELeSYJx5Ty2gmr8e7RonuUztrdD5WfPqLKMm1Ozp_T6zALpRmwTIW0QPnaBXaQD90FplAg46Iy1UlDKr-Eupy0i5SLch5Q-p2ZpaL_5fnTIUDlxC3pWhJTyx_71qDI-mAA_5lE_VdroOeflG56sSmDxopPEG3bFlSu1eowyBfxtu0_CuVd-M42RU75Zc4Gsj6uV77MBtbMrf4_7M_NUTSgoIF3fRqxrj0NzihIBg",
- defaultKeyFunc,
- map[string]interface{}{"foo": "bar"},
- true,
- 0,
- nil,
- },
- {
- "basic expired",
- "", // autogen
- defaultKeyFunc,
- map[string]interface{}{"foo": "bar", "exp": float64(time.Now().Unix() - 100)},
- false,
- jwt.ValidationErrorExpired,
- nil,
- },
- {
- "basic nbf",
- "", // autogen
- defaultKeyFunc,
- map[string]interface{}{"foo": "bar", "nbf": float64(time.Now().Unix() + 100)},
- false,
- jwt.ValidationErrorNotValidYet,
- nil,
- },
- {
- "expired and nbf",
- "", // autogen
- defaultKeyFunc,
- map[string]interface{}{"foo": "bar", "nbf": float64(time.Now().Unix() + 100), "exp": float64(time.Now().Unix() - 100)},
- false,
- jwt.ValidationErrorNotValidYet | jwt.ValidationErrorExpired,
- nil,
- },
- {
- "basic invalid",
- "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJmb28iOiJiYXIifQ.EhkiHkoESI_cG3NPigFrxEk9Z60_oXrOT2vGm9Pn6RDgYNovYORQmmA0zs1AoAOf09ly2Nx2YAg6ABqAYga1AcMFkJljwxTT5fYphTuqpWdy4BELeSYJx5Ty2gmr8e7RonuUztrdD5WfPqLKMm1Ozp_T6zALpRmwTIW0QPnaBXaQD90FplAg46Iy1UlDKr-Eupy0i5SLch5Q-p2ZpaL_5fnTIUDlxC3pWhJTyx_71qDI-mAA_5lE_VdroOeflG56sSmDxopPEG3bFlSu1eowyBfxtu0_CuVd-M42RU75Zc4Gsj6uV77MBtbMrf4_7M_NUTSgoIF3fRqxrj0NzihIBg",
- defaultKeyFunc,
- map[string]interface{}{"foo": "bar"},
- false,
- jwt.ValidationErrorSignatureInvalid,
- nil,
- },
- {
- "basic nokeyfunc",
- "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJmb28iOiJiYXIifQ.FhkiHkoESI_cG3NPigFrxEk9Z60_oXrOT2vGm9Pn6RDgYNovYORQmmA0zs1AoAOf09ly2Nx2YAg6ABqAYga1AcMFkJljwxTT5fYphTuqpWdy4BELeSYJx5Ty2gmr8e7RonuUztrdD5WfPqLKMm1Ozp_T6zALpRmwTIW0QPnaBXaQD90FplAg46Iy1UlDKr-Eupy0i5SLch5Q-p2ZpaL_5fnTIUDlxC3pWhJTyx_71qDI-mAA_5lE_VdroOeflG56sSmDxopPEG3bFlSu1eowyBfxtu0_CuVd-M42RU75Zc4Gsj6uV77MBtbMrf4_7M_NUTSgoIF3fRqxrj0NzihIBg",
- nilKeyFunc,
- map[string]interface{}{"foo": "bar"},
- false,
- jwt.ValidationErrorUnverifiable,
- nil,
- },
- {
- "basic nokey",
- "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJmb28iOiJiYXIifQ.FhkiHkoESI_cG3NPigFrxEk9Z60_oXrOT2vGm9Pn6RDgYNovYORQmmA0zs1AoAOf09ly2Nx2YAg6ABqAYga1AcMFkJljwxTT5fYphTuqpWdy4BELeSYJx5Ty2gmr8e7RonuUztrdD5WfPqLKMm1Ozp_T6zALpRmwTIW0QPnaBXaQD90FplAg46Iy1UlDKr-Eupy0i5SLch5Q-p2ZpaL_5fnTIUDlxC3pWhJTyx_71qDI-mAA_5lE_VdroOeflG56sSmDxopPEG3bFlSu1eowyBfxtu0_CuVd-M42RU75Zc4Gsj6uV77MBtbMrf4_7M_NUTSgoIF3fRqxrj0NzihIBg",
- emptyKeyFunc,
- map[string]interface{}{"foo": "bar"},
- false,
- jwt.ValidationErrorSignatureInvalid,
- nil,
- },
- {
- "basic errorkey",
- "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJmb28iOiJiYXIifQ.FhkiHkoESI_cG3NPigFrxEk9Z60_oXrOT2vGm9Pn6RDgYNovYORQmmA0zs1AoAOf09ly2Nx2YAg6ABqAYga1AcMFkJljwxTT5fYphTuqpWdy4BELeSYJx5Ty2gmr8e7RonuUztrdD5WfPqLKMm1Ozp_T6zALpRmwTIW0QPnaBXaQD90FplAg46Iy1UlDKr-Eupy0i5SLch5Q-p2ZpaL_5fnTIUDlxC3pWhJTyx_71qDI-mAA_5lE_VdroOeflG56sSmDxopPEG3bFlSu1eowyBfxtu0_CuVd-M42RU75Zc4Gsj6uV77MBtbMrf4_7M_NUTSgoIF3fRqxrj0NzihIBg",
- errorKeyFunc,
- map[string]interface{}{"foo": "bar"},
- false,
- jwt.ValidationErrorUnverifiable,
- nil,
- },
- {
- "invalid signing method",
- "",
- defaultKeyFunc,
- map[string]interface{}{"foo": "bar"},
- false,
- jwt.ValidationErrorSignatureInvalid,
- &jwt.Parser{ValidMethods: []string{"HS256"}},
- },
- {
- "valid signing method",
- "",
- defaultKeyFunc,
- map[string]interface{}{"foo": "bar"},
- true,
- 0,
- &jwt.Parser{ValidMethods: []string{"RS256", "HS256"}},
- },
- {
- "JSON Number",
- "",
- defaultKeyFunc,
- map[string]interface{}{"foo": json.Number("123.4")},
- true,
- 0,
- &jwt.Parser{UseJSONNumber: true},
- },
-}
-
-func init() {
- var e error
- if jwtTestDefaultKey, e = ioutil.ReadFile("test/sample_key.pub"); e != nil {
- panic(e)
- }
-}
-
-func makeSample(c map[string]interface{}) string {
- key, e := ioutil.ReadFile("test/sample_key")
- if e != nil {
- panic(e.Error())
- }
-
- token := jwt.New(jwt.SigningMethodRS256)
- token.Claims = c
- s, e := token.SignedString(key)
-
- if e != nil {
- panic(e.Error())
- }
-
- return s
-}
-
-func TestParser_Parse(t *testing.T) {
- for _, data := range jwtTestData {
- if data.tokenString == "" {
- data.tokenString = makeSample(data.claims)
- }
-
- var token *jwt.Token
- var err error
- if data.parser != nil {
- token, err = data.parser.Parse(data.tokenString, data.keyfunc)
- } else {
- token, err = jwt.Parse(data.tokenString, data.keyfunc)
- }
-
- if !reflect.DeepEqual(data.claims, token.Claims) {
- t.Errorf("[%v] Claims mismatch. Expecting: %v Got: %v", data.name, data.claims, token.Claims)
- }
- if data.valid && err != nil {
- t.Errorf("[%v] Error while verifying token: %T:%v", data.name, err, err)
- }
- if !data.valid && err == nil {
- t.Errorf("[%v] Invalid token passed validation", data.name)
- }
- if data.errors != 0 {
- if err == nil {
- t.Errorf("[%v] Expecting error. Didn't get one.", data.name)
- } else {
- // compare the bitfield part of the error
- if e := err.(*jwt.ValidationError).Errors; e != data.errors {
- t.Errorf("[%v] Errors don't match expectation. %v != %v", data.name, e, data.errors)
- }
- }
- }
- if data.valid && token.Signature == "" {
- t.Errorf("[%v] Signature is left unpopulated after parsing", data.name)
- }
- }
-}
-
-func TestParseRequest(t *testing.T) {
- // Bearer token request
- for _, data := range jwtTestData {
- // FIXME: custom parsers are not supported by this helper. skip tests that require them
- if data.parser != nil {
- t.Logf("Skipping [%v]. Custom parsers are not supported by ParseRequest", data.name)
- continue
- }
-
- if data.tokenString == "" {
- data.tokenString = makeSample(data.claims)
- }
-
- r, _ := http.NewRequest("GET", "/", nil)
- r.Header.Set("Authorization", fmt.Sprintf("Bearer %v", data.tokenString))
- token, err := jwt.ParseFromRequest(r, data.keyfunc)
-
- if token == nil {
- t.Errorf("[%v] Token was not found: %v", data.name, err)
- continue
- }
- if !reflect.DeepEqual(data.claims, token.Claims) {
- t.Errorf("[%v] Claims mismatch. Expecting: %v Got: %v", data.name, data.claims, token.Claims)
- }
- if data.valid && err != nil {
- t.Errorf("[%v] Error while verifying token: %v", data.name, err)
- }
- if !data.valid && err == nil {
- t.Errorf("[%v] Invalid token passed validation", data.name)
- }
- }
-}
-
-// Helper method for benchmarking various methods
-func benchmarkSigning(b *testing.B, method jwt.SigningMethod, key interface{}) {
- t := jwt.New(method)
- b.RunParallel(func(pb *testing.PB) {
- for pb.Next() {
- if _, err := t.SignedString(key); err != nil {
- b.Fatal(err)
- }
- }
- })
-
-}
diff --git a/vendor/github.com/dgrijalva/jwt-go/request/doc.go b/vendor/github.com/dgrijalva/jwt-go/request/doc.go
new file mode 100644
index 000000000..c01069c98
--- /dev/null
+++ b/vendor/github.com/dgrijalva/jwt-go/request/doc.go
@@ -0,0 +1,7 @@
+// Utility package for extracting JWT tokens from
+// HTTP requests.
+//
+// The main function is ParseFromRequest and it's WithClaims variant.
+// See examples for how to use the various Extractor implementations
+// or roll your own.
+package request
diff --git a/vendor/github.com/dgrijalva/jwt-go/request/extractor.go b/vendor/github.com/dgrijalva/jwt-go/request/extractor.go
new file mode 100644
index 000000000..14414fe2f
--- /dev/null
+++ b/vendor/github.com/dgrijalva/jwt-go/request/extractor.go
@@ -0,0 +1,81 @@
+package request
+
+import (
+ "errors"
+ "net/http"
+)
+
+// Errors
+var (
+ ErrNoTokenInRequest = errors.New("no token present in request")
+)
+
+// Interface for extracting a token from an HTTP request.
+// The ExtractToken method should return a token string or an error.
+// If no token is present, you must return ErrNoTokenInRequest.
+type Extractor interface {
+ ExtractToken(*http.Request) (string, error)
+}
+
+// Extractor for finding a token in a header. Looks at each specified
+// header in order until there's a match
+type HeaderExtractor []string
+
+func (e HeaderExtractor) ExtractToken(req *http.Request) (string, error) {
+ // loop over header names and return the first one that contains data
+ for _, header := range e {
+ if ah := req.Header.Get(header); ah != "" {
+ return ah, nil
+ }
+ }
+ return "", ErrNoTokenInRequest
+}
+
+// Extract token from request arguments. This includes a POSTed form or
+// GET URL arguments. Argument names are tried in order until there's a match.
+// This extractor calls `ParseMultipartForm` on the request
+type ArgumentExtractor []string
+
+func (e ArgumentExtractor) ExtractToken(req *http.Request) (string, error) {
+ // Make sure form is parsed
+ req.ParseMultipartForm(10e6)
+
+ // loop over arg names and return the first one that contains data
+ for _, arg := range e {
+ if ah := req.Form.Get(arg); ah != "" {
+ return ah, nil
+ }
+ }
+
+ return "", ErrNoTokenInRequest
+}
+
+// Tries Extractors in order until one returns a token string or an error occurs
+type MultiExtractor []Extractor
+
+func (e MultiExtractor) ExtractToken(req *http.Request) (string, error) {
+ // loop over header names and return the first one that contains data
+ for _, extractor := range e {
+ if tok, err := extractor.ExtractToken(req); tok != "" {
+ return tok, nil
+ } else if err != ErrNoTokenInRequest {
+ return "", err
+ }
+ }
+ return "", ErrNoTokenInRequest
+}
+
+// Wrap an Extractor in this to post-process the value before it's handed off.
+// See AuthorizationHeaderExtractor for an example
+type PostExtractionFilter struct {
+ Extractor
+ Filter func(string) (string, error)
+}
+
+func (e *PostExtractionFilter) ExtractToken(req *http.Request) (string, error) {
+ if tok, err := e.Extractor.ExtractToken(req); tok != "" {
+ return e.Filter(tok)
+ } else {
+ return "", err
+ }
+}
diff --git a/vendor/github.com/dgrijalva/jwt-go/request/oauth2.go b/vendor/github.com/dgrijalva/jwt-go/request/oauth2.go
new file mode 100644
index 000000000..5948694a5
--- /dev/null
+++ b/vendor/github.com/dgrijalva/jwt-go/request/oauth2.go
@@ -0,0 +1,28 @@
+package request
+
+import (
+ "strings"
+)
+
+// Strips 'Bearer ' prefix from bearer token string
+func stripBearerPrefixFromTokenString(tok string) (string, error) {
+ // Should be a bearer token
+ if len(tok) > 6 && strings.ToUpper(tok[0:7]) == "BEARER " {
+ return tok[7:], nil
+ }
+ return tok, nil
+}
+
+// Extract bearer token from Authorization header
+// Uses PostExtractionFilter to strip "Bearer " prefix from header
+var AuthorizationHeaderExtractor = &PostExtractionFilter{
+ HeaderExtractor{"Authorization"},
+ stripBearerPrefixFromTokenString,
+}
+
+// Extractor for OAuth2 access tokens. Looks in 'Authorization'
+// header then 'access_token' argument for a token.
+var OAuth2Extractor = &MultiExtractor{
+ AuthorizationHeaderExtractor,
+ ArgumentExtractor{"access_token"},
+}
diff --git a/vendor/github.com/dgrijalva/jwt-go/request/request.go b/vendor/github.com/dgrijalva/jwt-go/request/request.go
new file mode 100644
index 000000000..1807b3965
--- /dev/null
+++ b/vendor/github.com/dgrijalva/jwt-go/request/request.go
@@ -0,0 +1,24 @@
+package request
+
+import (
+ "github.com/dgrijalva/jwt-go"
+ "net/http"
+)
+
+// Extract and parse a JWT token from an HTTP request.
+// This behaves the same as Parse, but accepts a request and an extractor
+// instead of a token string. The Extractor interface allows you to define
+// the logic for extracting a token. Several useful implementations are provided.
+func ParseFromRequest(req *http.Request, extractor Extractor, keyFunc jwt.Keyfunc) (token *jwt.Token, err error) {
+ return ParseFromRequestWithClaims(req, extractor, jwt.MapClaims{}, keyFunc)
+}
+
+// ParseFromRequest but with custom Claims type
+func ParseFromRequestWithClaims(req *http.Request, extractor Extractor, claims jwt.Claims, keyFunc jwt.Keyfunc) (token *jwt.Token, err error) {
+ // Extract token from request
+ if tokStr, err := extractor.ExtractToken(req); err == nil {
+ return jwt.ParseWithClaims(tokStr, claims, keyFunc)
+ } else {
+ return nil, err
+ }
+}
diff --git a/vendor/github.com/dgrijalva/jwt-go/rsa.go b/vendor/github.com/dgrijalva/jwt-go/rsa.go
index cddffced5..0ae0b1984 100644
--- a/vendor/github.com/dgrijalva/jwt-go/rsa.go
+++ b/vendor/github.com/dgrijalva/jwt-go/rsa.go
@@ -44,8 +44,7 @@ func (m *SigningMethodRSA) Alg() string {
}
// Implements the Verify method from SigningMethod
-// For this signing method, must be either a PEM encoded PKCS1 or PKCS8 RSA public key as
-// []byte, or an rsa.PublicKey structure.
+// For this signing method, must be an rsa.PublicKey structure.
func (m *SigningMethodRSA) Verify(signingString, signature string, key interface{}) error {
var err error
@@ -56,16 +55,10 @@ func (m *SigningMethodRSA) Verify(signingString, signature string, key interface
}
var rsaKey *rsa.PublicKey
+ var ok bool
- switch k := key.(type) {
- case []byte:
- if rsaKey, err = ParseRSAPublicKeyFromPEM(k); err != nil {
- return err
- }
- case *rsa.PublicKey:
- rsaKey = k
- default:
- return ErrInvalidKey
+ if rsaKey, ok = key.(*rsa.PublicKey); !ok {
+ return ErrInvalidKeyType
}
// Create hasher
@@ -80,20 +73,13 @@ func (m *SigningMethodRSA) Verify(signingString, signature string, key interface
}
// Implements the Sign method from SigningMethod
-// For this signing method, must be either a PEM encoded PKCS1 or PKCS8 RSA private key as
-// []byte, or an rsa.PrivateKey structure.
+// For this signing method, must be an rsa.PrivateKey structure.
func (m *SigningMethodRSA) Sign(signingString string, key interface{}) (string, error) {
- var err error
var rsaKey *rsa.PrivateKey
+ var ok bool
- switch k := key.(type) {
- case []byte:
- if rsaKey, err = ParseRSAPrivateKeyFromPEM(k); err != nil {
- return "", err
- }
- case *rsa.PrivateKey:
- rsaKey = k
- default:
+ // Validate type of key
+ if rsaKey, ok = key.(*rsa.PrivateKey); !ok {
return "", ErrInvalidKey
}
diff --git a/vendor/github.com/dgrijalva/jwt-go/rsa_pss.go b/vendor/github.com/dgrijalva/jwt-go/rsa_pss.go
index b5b707350..10ee9db8a 100644
--- a/vendor/github.com/dgrijalva/jwt-go/rsa_pss.go
+++ b/vendor/github.com/dgrijalva/jwt-go/rsa_pss.go
@@ -106,7 +106,7 @@ func (m *SigningMethodRSAPSS) Sign(signingString string, key interface{}) (strin
case *rsa.PrivateKey:
rsaKey = k
default:
- return "", ErrInvalidKey
+ return "", ErrInvalidKeyType
}
// Create the hasher
diff --git a/vendor/github.com/dgrijalva/jwt-go/rsa_pss_test.go b/vendor/github.com/dgrijalva/jwt-go/rsa_pss_test.go
deleted file mode 100644
index 9045aaf34..000000000
--- a/vendor/github.com/dgrijalva/jwt-go/rsa_pss_test.go
+++ /dev/null
@@ -1,96 +0,0 @@
-// +build go1.4
-
-package jwt_test
-
-import (
- "crypto/rsa"
- "io/ioutil"
- "strings"
- "testing"
-
- "github.com/dgrijalva/jwt-go"
-)
-
-var rsaPSSTestData = []struct {
- name string
- tokenString string
- alg string
- claims map[string]interface{}
- valid bool
-}{
- {
- "Basic PS256",
- "eyJhbGciOiJQUzI1NiIsInR5cCI6IkpXVCJ9.eyJmb28iOiJiYXIifQ.PPG4xyDVY8ffp4CcxofNmsTDXsrVG2npdQuibLhJbv4ClyPTUtR5giNSvuxo03kB6I8VXVr0Y9X7UxhJVEoJOmULAwRWaUsDnIewQa101cVhMa6iR8X37kfFoiZ6NkS-c7henVkkQWu2HtotkEtQvN5hFlk8IevXXPmvZlhQhwzB1sGzGYnoi1zOfuL98d3BIjUjtlwii5w6gYG2AEEzp7HnHCsb3jIwUPdq86Oe6hIFjtBwduIK90ca4UqzARpcfwxHwVLMpatKask00AgGVI0ysdk0BLMjmLutquD03XbThHScC2C2_Pp4cHWgMzvbgLU2RYYZcZRKr46QeNgz9w",
- "PS256",
- map[string]interface{}{"foo": "bar"},
- true,
- },
- {
- "Basic PS384",
- "eyJhbGciOiJQUzM4NCIsInR5cCI6IkpXVCJ9.eyJmb28iOiJiYXIifQ.w7-qqgj97gK4fJsq_DCqdYQiylJjzWONvD0qWWWhqEOFk2P1eDULPnqHRnjgTXoO4HAw4YIWCsZPet7nR3Xxq4ZhMqvKW8b7KlfRTb9cH8zqFvzMmybQ4jv2hKc3bXYqVow3AoR7hN_CWXI3Dv6Kd2X5xhtxRHI6IL39oTVDUQ74LACe-9t4c3QRPuj6Pq1H4FAT2E2kW_0KOc6EQhCLWEhm2Z2__OZskDC8AiPpP8Kv4k2vB7l0IKQu8Pr4RcNBlqJdq8dA5D3hk5TLxP8V5nG1Ib80MOMMqoS3FQvSLyolFX-R_jZ3-zfq6Ebsqr0yEb0AH2CfsECF7935Pa0FKQ",
- "PS384",
- map[string]interface{}{"foo": "bar"},
- true,
- },
- {
- "Basic PS512",
- "eyJhbGciOiJQUzUxMiIsInR5cCI6IkpXVCJ9.eyJmb28iOiJiYXIifQ.GX1HWGzFaJevuSLavqqFYaW8_TpvcjQ8KfC5fXiSDzSiT9UD9nB_ikSmDNyDILNdtjZLSvVKfXxZJqCfefxAtiozEDDdJthZ-F0uO4SPFHlGiXszvKeodh7BuTWRI2wL9-ZO4mFa8nq3GMeQAfo9cx11i7nfN8n2YNQ9SHGovG7_T_AvaMZB_jT6jkDHpwGR9mz7x1sycckEo6teLdHRnH_ZdlHlxqknmyTu8Odr5Xh0sJFOL8BepWbbvIIn-P161rRHHiDWFv6nhlHwZnVzjx7HQrWSGb6-s2cdLie9QL_8XaMcUpjLkfOMKkDOfHo6AvpL7Jbwi83Z2ZTHjJWB-A",
- "PS512",
- map[string]interface{}{"foo": "bar"},
- true,
- },
- {
- "basic PS256 invalid: foo => bar",
- "eyJhbGciOiJQUzI1NiIsInR5cCI6IkpXVCJ9.eyJmb28iOiJiYXIifQ.PPG4xyDVY8ffp4CcxofNmsTDXsrVG2npdQuibLhJbv4ClyPTUtR5giNSvuxo03kB6I8VXVr0Y9X7UxhJVEoJOmULAwRWaUsDnIewQa101cVhMa6iR8X37kfFoiZ6NkS-c7henVkkQWu2HtotkEtQvN5hFlk8IevXXPmvZlhQhwzB1sGzGYnoi1zOfuL98d3BIjUjtlwii5w6gYG2AEEzp7HnHCsb3jIwUPdq86Oe6hIFjtBwduIK90ca4UqzARpcfwxHwVLMpatKask00AgGVI0ysdk0BLMjmLutquD03XbThHScC2C2_Pp4cHWgMzvbgLU2RYYZcZRKr46QeNgz9W",
- "PS256",
- map[string]interface{}{"foo": "bar"},
- false,
- },
-}
-
-func TestRSAPSSVerify(t *testing.T) {
- var err error
-
- key, _ := ioutil.ReadFile("test/sample_key.pub")
- var rsaPSSKey *rsa.PublicKey
- if rsaPSSKey, err = jwt.ParseRSAPublicKeyFromPEM(key); err != nil {
- t.Errorf("Unable to parse RSA public key: %v", err)
- }
-
- for _, data := range rsaPSSTestData {
- parts := strings.Split(data.tokenString, ".")
-
- method := jwt.GetSigningMethod(data.alg)
- err := method.Verify(strings.Join(parts[0:2], "."), parts[2], rsaPSSKey)
- if data.valid && err != nil {
- t.Errorf("[%v] Error while verifying key: %v", data.name, err)
- }
- if !data.valid && err == nil {
- t.Errorf("[%v] Invalid key passed validation", data.name)
- }
- }
-}
-
-func TestRSAPSSSign(t *testing.T) {
- var err error
-
- key, _ := ioutil.ReadFile("test/sample_key")
- var rsaPSSKey *rsa.PrivateKey
- if rsaPSSKey, err = jwt.ParseRSAPrivateKeyFromPEM(key); err != nil {
- t.Errorf("Unable to parse RSA private key: %v", err)
- }
-
- for _, data := range rsaPSSTestData {
- if data.valid {
- parts := strings.Split(data.tokenString, ".")
- method := jwt.GetSigningMethod(data.alg)
- sig, err := method.Sign(strings.Join(parts[0:2], "."), rsaPSSKey)
- if err != nil {
- t.Errorf("[%v] Error signing token: %v", data.name, err)
- }
- if sig == parts[2] {
- t.Errorf("[%v] Signatures shouldn't match\nnew:\n%v\noriginal:\n%v", data.name, sig, parts[2])
- }
- }
- }
-}
diff --git a/vendor/github.com/dgrijalva/jwt-go/rsa_test.go b/vendor/github.com/dgrijalva/jwt-go/rsa_test.go
deleted file mode 100644
index 13ba1fcdc..000000000
--- a/vendor/github.com/dgrijalva/jwt-go/rsa_test.go
+++ /dev/null
@@ -1,174 +0,0 @@
-package jwt_test
-
-import (
- "github.com/dgrijalva/jwt-go"
- "io/ioutil"
- "strings"
- "testing"
-)
-
-var rsaTestData = []struct {
- name string
- tokenString string
- alg string
- claims map[string]interface{}
- valid bool
-}{
- {
- "Basic RS256",
- "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJmb28iOiJiYXIifQ.FhkiHkoESI_cG3NPigFrxEk9Z60_oXrOT2vGm9Pn6RDgYNovYORQmmA0zs1AoAOf09ly2Nx2YAg6ABqAYga1AcMFkJljwxTT5fYphTuqpWdy4BELeSYJx5Ty2gmr8e7RonuUztrdD5WfPqLKMm1Ozp_T6zALpRmwTIW0QPnaBXaQD90FplAg46Iy1UlDKr-Eupy0i5SLch5Q-p2ZpaL_5fnTIUDlxC3pWhJTyx_71qDI-mAA_5lE_VdroOeflG56sSmDxopPEG3bFlSu1eowyBfxtu0_CuVd-M42RU75Zc4Gsj6uV77MBtbMrf4_7M_NUTSgoIF3fRqxrj0NzihIBg",
- "RS256",
- map[string]interface{}{"foo": "bar"},
- true,
- },
- {
- "Basic RS384",
- "eyJhbGciOiJSUzM4NCIsInR5cCI6IkpXVCJ9.eyJmb28iOiJiYXIifQ.W-jEzRfBigtCWsinvVVuldiuilzVdU5ty0MvpLaSaqK9PlAWWlDQ1VIQ_qSKzwL5IXaZkvZFJXT3yL3n7OUVu7zCNJzdwznbC8Z-b0z2lYvcklJYi2VOFRcGbJtXUqgjk2oGsiqUMUMOLP70TTefkpsgqDxbRh9CDUfpOJgW-dU7cmgaoswe3wjUAUi6B6G2YEaiuXC0XScQYSYVKIzgKXJV8Zw-7AN_DBUI4GkTpsvQ9fVVjZM9csQiEXhYekyrKu1nu_POpQonGd8yqkIyXPECNmmqH5jH4sFiF67XhD7_JpkvLziBpI-uh86evBUadmHhb9Otqw3uV3NTaXLzJw",
- "RS384",
- map[string]interface{}{"foo": "bar"},
- true,
- },
- {
- "Basic RS512",
- "eyJhbGciOiJSUzUxMiIsInR5cCI6IkpXVCJ9.eyJmb28iOiJiYXIifQ.zBlLlmRrUxx4SJPUbV37Q1joRcI9EW13grnKduK3wtYKmDXbgDpF1cZ6B-2Jsm5RB8REmMiLpGms-EjXhgnyh2TSHE-9W2gA_jvshegLWtwRVDX40ODSkTb7OVuaWgiy9y7llvcknFBTIg-FnVPVpXMmeV_pvwQyhaz1SSwSPrDyxEmksz1hq7YONXhXPpGaNbMMeDTNP_1oj8DZaqTIL9TwV8_1wb2Odt_Fy58Ke2RVFijsOLdnyEAjt2n9Mxihu9i3PhNBkkxa2GbnXBfq3kzvZ_xxGGopLdHhJjcGWXO-NiwI9_tiu14NRv4L2xC0ItD9Yz68v2ZIZEp_DuzwRQ",
- "RS512",
- map[string]interface{}{"foo": "bar"},
- true,
- },
- {
- "basic invalid: foo => bar",
- "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJmb28iOiJiYXIifQ.EhkiHkoESI_cG3NPigFrxEk9Z60_oXrOT2vGm9Pn6RDgYNovYORQmmA0zs1AoAOf09ly2Nx2YAg6ABqAYga1AcMFkJljwxTT5fYphTuqpWdy4BELeSYJx5Ty2gmr8e7RonuUztrdD5WfPqLKMm1Ozp_T6zALpRmwTIW0QPnaBXaQD90FplAg46Iy1UlDKr-Eupy0i5SLch5Q-p2ZpaL_5fnTIUDlxC3pWhJTyx_71qDI-mAA_5lE_VdroOeflG56sSmDxopPEG3bFlSu1eowyBfxtu0_CuVd-M42RU75Zc4Gsj6uV77MBtbMrf4_7M_NUTSgoIF3fRqxrj0NzihIBg",
- "RS256",
- map[string]interface{}{"foo": "bar"},
- false,
- },
-}
-
-func TestRSAVerify(t *testing.T) {
- key, _ := ioutil.ReadFile("test/sample_key.pub")
-
- for _, data := range rsaTestData {
- parts := strings.Split(data.tokenString, ".")
-
- method := jwt.GetSigningMethod(data.alg)
- err := method.Verify(strings.Join(parts[0:2], "."), parts[2], key)
- if data.valid && err != nil {
- t.Errorf("[%v] Error while verifying key: %v", data.name, err)
- }
- if !data.valid && err == nil {
- t.Errorf("[%v] Invalid key passed validation", data.name)
- }
- }
-}
-
-func TestRSASign(t *testing.T) {
- key, _ := ioutil.ReadFile("test/sample_key")
-
- for _, data := range rsaTestData {
- if data.valid {
- parts := strings.Split(data.tokenString, ".")
- method := jwt.GetSigningMethod(data.alg)
- sig, err := method.Sign(strings.Join(parts[0:2], "."), key)
- if err != nil {
- t.Errorf("[%v] Error signing token: %v", data.name, err)
- }
- if sig != parts[2] {
- t.Errorf("[%v] Incorrect signature.\nwas:\n%v\nexpecting:\n%v", data.name, sig, parts[2])
- }
- }
- }
-}
-
-func TestRSAVerifyWithPreParsedPrivateKey(t *testing.T) {
- key, _ := ioutil.ReadFile("test/sample_key.pub")
- parsedKey, err := jwt.ParseRSAPublicKeyFromPEM(key)
- if err != nil {
- t.Fatal(err)
- }
- testData := rsaTestData[0]
- parts := strings.Split(testData.tokenString, ".")
- err = jwt.SigningMethodRS256.Verify(strings.Join(parts[0:2], "."), parts[2], parsedKey)
- if err != nil {
- t.Errorf("[%v] Error while verifying key: %v", testData.name, err)
- }
-}
-
-func TestRSAWithPreParsedPrivateKey(t *testing.T) {
- key, _ := ioutil.ReadFile("test/sample_key")
- parsedKey, err := jwt.ParseRSAPrivateKeyFromPEM(key)
- if err != nil {
- t.Fatal(err)
- }
- testData := rsaTestData[0]
- parts := strings.Split(testData.tokenString, ".")
- sig, err := jwt.SigningMethodRS256.Sign(strings.Join(parts[0:2], "."), parsedKey)
- if err != nil {
- t.Errorf("[%v] Error signing token: %v", testData.name, err)
- }
- if sig != parts[2] {
- t.Errorf("[%v] Incorrect signature.\nwas:\n%v\nexpecting:\n%v", testData.name, sig, parts[2])
- }
-}
-
-func TestRSAKeyParsing(t *testing.T) {
- key, _ := ioutil.ReadFile("test/sample_key")
- pubKey, _ := ioutil.ReadFile("test/sample_key.pub")
- badKey := []byte("All your base are belong to key")
-
- // Test parsePrivateKey
- if _, e := jwt.ParseRSAPrivateKeyFromPEM(key); e != nil {
- t.Errorf("Failed to parse valid private key: %v", e)
- }
-
- if k, e := jwt.ParseRSAPrivateKeyFromPEM(pubKey); e == nil {
- t.Errorf("Parsed public key as valid private key: %v", k)
- }
-
- if k, e := jwt.ParseRSAPrivateKeyFromPEM(badKey); e == nil {
- t.Errorf("Parsed invalid key as valid private key: %v", k)
- }
-
- // Test parsePublicKey
- if _, e := jwt.ParseRSAPublicKeyFromPEM(pubKey); e != nil {
- t.Errorf("Failed to parse valid public key: %v", e)
- }
-
- if k, e := jwt.ParseRSAPublicKeyFromPEM(key); e == nil {
- t.Errorf("Parsed private key as valid public key: %v", k)
- }
-
- if k, e := jwt.ParseRSAPublicKeyFromPEM(badKey); e == nil {
- t.Errorf("Parsed invalid key as valid private key: %v", k)
- }
-
-}
-
-func BenchmarkRS256Signing(b *testing.B) {
- key, _ := ioutil.ReadFile("test/sample_key")
- parsedKey, err := jwt.ParseRSAPrivateKeyFromPEM(key)
- if err != nil {
- b.Fatal(err)
- }
-
- benchmarkSigning(b, jwt.SigningMethodRS256, parsedKey)
-}
-
-func BenchmarkRS384Signing(b *testing.B) {
- key, _ := ioutil.ReadFile("test/sample_key")
- parsedKey, err := jwt.ParseRSAPrivateKeyFromPEM(key)
- if err != nil {
- b.Fatal(err)
- }
-
- benchmarkSigning(b, jwt.SigningMethodRS384, parsedKey)
-}
-
-func BenchmarkRS512Signing(b *testing.B) {
- key, _ := ioutil.ReadFile("test/sample_key")
- parsedKey, err := jwt.ParseRSAPrivateKeyFromPEM(key)
- if err != nil {
- b.Fatal(err)
- }
-
- benchmarkSigning(b, jwt.SigningMethodRS512, parsedKey)
-}
diff --git a/vendor/github.com/dgrijalva/jwt-go/rsa_utils.go b/vendor/github.com/dgrijalva/jwt-go/rsa_utils.go
index 6f3b6ff04..213a90dbb 100644
--- a/vendor/github.com/dgrijalva/jwt-go/rsa_utils.go
+++ b/vendor/github.com/dgrijalva/jwt-go/rsa_utils.go
@@ -10,6 +10,7 @@ import (
var (
ErrKeyMustBePEMEncoded = errors.New("Invalid Key: Key must be PEM encoded PKCS1 or PKCS8 private key")
ErrNotRSAPrivateKey = errors.New("Key is not a valid RSA private key")
+ ErrNotRSAPublicKey = errors.New("Key is not a valid RSA public key")
)
// Parse PEM encoded PKCS1 or PKCS8 private key
@@ -61,7 +62,7 @@ func ParseRSAPublicKeyFromPEM(key []byte) (*rsa.PublicKey, error) {
var pkey *rsa.PublicKey
var ok bool
if pkey, ok = parsedKey.(*rsa.PublicKey); !ok {
- return nil, ErrNotRSAPrivateKey
+ return nil, ErrNotRSAPublicKey
}
return pkey, nil
diff --git a/vendor/github.com/dgrijalva/jwt-go/signing_method.go b/vendor/github.com/dgrijalva/jwt-go/signing_method.go
index 12cf0f3d0..ed1f212b2 100644
--- a/vendor/github.com/dgrijalva/jwt-go/signing_method.go
+++ b/vendor/github.com/dgrijalva/jwt-go/signing_method.go
@@ -1,6 +1,11 @@
package jwt
+import (
+ "sync"
+)
+
var signingMethods = map[string]func() SigningMethod{}
+var signingMethodLock = new(sync.RWMutex)
// Implement SigningMethod to add new methods for signing or verifying tokens.
type SigningMethod interface {
@@ -12,11 +17,17 @@ type SigningMethod interface {
// Register the "alg" name and a factory function for signing method.
// This is typically done during init() in the method's implementation
func RegisterSigningMethod(alg string, f func() SigningMethod) {
+ signingMethodLock.Lock()
+ defer signingMethodLock.Unlock()
+
signingMethods[alg] = f
}
// Get a signing method from an "alg" string
func GetSigningMethod(alg string) (method SigningMethod) {
+ signingMethodLock.RLock()
+ defer signingMethodLock.RUnlock()
+
if methodF, ok := signingMethods[alg]; ok {
method = methodF()
}
diff --git a/vendor/github.com/dgrijalva/jwt-go/token.go b/vendor/github.com/dgrijalva/jwt-go/token.go
index d35aaa4a9..d637e0867 100644
--- a/vendor/github.com/dgrijalva/jwt-go/token.go
+++ b/vendor/github.com/dgrijalva/jwt-go/token.go
@@ -3,7 +3,6 @@ package jwt
import (
"encoding/base64"
"encoding/json"
- "net/http"
"strings"
"time"
)
@@ -15,7 +14,7 @@ var TimeFunc = time.Now
// Parse methods use this callback function to supply
// the key for verification. The function receives the parsed,
-// but unverified Token. This allows you to use propries in the
+// but unverified Token. This allows you to use properties in the
// Header of the token (such as `kid`) to identify which key to use.
type Keyfunc func(*Token) (interface{}, error)
@@ -25,19 +24,23 @@ type Token struct {
Raw string // The raw token. Populated when you Parse a token
Method SigningMethod // The signing method used or to be used
Header map[string]interface{} // The first segment of the token
- Claims map[string]interface{} // The second segment of the token
+ Claims Claims // The second segment of the token
Signature string // The third segment of the token. Populated when you Parse a token
Valid bool // Is the token valid? Populated when you Parse/Verify a token
}
// Create a new Token. Takes a signing method
func New(method SigningMethod) *Token {
+ return NewWithClaims(method, MapClaims{})
+}
+
+func NewWithClaims(method SigningMethod, claims Claims) *Token {
return &Token{
Header: map[string]interface{}{
"typ": "JWT",
"alg": method.Alg(),
},
- Claims: make(map[string]interface{}),
+ Claims: claims,
Method: method,
}
}
@@ -63,16 +66,15 @@ func (t *Token) SigningString() (string, error) {
var err error
parts := make([]string, 2)
for i, _ := range parts {
- var source map[string]interface{}
+ var jsonValue []byte
if i == 0 {
- source = t.Header
+ if jsonValue, err = json.Marshal(t.Header); err != nil {
+ return "", err
+ }
} else {
- source = t.Claims
- }
-
- var jsonValue []byte
- if jsonValue, err = json.Marshal(source); err != nil {
- return "", err
+ if jsonValue, err = json.Marshal(t.Claims); err != nil {
+ return "", err
+ }
}
parts[i] = EncodeSegment(jsonValue)
@@ -87,28 +89,8 @@ func Parse(tokenString string, keyFunc Keyfunc) (*Token, error) {
return new(Parser).Parse(tokenString, keyFunc)
}
-// Try to find the token in an http.Request.
-// This method will call ParseMultipartForm if there's no token in the header.
-// Currently, it looks in the Authorization header as well as
-// looking for an 'access_token' request parameter in req.Form.
-func ParseFromRequest(req *http.Request, keyFunc Keyfunc) (token *Token, err error) {
-
- // Look for an Authorization header
- if ah := req.Header.Get("Authorization"); ah != "" {
- // Should be a bearer token
- if len(ah) > 6 && strings.ToUpper(ah[0:6]) == "BEARER" {
- return Parse(ah[7:], keyFunc)
- }
- }
-
- // Look for "access_token" parameter
- req.ParseMultipartForm(10e6)
- if tokStr := req.Form.Get("access_token"); tokStr != "" {
- return Parse(tokStr, keyFunc)
- }
-
- return nil, ErrNoTokenInRequest
-
+func ParseWithClaims(tokenString string, claims Claims, keyFunc Keyfunc) (*Token, error) {
+ return new(Parser).ParseWithClaims(tokenString, claims, keyFunc)
}
// Encode JWT specific base64url encoding with padding stripped
diff --git a/vendor/github.com/dustin/go-humanize/README.markdown b/vendor/github.com/dustin/go-humanize/README.markdown
index f94e8154f..23dfee0ac 100644
--- a/vendor/github.com/dustin/go-humanize/README.markdown
+++ b/vendor/github.com/dustin/go-humanize/README.markdown
@@ -1,4 +1,4 @@
-# Humane Units
+# Humane Units [![Build Status](https://travis-ci.org/dustin/go-humanize.svg?branch=master)](https://travis-ci.org/dustin/go-humanize) [![GoDoc](https://godoc.org/github.com/dustin/go-humanize?status.svg)](https://godoc.org/github.com/dustin/go-humanize)
Just a few functions for helping humanize times and sizes.
@@ -15,7 +15,9 @@ strings like, `83MB` or `79MiB` (whichever you prefer).
Example:
- fmt.Printf("That file is %s.", humanize.Bytes(82854982))
+```go
+fmt.Printf("That file is %s.", humanize.Bytes(82854982))
+```
## Times
@@ -24,7 +26,9 @@ For example, `12 seconds ago` or `3 days from now`.
Example:
- fmt.Printf("This was touched %s", humanize.Time(someTimeInstance))
+```go
+fmt.Printf("This was touched %s", humanize.Time(someTimeInstance))
+```
Thanks to Kyle Lemons for the time implementation from an IRC
conversation one day. It's pretty neat.
@@ -43,7 +47,9 @@ to label ordinals.
Example:
- fmt.Printf("You're my %s best friend.", humanize.Ordinal(193))
+```go
+fmt.Printf("You're my %s best friend.", humanize.Ordinal(193))
+```
## Commas
@@ -57,16 +63,20 @@ Want to shove commas into numbers? Be my guest.
Example:
- fmt.Printf("You owe $%s.\n", humanize.Comma(6582491))
+```go
+fmt.Printf("You owe $%s.\n", humanize.Comma(6582491))
+```
## Ftoa
Nicer float64 formatter that removes trailing zeros.
- fmt.Printf("%f", 2.24) // 2.240000
- fmt.Printf("%s", humanize.Ftoa(2.24)) // 2.24
- fmt.Printf("%f", 2.0) // 2.000000
- fmt.Printf("%s", humanize.Ftoa(2.0)) // 2
+```go
+fmt.Printf("%f", 2.24) // 2.240000
+fmt.Printf("%s", humanize.Ftoa(2.24)) // 2.24
+fmt.Printf("%f", 2.0) // 2.000000
+fmt.Printf("%s", humanize.Ftoa(2.0)) // 2
+```
## SI notation
@@ -74,8 +84,9 @@ Format numbers with [SI notation][sinotation].
Example:
- humanize.SI(0.00000000223, "M") // 2.23nM
-
+```go
+humanize.SI(0.00000000223, "M") // 2.23nM
+```
[odisc]: https://groups.google.com/d/topic/golang-nuts/l8NhI74jl-4/discussion
[sinotation]: http://en.wikipedia.org/wiki/Metric_prefix
diff --git a/vendor/github.com/dustin/go-humanize/bigbytes.go b/vendor/github.com/dustin/go-humanize/bigbytes.go
index e4a814a90..67ea5c823 100644
--- a/vendor/github.com/dustin/go-humanize/bigbytes.go
+++ b/vendor/github.com/dustin/go-humanize/bigbytes.go
@@ -95,14 +95,14 @@ var ten = big.NewInt(10)
func humanateBigBytes(s, base *big.Int, sizes []string) string {
if s.Cmp(ten) < 0 {
- return fmt.Sprintf("%dB", s)
+ return fmt.Sprintf("%d B", s)
}
c := (&big.Int{}).Set(s)
val, mag := oomm(c, base, len(sizes)-1)
suffix := sizes[mag]
- f := "%.0f%s"
+ f := "%.0f %s"
if val < 10 {
- f = "%.1f%s"
+ f = "%.1f %s"
}
return fmt.Sprintf(f, val, suffix)
diff --git a/vendor/github.com/dustin/go-humanize/bytes.go b/vendor/github.com/dustin/go-humanize/bytes.go
index b7a77b529..dacbb9c1e 100644
--- a/vendor/github.com/dustin/go-humanize/bytes.go
+++ b/vendor/github.com/dustin/go-humanize/bytes.go
@@ -67,14 +67,14 @@ func logn(n, b float64) float64 {
func humanateBytes(s uint64, base float64, sizes []string) string {
if s < 10 {
- return fmt.Sprintf("%dB", s)
+ return fmt.Sprintf("%d B", s)
}
e := math.Floor(logn(float64(s), base))
suffix := sizes[int(e)]
val := math.Floor(float64(s)/math.Pow(base, e)*10+0.5) / 10
- f := "%.0f%s"
+ f := "%.0f %s"
if val < 10 {
- f = "%.1f%s"
+ f = "%.1f %s"
}
return fmt.Sprintf(f, val, suffix)
diff --git a/vendor/github.com/dustin/go-humanize/comma.go b/vendor/github.com/dustin/go-humanize/comma.go
index b65ea6fa7..74f446b67 100644
--- a/vendor/github.com/dustin/go-humanize/comma.go
+++ b/vendor/github.com/dustin/go-humanize/comma.go
@@ -39,7 +39,7 @@ func Comma(v int64) string {
// Commaf produces a string form of the given number in base 10 with
// commas after every three orders of magnitude.
//
-// e.g. Comma(834142.32) -> 834,142.32
+// e.g. Commaf(834142.32) -> 834,142.32
func Commaf(v float64) string {
buf := &bytes.Buffer{}
if v < 0 {
diff --git a/vendor/github.com/dustin/go-humanize/commaf.go b/vendor/github.com/dustin/go-humanize/commaf.go
new file mode 100644
index 000000000..620690dec
--- /dev/null
+++ b/vendor/github.com/dustin/go-humanize/commaf.go
@@ -0,0 +1,40 @@
+// +build go1.6
+
+package humanize
+
+import (
+ "bytes"
+ "math/big"
+ "strings"
+)
+
+// BigCommaf produces a string form of the given big.Float in base 10
+// with commas after every three orders of magnitude.
+func BigCommaf(v *big.Float) string {
+ buf := &bytes.Buffer{}
+ if v.Sign() < 0 {
+ buf.Write([]byte{'-'})
+ v.Abs(v)
+ }
+
+ comma := []byte{','}
+
+ parts := strings.Split(v.Text('f', -1), ".")
+ pos := 0
+ if len(parts[0])%3 != 0 {
+ pos += len(parts[0]) % 3
+ buf.WriteString(parts[0][:pos])
+ buf.Write(comma)
+ }
+ for ; pos < len(parts[0]); pos += 3 {
+ buf.WriteString(parts[0][pos : pos+3])
+ buf.Write(comma)
+ }
+ buf.Truncate(buf.Len() - 1)
+
+ if len(parts) > 1 {
+ buf.Write([]byte{'.'})
+ buf.WriteString(parts[1])
+ }
+ return buf.String()
+}
diff --git a/vendor/github.com/dustin/go-humanize/si.go b/vendor/github.com/dustin/go-humanize/si.go
index dee8b765a..9cce4e8d3 100644
--- a/vendor/github.com/dustin/go-humanize/si.go
+++ b/vendor/github.com/dustin/go-humanize/si.go
@@ -41,7 +41,7 @@ func revfmap(in map[float64]string) map[string]float64 {
var riParseRegex *regexp.Regexp
func init() {
- ri := `^([0-9.]+)([`
+ ri := `^([\-0-9.]+)\s?([`
for _, v := range siPrefixTable {
ri += v
}
@@ -61,18 +61,21 @@ func ComputeSI(input float64) (float64, string) {
if input == 0 {
return 0, ""
}
- exponent := math.Floor(logn(input, 10))
+ mag := math.Abs(input)
+ exponent := math.Floor(logn(mag, 10))
exponent = math.Floor(exponent/3) * 3
- value := input / math.Pow(10, exponent)
+ value := mag / math.Pow(10, exponent)
// Handle special case where value is exactly 1000.0
// Should return 1M instead of 1000k
if value == 1000.0 {
exponent += 3
- value = input / math.Pow(10, exponent)
+ value = mag / math.Pow(10, exponent)
}
+ value = math.Copysign(value, input)
+
prefix := siPrefixTable[exponent]
return value, prefix
}
@@ -87,7 +90,7 @@ func ComputeSI(input float64) (float64, string) {
// e.g. SI(2.2345e-12, "F") -> 2.2345pF
func SI(input float64, unit string) string {
value, prefix := ComputeSI(input)
- return Ftoa(value) + prefix + unit
+ return Ftoa(value) + " " + prefix + unit
}
var errInvalid = errors.New("invalid input")
diff --git a/vendor/github.com/dustin/go-humanize/times.go b/vendor/github.com/dustin/go-humanize/times.go
index 592ebe1d6..49906b372 100644
--- a/vendor/github.com/dustin/go-humanize/times.go
+++ b/vendor/github.com/dustin/go-humanize/times.go
@@ -76,7 +76,6 @@ func RelTime(a, b time.Time, albl, blbl string) string {
for _, ch := range mag.format {
if escaped {
switch ch {
- case '%':
case 's':
args = append(args, lbl)
case 'd':
diff --git a/vendor/github.com/fatih/color/README.md b/vendor/github.com/fatih/color/README.md
index cb77aea54..0921f98a5 100644
--- a/vendor/github.com/fatih/color/README.md
+++ b/vendor/github.com/fatih/color/README.md
@@ -2,7 +2,10 @@
-Color lets you use colorized outputs in terms of [ANSI Escape Codes](http://en.wikipedia.org/wiki/ANSI_escape_code#Colors) in Go (Golang). It has support for Windows too! The API can be used in several ways, pick one that suits you.
+Color lets you use colorized outputs in terms of [ANSI Escape
+Codes](http://en.wikipedia.org/wiki/ANSI_escape_code#Colors) in Go (Golang). It
+has support for Windows too! The API can be used in several ways, pick one that
+suits you.
diff --git a/vendor/github.com/gorilla/handlers/cors.go b/vendor/github.com/gorilla/handlers/cors.go
index d4229a5d9..1f92d1ad4 100644
--- a/vendor/github.com/gorilla/handlers/cors.go
+++ b/vendor/github.com/gorilla/handlers/cors.go
@@ -112,6 +112,9 @@ func (ch *cors) ServeHTTP(w http.ResponseWriter, r *http.Request) {
w.Header().Set(corsAllowOriginHeader, origin)
+ if r.Method == corsOptionMethod {
+ return
+ }
ch.h.ServeHTTP(w, r)
}
diff --git a/vendor/github.com/gorilla/mux/README.md b/vendor/github.com/gorilla/mux/README.md
index 55dd4e59a..960ef7c15 100644
--- a/vendor/github.com/gorilla/mux/README.md
+++ b/vendor/github.com/gorilla/mux/README.md
@@ -1,218 +1,225 @@
mux
===
[![GoDoc](https://godoc.org/github.com/gorilla/mux?status.svg)](https://godoc.org/github.com/gorilla/mux)
-[![Build Status](https://travis-ci.org/gorilla/mux.png?branch=master)](https://travis-ci.org/gorilla/mux)
-
-Package gorilla/mux implements a request router and dispatcher.
-
-The name mux stands for "HTTP request multiplexer". Like the standard
-http.ServeMux, mux.Router matches incoming requests against a list of
-registered routes and calls a handler for the route that matches the URL
-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.
- * Registered URLs can be built, or "reversed", which helps maintaining
- references to resources.
- * Routes can be used as subrouters: nested routes are only tested if the
- parent route matches. This is useful to define groups of routes that
- share common conditions like a host, a path prefix or other repeated
- attributes. As a bonus, this optimizes request matching.
- * It implements the http.Handler interface so it is compatible with the
- standard http.ServeMux.
+[![Build Status](https://travis-ci.org/gorilla/mux.svg?branch=master)](https://travis-ci.org/gorilla/mux)
-Let's start registering a couple of URL paths and handlers:
+http://www.gorillatoolkit.org/pkg/mux
+
+Package `gorilla/mux` implements a request router and dispatcher.
- func main() {
- r := mux.NewRouter()
- r.HandleFunc("/", HomeHandler)
- r.HandleFunc("/products", ProductsHandler)
- r.HandleFunc("/articles", ArticlesHandler)
- http.Handle("/", r)
- }
+The name mux stands for "HTTP request multiplexer". Like the standard `http.ServeMux`, `mux.Router` matches incoming requests against a list of registered routes and calls a handler for the route that matches the URL or other conditions. The main features are:
-Here we register three routes mapping URL paths to handlers. This is
-equivalent to how http.HandleFunc() works: if an incoming request URL matches
-one of the paths, the corresponding handler is called passing
-(http.ResponseWriter, *http.Request) as parameters.
+* 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.
+* Registered URLs can be built, or "reversed", which helps maintaining references to resources.
+* Routes can be used as subrouters: nested routes are only tested if the parent route matches. This is useful to define groups of routes that share common conditions like a host, a path prefix or other repeated attributes. As a bonus, this optimizes request matching.
+* It implements the `http.Handler` interface so it is compatible with the standard `http.ServeMux`.
-Paths can have variables. They are defined using the format {name} or
-{name:pattern}. If a regular expression pattern is not defined, the matched
-variable will be anything until the next slash. For example:
+Let's start registering a couple of URL paths and handlers:
+```go
+func main() {
r := mux.NewRouter()
- r.HandleFunc("/products/{key}", ProductHandler)
- r.HandleFunc("/articles/{category}/", ArticlesCategoryHandler)
- r.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler)
+ r.HandleFunc("/", HomeHandler)
+ r.HandleFunc("/products", ProductsHandler)
+ r.HandleFunc("/articles", ArticlesHandler)
+ http.Handle("/", r)
+}
+```
-The names are used to create a map of route variables which can be retrieved
-calling mux.Vars():
+Here we register three routes mapping URL paths to handlers. This is equivalent to how `http.HandleFunc()` works: if an incoming request URL matches one of the paths, the corresponding handler is called passing (`http.ResponseWriter`, `*http.Request`) as parameters.
- vars := mux.Vars(request)
- category := vars["category"]
+Paths can have variables. They are defined using the format `{name}` or `{name:pattern}`. If a regular expression pattern is not defined, the matched variable will be anything until the next slash. For example:
-And this is all you need to know about the basic usage. More advanced options
-are explained below.
+```go
+r := mux.NewRouter()
+r.HandleFunc("/products/{key}", ProductHandler)
+r.HandleFunc("/articles/{category}/", ArticlesCategoryHandler)
+r.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler)
+```
-Routes can also be restricted to a domain or subdomain. Just define a host
-pattern to be matched. They can also have variables:
+The names are used to create a map of route variables which can be retrieved calling `mux.Vars()`:
- r := mux.NewRouter()
- // Only matches if domain is "www.example.com".
- r.Host("www.example.com")
- // Matches a dynamic subdomain.
- r.Host("{subdomain:[a-z]+}.domain.com")
+```go
+vars := mux.Vars(request)
+category := vars["category"]
+```
+
+And this is all you need to know about the basic usage. More advanced options are explained below.
+
+Routes can also be restricted to a domain or subdomain. Just define a host pattern to be matched. They can also have variables:
+
+```go
+r := mux.NewRouter()
+// Only matches if domain is "www.example.com".
+r.Host("www.example.com")
+// Matches a dynamic subdomain.
+r.Host("{subdomain:[a-z]+}.domain.com")
+```
There are several other matchers that can be added. To match path prefixes:
- r.PathPrefix("/products/")
+```go
+r.PathPrefix("/products/")
+```
...or HTTP methods:
- r.Methods("GET", "POST")
+```go
+r.Methods("GET", "POST")
+```
...or URL schemes:
- r.Schemes("https")
+```go
+r.Schemes("https")
+```
...or header values:
- r.Headers("X-Requested-With", "XMLHttpRequest")
+```go
+r.Headers("X-Requested-With", "XMLHttpRequest")
+```
...or query values:
- r.Queries("key", "value")
+```go
+r.Queries("key", "value")
+```
...or to use a custom matcher function:
- r.MatcherFunc(func(r *http.Request, rm *RouteMatch) bool {
- return r.ProtoMajor == 0
- })
+```go
+r.MatcherFunc(func(r *http.Request, rm *RouteMatch) bool {
+ return r.ProtoMajor == 0
+})
+```
...and finally, it is possible to combine several matchers in a single route:
- r.HandleFunc("/products", ProductsHandler).
- Host("www.example.com").
- Methods("GET").
- Schemes("http")
+```go
+r.HandleFunc("/products", ProductsHandler).
+ Host("www.example.com").
+ Methods("GET").
+ Schemes("http")
+```
-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".
+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:
+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:
- r := mux.NewRouter()
- s := r.Host("www.example.com").Subrouter()
+```go
+r := mux.NewRouter()
+s := r.Host("www.example.com").Subrouter()
+```
Then register routes in the subrouter:
- s.HandleFunc("/products/", ProductsHandler)
- s.HandleFunc("/products/{key}", ProductHandler)
- s.HandleFunc("/articles/{category}/{id:[0-9]+}"), ArticleHandler)
+```go
+s.HandleFunc("/products/", ProductsHandler)
+s.HandleFunc("/products/{key}", ProductHandler)
+s.HandleFunc("/articles/{category}/{id:[0-9]+}"), ArticleHandler)
+```
-The three URL paths we registered above will only be tested if the domain is
-`www.example.com`, because the subrouter is tested first. This is not
-only convenient, but also optimizes request matching. You can create
-subrouters combining any attribute matchers accepted by a route.
+The three URL paths we registered above will only be tested if the domain is `www.example.com`, because the subrouter is tested first. This is not only convenient, but also optimizes request matching. You can create subrouters combining any attribute matchers accepted by a route.
-Subrouters can be used to create domain or path "namespaces": you define
-subrouters in a central place and then parts of the app can register its
-paths relatively to a given subrouter.
+Subrouters can be used to create domain or path "namespaces": you define subrouters in a central place and then parts of the app can register its paths relatively to a given subrouter.
-There's one more thing about subroutes. When a subrouter has a path prefix,
-the inner routes use it as base for their paths:
+There's one more thing about subroutes. When a subrouter has a path prefix, the inner routes use it as base for their paths:
- r := mux.NewRouter()
- s := r.PathPrefix("/products").Subrouter()
- // "/products/"
- s.HandleFunc("/", ProductsHandler)
- // "/products/{key}/"
- s.HandleFunc("/{key}/", ProductHandler)
- // "/products/{key}/details"
- s.HandleFunc("/{key}/details", ProductDetailsHandler)
+```go
+r := mux.NewRouter()
+s := r.PathPrefix("/products").Subrouter()
+// "/products/"
+s.HandleFunc("/", ProductsHandler)
+// "/products/{key}/"
+s.HandleFunc("/{key}/", ProductHandler)
+// "/products/{key}/details"
+s.HandleFunc("/{key}/details", ProductDetailsHandler)
+```
Now let's see how to build registered URLs.
-Routes can be named. All routes that define a name can have their URLs built,
-or "reversed". We define a name calling Name() on a route. For example:
+Routes can be named. All routes that define a name can have their URLs built, or "reversed". We define a name calling `Name()` on a route. For example:
- r := mux.NewRouter()
- r.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler).
- Name("article")
+```go
+r := mux.NewRouter()
+r.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler).
+ Name("article")
+```
-To build a URL, get the route and call the URL() method, passing a sequence of
-key/value pairs for the route variables. For the previous route, we would do:
+To build a URL, get the route and call the `URL()` method, passing a sequence of key/value pairs for the route variables. For the previous route, we would do:
- url, err := r.Get("article").URL("category", "technology", "id", "42")
+```go
+url, err := r.Get("article").URL("category", "technology", "id", "42")
+```
-...and the result will be a url.URL with the following path:
+...and the result will be a `url.URL` with the following path:
- "/articles/technology/42"
+```
+"/articles/technology/42"
+```
This also works for host variables:
- r := mux.NewRouter()
- r.Host("{subdomain}.domain.com").
- Path("/articles/{category}/{id:[0-9]+}").
- HandlerFunc(ArticleHandler).
- Name("article")
-
- // url.String() will be "http://news.domain.com/articles/technology/42"
- url, err := r.Get("article").URL("subdomain", "news",
- "category", "technology",
- "id", "42")
+```go
+r := mux.NewRouter()
+r.Host("{subdomain}.domain.com").
+ Path("/articles/{category}/{id:[0-9]+}").
+ HandlerFunc(ArticleHandler).
+ Name("article")
+
+// url.String() will be "http://news.domain.com/articles/technology/42"
+url, err := r.Get("article").URL("subdomain", "news",
+ "category", "technology",
+ "id", "42")
+```
-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.
+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.
Regex support also exists for matching Headers within a route. For example, we could do:
- r.HeadersRegexp("Content-Type", "application/(text|json)")
-
-...and the route will match both requests with a Content-Type of `application/json` as well as
-`application/text`
+```go
+r.HeadersRegexp("Content-Type", "application/(text|json)")
+```
-There's also a way to build only the URL host or path for a route:
-use the methods URLHost() or URLPath() instead. For the previous route,
-we would do:
+...and the route will match both requests with a Content-Type of `application/json` as well as `application/text`
- // "http://news.domain.com/"
- host, err := r.Get("article").URLHost("subdomain", "news")
+There's also a way to build only the URL host or path for a route: use the methods `URLHost()` or `URLPath()` instead. For the previous route, we would do:
- // "/articles/technology/42"
- path, err := r.Get("article").URLPath("category", "technology", "id", "42")
+```go
+// "http://news.domain.com/"
+host, err := r.Get("article").URLHost("subdomain", "news")
-And if you use subrouters, host and path defined separately can be built
-as well:
+// "/articles/technology/42"
+path, err := r.Get("article").URLPath("category", "technology", "id", "42")
+```
- r := mux.NewRouter()
- s := r.Host("{subdomain}.domain.com").Subrouter()
- s.Path("/articles/{category}/{id:[0-9]+}").
- HandlerFunc(ArticleHandler).
- Name("article")
+And if you use subrouters, host and path defined separately can be built as well:
- // "http://news.domain.com/articles/technology/42"
- url, err := r.Get("article").URL("subdomain", "news",
- "category", "technology",
- "id", "42")
+```go
+r := mux.NewRouter()
+s := r.Host("{subdomain}.domain.com").Subrouter()
+s.Path("/articles/{category}/{id:[0-9]+}").
+ HandlerFunc(ArticleHandler).
+ Name("article")
+
+// "http://news.domain.com/articles/technology/42"
+url, err := r.Get("article").URL("subdomain", "news",
+ "category", "technology",
+ "id", "42")
+```
## Full Example
-Here's a complete, runnable example of a small mux based server:
+Here's a complete, runnable example of a small `mux` based server:
```go
package main
import (
"net/http"
-
+ "log"
"github.com/gorilla/mux"
)
@@ -226,7 +233,7 @@ func main() {
r.HandleFunc("/", YourHandler)
// Bind to a port and pass our router in
- http.ListenAndServe(":8000", r)
+ log.Fatal(http.ListenAndServe(":8000", r))
}
```
diff --git a/vendor/github.com/gorilla/mux/context_gorilla.go b/vendor/github.com/gorilla/mux/context_gorilla.go
new file mode 100644
index 000000000..d7adaa8fa
--- /dev/null
+++ b/vendor/github.com/gorilla/mux/context_gorilla.go
@@ -0,0 +1,26 @@
+// +build !go1.7
+
+package mux
+
+import (
+ "net/http"
+
+ "github.com/gorilla/context"
+)
+
+func contextGet(r *http.Request, key interface{}) interface{} {
+ return context.Get(r, key)
+}
+
+func contextSet(r *http.Request, key, val interface{}) *http.Request {
+ if val == nil {
+ return r
+ }
+
+ context.Set(r, key, val)
+ return r
+}
+
+func contextClear(r *http.Request) {
+ context.Clear(r)
+}
diff --git a/vendor/github.com/gorilla/mux/context_native.go b/vendor/github.com/gorilla/mux/context_native.go
new file mode 100644
index 000000000..209cbea7d
--- /dev/null
+++ b/vendor/github.com/gorilla/mux/context_native.go
@@ -0,0 +1,24 @@
+// +build go1.7
+
+package mux
+
+import (
+ "context"
+ "net/http"
+)
+
+func contextGet(r *http.Request, key interface{}) interface{} {
+ return r.Context().Value(key)
+}
+
+func contextSet(r *http.Request, key, val interface{}) *http.Request {
+ if val == nil {
+ return r
+ }
+
+ return r.WithContext(context.WithValue(r.Context(), key, val))
+}
+
+func contextClear(r *http.Request) {
+ return
+}
diff --git a/vendor/github.com/gorilla/mux/doc.go b/vendor/github.com/gorilla/mux/doc.go
index 49798cb5c..835f5342e 100644
--- a/vendor/github.com/gorilla/mux/doc.go
+++ b/vendor/github.com/gorilla/mux/doc.go
@@ -3,7 +3,7 @@
// license that can be found in the LICENSE file.
/*
-Package gorilla/mux implements a request router and dispatcher.
+Package mux implements a request router and dispatcher.
The name mux stands for "HTTP request multiplexer". Like the standard
http.ServeMux, mux.Router matches incoming requests against a list of
diff --git a/vendor/github.com/gorilla/mux/mux.go b/vendor/github.com/gorilla/mux/mux.go
index 002051fcf..f8c10f3bb 100644
--- a/vendor/github.com/gorilla/mux/mux.go
+++ b/vendor/github.com/gorilla/mux/mux.go
@@ -10,8 +10,6 @@ import (
"net/http"
"path"
"regexp"
-
- "github.com/gorilla/context"
)
// NewRouter returns a new router instance.
@@ -48,7 +46,11 @@ type Router struct {
namedRoutes map[string]*Route
// See Router.StrictSlash(). This defines the flag for new routes.
strictSlash bool
- // If true, do not clear the request context after handling the request
+ // See Router.SkipClean(). This defines the flag for new routes.
+ skipClean bool
+ // If true, do not clear the request context after handling the request.
+ // This has no effect when go1.7+ is used, since the context is stored
+ // on the request itself.
KeepContext bool
}
@@ -59,6 +61,12 @@ func (r *Router) Match(req *http.Request, match *RouteMatch) bool {
return true
}
}
+
+ // Closest match for a router (includes sub-routers)
+ if r.NotFoundHandler != nil {
+ match.Handler = r.NotFoundHandler
+ return true
+ }
return false
}
@@ -67,35 +75,34 @@ func (r *Router) Match(req *http.Request, match *RouteMatch) bool {
// When there is a match, the route variables can be retrieved calling
// mux.Vars(request).
func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
- // Clean path to canonical form and redirect.
- if p := cleanPath(req.URL.Path); p != req.URL.Path {
-
- // Added 3 lines (Philip Schlump) - It was droping the query string and #whatever from query.
- // This matches with fix in go 1.2 r.c. 4 for same problem. Go Issue:
- // http://code.google.com/p/go/issues/detail?id=5252
- url := *req.URL
- url.Path = p
- p = url.String()
-
- w.Header().Set("Location", p)
- w.WriteHeader(http.StatusMovedPermanently)
- return
+ if !r.skipClean {
+ // Clean path to canonical form and redirect.
+ if p := cleanPath(req.URL.Path); p != req.URL.Path {
+
+ // Added 3 lines (Philip Schlump) - It was dropping the query string and #whatever from query.
+ // This matches with fix in go 1.2 r.c. 4 for same problem. Go Issue:
+ // http://code.google.com/p/go/issues/detail?id=5252
+ url := *req.URL
+ url.Path = p
+ p = url.String()
+
+ w.Header().Set("Location", p)
+ w.WriteHeader(http.StatusMovedPermanently)
+ return
+ }
}
var match RouteMatch
var handler http.Handler
if r.Match(req, &match) {
handler = match.Handler
- setVars(req, match.Vars)
- setCurrentRoute(req, match.Route)
+ req = setVars(req, match.Vars)
+ req = setCurrentRoute(req, match.Route)
}
if handler == nil {
- handler = r.NotFoundHandler
- if handler == nil {
- handler = http.NotFoundHandler()
- }
+ handler = http.NotFoundHandler()
}
if !r.KeepContext {
- defer context.Clear(req)
+ defer contextClear(req)
}
handler.ServeHTTP(w, req)
}
@@ -130,6 +137,19 @@ func (r *Router) StrictSlash(value bool) *Router {
return r
}
+// SkipClean defines the path cleaning behaviour for new routes. The initial
+// value is false. Users should be careful about which routes are not cleaned
+//
+// When true, if the route path is "/path//to", it will remain with the double
+// slash. This is helpful if you have a route like: /fetch/http://xkcd.com/534/
+//
+// When false, the path will be cleaned, so /fetch/http://xkcd.com/534/ will
+// become /fetch/http/xkcd.com/534
+func (r *Router) SkipClean(value bool) *Router {
+ r.skipClean = value
+ return r
+}
+
// ----------------------------------------------------------------------------
// parentRoute
// ----------------------------------------------------------------------------
@@ -167,7 +187,7 @@ func (r *Router) buildVars(m map[string]string) map[string]string {
// NewRoute registers an empty route.
func (r *Router) NewRoute() *Route {
- route := &Route{parent: r, strictSlash: r.strictSlash}
+ route := &Route{parent: r, strictSlash: r.strictSlash, skipClean: r.skipClean}
r.routes = append(r.routes, route)
return route
}
@@ -233,7 +253,7 @@ func (r *Router) Schemes(schemes ...string) *Route {
return r.NewRoute().Schemes(schemes...)
}
-// BuildVars registers a new route with a custom function for modifying
+// BuildVarsFunc registers a new route with a custom function for modifying
// route variables before building a URL.
func (r *Router) BuildVarsFunc(f BuildVarsFunc) *Route {
return r.NewRoute().BuildVarsFunc(f)
@@ -305,7 +325,7 @@ const (
// Vars returns the route variables for the current request, if any.
func Vars(r *http.Request) map[string]string {
- if rv := context.Get(r, varsKey); rv != nil {
+ if rv := contextGet(r, varsKey); rv != nil {
return rv.(map[string]string)
}
return nil
@@ -317,18 +337,18 @@ func Vars(r *http.Request) map[string]string {
// after the handler returns, unless the KeepContext option is set on the
// Router.
func CurrentRoute(r *http.Request) *Route {
- if rv := context.Get(r, routeKey); rv != nil {
+ if rv := contextGet(r, routeKey); rv != nil {
return rv.(*Route)
}
return nil
}
-func setVars(r *http.Request, val interface{}) {
- context.Set(r, varsKey, val)
+func setVars(r *http.Request, val interface{}) *http.Request {
+ return contextSet(r, varsKey, val)
}
-func setCurrentRoute(r *http.Request, val interface{}) {
- context.Set(r, routeKey, val)
+func setCurrentRoute(r *http.Request, val interface{}) *http.Request {
+ return contextSet(r, routeKey, val)
}
// ----------------------------------------------------------------------------
@@ -350,6 +370,7 @@ func cleanPath(p string) string {
if p[len(p)-1] == '/' && np != "/" {
np += "/"
}
+
return np
}
@@ -365,6 +386,8 @@ func uniqueVars(s1, s2 []string) error {
return nil
}
+// checkPairs returns the count of strings passed in, and an error if
+// the count is not an even number.
func checkPairs(pairs ...string) (int, error) {
length := len(pairs)
if length%2 != 0 {
@@ -374,7 +397,8 @@ func checkPairs(pairs ...string) (int, error) {
return length, nil
}
-// mapFromPairs converts variadic string parameters to a string map.
+// mapFromPairsToString converts variadic string parameters to a
+// string to string map.
func mapFromPairsToString(pairs ...string) (map[string]string, error) {
length, err := checkPairs(pairs...)
if err != nil {
@@ -387,6 +411,8 @@ func mapFromPairsToString(pairs ...string) (map[string]string, error) {
return m, nil
}
+// mapFromPairsToRegex converts variadic string paramers to a
+// string to regex map.
func mapFromPairsToRegex(pairs ...string) (map[string]*regexp.Regexp, error) {
length, err := checkPairs(pairs...)
if err != nil {
diff --git a/vendor/github.com/gorilla/mux/regexp.go b/vendor/github.com/gorilla/mux/regexp.go
index 06728dd54..08710bc98 100644
--- a/vendor/github.com/gorilla/mux/regexp.go
+++ b/vendor/github.com/gorilla/mux/regexp.go
@@ -73,14 +73,14 @@ func newRouteRegexp(tpl string, matchHost, matchPrefix, matchQuery, strictSlash
tpl[idxs[i]:end])
}
// Build the regexp pattern.
- varIdx := i / 2
- fmt.Fprintf(pattern, "%s(?P<%s>%s)", regexp.QuoteMeta(raw), varGroupName(varIdx), patt)
+ fmt.Fprintf(pattern, "%s(?P<%s>%s)", regexp.QuoteMeta(raw), varGroupName(i/2), patt)
+
// Build the reverse template.
fmt.Fprintf(reverse, "%s%%s", raw)
// Append variable name and compiled pattern.
- varsN[varIdx] = name
- varsR[varIdx], err = regexp.Compile(fmt.Sprintf("^%s$", patt))
+ varsN[i/2] = name
+ varsR[i/2], err = regexp.Compile(fmt.Sprintf("^%s$", patt))
if err != nil {
return nil, err
}
@@ -148,10 +148,11 @@ func (r *routeRegexp) Match(req *http.Request, match *RouteMatch) bool {
if !r.matchHost {
if r.matchQuery {
return r.matchQueryString(req)
- } else {
- return r.regexp.MatchString(req.URL.Path)
}
+
+ return r.regexp.MatchString(req.URL.Path)
}
+
return r.regexp.MatchString(getHost(req))
}
@@ -181,10 +182,10 @@ func (r *routeRegexp) url(values map[string]string) (string, error) {
return rv, nil
}
-// getUrlQuery returns a single query parameter from a request URL.
+// getURLQuery returns a single query parameter from a request URL.
// For a URL with foo=bar&baz=ding, we return only the relevant key
// value pair for the routeRegexp.
-func (r *routeRegexp) getUrlQuery(req *http.Request) string {
+func (r *routeRegexp) getURLQuery(req *http.Request) string {
if !r.matchQuery {
return ""
}
@@ -198,14 +199,14 @@ func (r *routeRegexp) getUrlQuery(req *http.Request) string {
}
func (r *routeRegexp) matchQueryString(req *http.Request) bool {
- return r.regexp.MatchString(r.getUrlQuery(req))
+ return r.regexp.MatchString(r.getURLQuery(req))
}
// braceIndices returns the first level curly brace indices from a string.
// It returns an error in case of unbalanced braces.
func braceIndices(s string) ([]int, error) {
var level, idx int
- idxs := make([]int, 0)
+ var idxs []int
for i := 0; i < len(s); i++ {
switch s[i] {
case '{':
@@ -246,30 +247,17 @@ type routeRegexpGroup struct {
func (v *routeRegexpGroup) setMatch(req *http.Request, m *RouteMatch, r *Route) {
// Store host variables.
if v.host != nil {
- hostVars := v.host.regexp.FindStringSubmatch(getHost(req))
- if hostVars != nil {
- subexpNames := v.host.regexp.SubexpNames()
- varName := 0
- for i, name := range subexpNames[1:] {
- if name != "" && name == varGroupName(varName) {
- m.Vars[v.host.varsN[varName]] = hostVars[i+1]
- varName++
- }
- }
+ host := getHost(req)
+ matches := v.host.regexp.FindStringSubmatchIndex(host)
+ if len(matches) > 0 {
+ extractVars(host, matches, v.host.varsN, m.Vars)
}
}
// Store path variables.
if v.path != nil {
- pathVars := v.path.regexp.FindStringSubmatch(req.URL.Path)
- if pathVars != nil {
- subexpNames := v.path.regexp.SubexpNames()
- varName := 0
- for i, name := range subexpNames[1:] {
- if name != "" && name == varGroupName(varName) {
- m.Vars[v.path.varsN[varName]] = pathVars[i+1]
- varName++
- }
- }
+ matches := v.path.regexp.FindStringSubmatchIndex(req.URL.Path)
+ if len(matches) > 0 {
+ extractVars(req.URL.Path, matches, v.path.varsN, m.Vars)
// Check if we should redirect.
if v.path.strictSlash {
p1 := strings.HasSuffix(req.URL.Path, "/")
@@ -288,16 +276,10 @@ func (v *routeRegexpGroup) setMatch(req *http.Request, m *RouteMatch, r *Route)
}
// Store query string variables.
for _, q := range v.queries {
- queryVars := q.regexp.FindStringSubmatch(q.getUrlQuery(req))
- if queryVars != nil {
- subexpNames := q.regexp.SubexpNames()
- varName := 0
- for i, name := range subexpNames[1:] {
- if name != "" && name == varGroupName(varName) {
- m.Vars[q.varsN[varName]] = queryVars[i+1]
- varName++
- }
- }
+ queryURL := q.getURLQuery(req)
+ matches := q.regexp.FindStringSubmatchIndex(queryURL)
+ if len(matches) > 0 {
+ extractVars(queryURL, matches, q.varsN, m.Vars)
}
}
}
@@ -315,3 +297,16 @@ func getHost(r *http.Request) string {
return host
}
+
+func extractVars(input string, matches []int, names []string, output map[string]string) {
+ matchesCount := 0
+ prevEnd := -1
+ for i := 2; i < len(matches) && matchesCount < len(names); i += 2 {
+ if prevEnd < matches[i+1] {
+ value := input[matches[i]:matches[i+1]]
+ output[names[matchesCount]] = value
+ prevEnd = matches[i+1]
+ matchesCount++
+ }
+ }
+}
diff --git a/vendor/github.com/gorilla/mux/route.go b/vendor/github.com/gorilla/mux/route.go
index 890130460..6c53f9f1d 100644
--- a/vendor/github.com/gorilla/mux/route.go
+++ b/vendor/github.com/gorilla/mux/route.go
@@ -26,6 +26,9 @@ type Route struct {
// If true, when the path pattern is "/path/", accessing "/path" will
// redirect to the former and vice versa.
strictSlash bool
+ // If true, when the path pattern is "/path//to", accessing "/path//to"
+ // will not redirect
+ skipClean bool
// If true, this route never matches: it is only used to build URLs.
buildOnly bool
// The name used to build URLs.
@@ -36,6 +39,10 @@ type Route struct {
buildVarsFunc BuildVarsFunc
}
+func (r *Route) SkipClean() bool {
+ return r.skipClean
+}
+
// Match matches the route against the request.
func (r *Route) Match(req *http.Request, match *RouteMatch) bool {
if r.buildOnly || r.err != nil {
@@ -200,15 +207,7 @@ func (m headerMatcher) Match(r *http.Request, match *RouteMatch) bool {
// "X-Requested-With", "XMLHttpRequest")
//
// The above route will only match if both request header values match.
-// Alternatively, you can provide a regular expression and match the header as follows:
-//
-// r.Headers("Content-Type", "application/(text|json)",
-// "X-Requested-With", "XMLHttpRequest")
-//
-// The above route will the same as the previous example, with the addition of matching
-// application/text as well.
-//
-// It the value is an empty string, it will match any value if the key is set.
+// If the value is an empty string, it will match any value if the key is set.
func (r *Route) Headers(pairs ...string) *Route {
if r.err == nil {
var headers map[string]string
@@ -225,8 +224,9 @@ func (m headerRegexMatcher) Match(r *http.Request, match *RouteMatch) bool {
return matchMapWithRegex(m, r.Header, true)
}
-// Regular expressions can be used with headers as well.
-// It accepts a sequence of key/value pairs, where the value has regex support. For example
+// HeadersRegexp accepts a sequence of key/value pairs, where the value has regex
+// support. For example:
+//
// r := mux.NewRouter()
// r.HeadersRegexp("Content-Type", "application/(text|json)",
// "X-Requested-With", "XMLHttpRequest")
@@ -271,6 +271,7 @@ func (r *Route) Host(tpl string) *Route {
// MatcherFunc is the function signature used by custom matchers.
type MatcherFunc func(*http.Request, *RouteMatch) bool
+// Match returns the match for a given request.
func (m MatcherFunc) Match(r *http.Request, match *RouteMatch) bool {
return m(r, match)
}
@@ -540,6 +541,36 @@ func (r *Route) URLPath(pairs ...string) (*url.URL, error) {
}, nil
}
+// GetPathTemplate returns the template used to build the
+// route match.
+// 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) GetPathTemplate() (string, error) {
+ if r.err != nil {
+ return "", r.err
+ }
+ if r.regexp == nil || r.regexp.path == nil {
+ return "", errors.New("mux: route doesn't have a path")
+ }
+ return r.regexp.path.template, nil
+}
+
+// GetHostTemplate returns the template used to build the
+// route match.
+// 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 host.
+func (r *Route) GetHostTemplate() (string, error) {
+ if r.err != nil {
+ return "", r.err
+ }
+ if r.regexp == nil || r.regexp.host == nil {
+ return "", errors.New("mux: route doesn't have a host")
+ }
+ return r.regexp.host.template, nil
+}
+
// prepareVars converts the route variable pairs into a map. If the route has a
// BuildVarsFunc, it is invoked.
func (r *Route) prepareVars(pairs ...string) (map[string]string, error) {
diff --git a/vendor/github.com/gorilla/rpc/LICENSE b/vendor/github.com/gorilla/rpc/LICENSE
new file mode 100644
index 000000000..0e5fb8728
--- /dev/null
+++ b/vendor/github.com/gorilla/rpc/LICENSE
@@ -0,0 +1,27 @@
+Copyright (c) 2012 Rodrigo Moraes. 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.
+ * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+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
+OWNER 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/rpc/v2/json2/json_test.go b/vendor/github.com/gorilla/rpc/v2/json2/json_test.go
deleted file mode 100644
index d3c192ec2..000000000
--- a/vendor/github.com/gorilla/rpc/v2/json2/json_test.go
+++ /dev/null
@@ -1,173 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Copyright 2012 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 json2
-
-import (
- "bytes"
- "encoding/json"
- "errors"
- "net/http"
- "testing"
-
- "github.com/gorilla/rpc/v2"
-)
-
-// ResponseRecorder is an implementation of http.ResponseWriter that
-// records its mutations for later inspection in tests.
-type ResponseRecorder struct {
- Code int // the HTTP response code from WriteHeader
- HeaderMap http.Header // the HTTP response headers
- Body *bytes.Buffer // if non-nil, the bytes.Buffer to append written data to
- Flushed bool
-}
-
-// NewRecorder returns an initialized ResponseRecorder.
-func NewRecorder() *ResponseRecorder {
- return &ResponseRecorder{
- HeaderMap: make(http.Header),
- Body: new(bytes.Buffer),
- }
-}
-
-// DefaultRemoteAddr is the default remote address to return in RemoteAddr if
-// an explicit DefaultRemoteAddr isn't set on ResponseRecorder.
-const DefaultRemoteAddr = "1.2.3.4"
-
-// Header returns the response headers.
-func (rw *ResponseRecorder) Header() http.Header {
- return rw.HeaderMap
-}
-
-// Write always succeeds and writes to rw.Body, if not nil.
-func (rw *ResponseRecorder) Write(buf []byte) (int, error) {
- if rw.Body != nil {
- rw.Body.Write(buf)
- }
- if rw.Code == 0 {
- rw.Code = http.StatusOK
- }
- return len(buf), nil
-}
-
-// WriteHeader sets rw.Code.
-func (rw *ResponseRecorder) WriteHeader(code int) {
- rw.Code = code
-}
-
-// Flush sets rw.Flushed to true.
-func (rw *ResponseRecorder) Flush() {
- rw.Flushed = true
-}
-
-// ----------------------------------------------------------------------------
-
-var ErrResponseError = errors.New("response error")
-
-type Service1Request struct {
- A int
- B int
-}
-
-type Service1NoParamsRequest struct {
- V string `json:"jsonrpc"`
- M string `json:"method"`
- ID uint64 `json:"id"`
-}
-
-type Service1Response struct {
- Result int
-}
-
-type Service1 struct {
-}
-
-const Service1DefaultResponse = 9999
-
-func (t *Service1) Multiply(r *http.Request, req *Service1Request, res *Service1Response) error {
- if req.A == 0 && req.B == 0 {
- // Sentinel value for test with no params.
- res.Result = Service1DefaultResponse
- } else {
- res.Result = req.A * req.B
- }
- return nil
-}
-
-func (t *Service1) ResponseError(r *http.Request, req *Service1Request, res *Service1Response) error {
- return ErrResponseError
-}
-
-func execute(t *testing.T, s *rpc.Server, method string, req, res interface{}) error {
- if !s.HasMethod(method) {
- t.Fatal("Expected to be registered:", method)
- }
-
- buf, _ := EncodeClientRequest(method, req)
- body := bytes.NewBuffer(buf)
- r, _ := http.NewRequest("POST", "http://localhost:8080/", body)
- r.Header.Set("Content-Type", "application/json")
-
- w := NewRecorder()
- s.ServeHTTP(w, r)
-
- return DecodeClientResponse(w.Body, res)
-}
-
-func executeRaw(t *testing.T, s *rpc.Server, req interface{}, res interface{}) error {
- j, _ := json.Marshal(req)
- r, _ := http.NewRequest("POST", "http://localhost:8080/", bytes.NewBuffer(j))
- r.Header.Set("Content-Type", "application/json")
-
- w := NewRecorder()
- s.ServeHTTP(w, r)
-
- return DecodeClientResponse(w.Body, res)
-}
-
-func TestService(t *testing.T) {
- s := rpc.NewServer()
- s.RegisterCodec(NewCodec(), "application/json")
- s.RegisterService(new(Service1), "")
-
- var res Service1Response
- if err := execute(t, s, "Service1.Multiply", &Service1Request{4, 2}, &res); err != nil {
- t.Error("Expected err to be nil, but got:", err)
- }
- if res.Result != 8 {
- t.Errorf("Wrong response: %v.", res.Result)
- }
-
- if err := execute(t, s, "Service1.ResponseError", &Service1Request{4, 2}, &res); err == nil {
- t.Errorf("Expected to get %q, but got nil", ErrResponseError)
- } else if err.Error() != ErrResponseError.Error() {
- t.Errorf("Expected to get %q, but got %q", ErrResponseError, err)
- }
-
- // No parameters.
- res = Service1Response{}
- if err := executeRaw(t, s, &Service1NoParamsRequest{"2.0", "Service1.Multiply", 1}, &res); err != nil {
- t.Error(err)
- }
- if res.Result != Service1DefaultResponse {
- t.Errorf("Wrong response: got %v, want %v", res.Result, Service1DefaultResponse)
- }
-}
-
-func TestDecodeNullResult(t *testing.T) {
- data := `{"jsonrpc": "2.0", "id": 12345, "result": null}`
- reader := bytes.NewReader([]byte(data))
- var result interface{}
-
- err := DecodeClientResponse(reader, &result)
-
- if err != ErrNullResult {
- t.Error("Expected err no be ErrNullResult, but got:", err)
- }
-
- if result != nil {
- t.Error("Expected result to be nil, but got:", result)
- }
-}
diff --git a/vendor/github.com/gorilla/rpc/v2/json2/server.go b/vendor/github.com/gorilla/rpc/v2/json2/server.go
index e2266b4a5..158e996e8 100644
--- a/vendor/github.com/gorilla/rpc/v2/json2/server.go
+++ b/vendor/github.com/gorilla/rpc/v2/json2/server.go
@@ -123,15 +123,28 @@ func (c *CodecRequest) Method() (string, error) {
return "", c.err
}
-// ReadRe> 4)
case 30 <= n && n <= 37:
- attr = (attr & backgroundMask)
+ attr &= backgroundMask
if (n-30)&1 != 0 {
attr |= foregroundRed
}
@@ -563,7 +573,7 @@ loop:
attr &= backgroundMask
attr |= w.oldattr & foregroundMask
case 40 <= n && n <= 47:
- attr = (attr & foregroundMask)
+ attr &= foregroundMask
if (n-40)&1 != 0 {
attr |= backgroundRed
}
@@ -617,6 +627,22 @@ loop:
procSetConsoleTextAttribute.Call(uintptr(w.handle), uintptr(attr))
}
}
+ case 'h':
+ cs := buf.String()
+ if cs == "?25" {
+ var ci consoleCursorInfo
+ procGetConsoleCursorInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&ci)))
+ ci.visible = 1
+ procSetConsoleCursorInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&ci)))
+ }
+ case 'l':
+ cs := buf.String()
+ if cs == "?25" {
+ var ci consoleCursorInfo
+ procGetConsoleCursorInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&ci)))
+ ci.visible = 0
+ procSetConsoleCursorInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&ci)))
+ }
}
}
return len(data) - w.lastbuf.Len(), nil
diff --git a/vendor/github.com/mattn/go-colorable/noncolorable.go b/vendor/github.com/mattn/go-colorable/noncolorable.go
new file mode 100644
index 000000000..fb976dbd8
--- /dev/null
+++ b/vendor/github.com/mattn/go-colorable/noncolorable.go
@@ -0,0 +1,57 @@
+package colorable
+
+import (
+ "bytes"
+ "fmt"
+ "io"
+)
+
+type NonColorable struct {
+ out io.Writer
+ lastbuf bytes.Buffer
+}
+
+func NewNonColorable(w io.Writer) io.Writer {
+ return &NonColorable{out: w}
+}
+
+func (w *NonColorable) Write(data []byte) (n int, err error) {
+ er := bytes.NewBuffer(data)
+loop:
+ for {
+ c1, _, err := er.ReadRune()
+ if err != nil {
+ break loop
+ }
+ if c1 != 0x1b {
+ fmt.Fprint(w.out, string(c1))
+ continue
+ }
+ c2, _, err := er.ReadRune()
+ if err != nil {
+ w.lastbuf.WriteRune(c1)
+ break loop
+ }
+ if c2 != 0x5b {
+ w.lastbuf.WriteRune(c1)
+ w.lastbuf.WriteRune(c2)
+ continue
+ }
+
+ var buf bytes.Buffer
+ for {
+ c, _, err := er.ReadRune()
+ if err != nil {
+ w.lastbuf.WriteRune(c1)
+ w.lastbuf.WriteRune(c2)
+ w.lastbuf.Write(buf.Bytes())
+ break loop
+ }
+ if ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || c == '@' {
+ break
+ }
+ buf.Write([]byte(string(c)))
+ }
+ }
+ return len(data) - w.lastbuf.Len(), nil
+}
diff --git a/vendor/github.com/mattn/go-isatty/isatty_bsd.go b/vendor/github.com/mattn/go-isatty/isatty_bsd.go
index e6282b529..98ffe86a4 100644
--- a/vendor/github.com/mattn/go-isatty/isatty_bsd.go
+++ b/vendor/github.com/mattn/go-isatty/isatty_bsd.go
@@ -1,4 +1,5 @@
// +build darwin freebsd openbsd netbsd
+// +build !appengine
package isatty
diff --git a/vendor/github.com/mattn/go-isatty/isatty_linux.go b/vendor/github.com/mattn/go-isatty/isatty_linux.go
index 8b361d7fb..9d24bac1d 100644
--- a/vendor/github.com/mattn/go-isatty/isatty_linux.go
+++ b/vendor/github.com/mattn/go-isatty/isatty_linux.go
@@ -1,4 +1,5 @@
// +build linux
+// +build !appengine
package isatty
diff --git a/vendor/github.com/mattn/go-isatty/isatty_solaris.go b/vendor/github.com/mattn/go-isatty/isatty_solaris.go
new file mode 100644
index 000000000..1f0c6bf53
--- /dev/null
+++ b/vendor/github.com/mattn/go-isatty/isatty_solaris.go
@@ -0,0 +1,16 @@
+// +build solaris
+// +build !appengine
+
+package isatty
+
+import (
+ "golang.org/x/sys/unix"
+)
+
+// IsTerminal returns true if the given file descriptor is a terminal.
+// see: http://src.illumos.org/source/xref/illumos-gate/usr/src/lib/libbc/libc/gen/common/isatty.c
+func IsTerminal(fd uintptr) bool {
+ var termio unix.Termio
+ err := unix.IoctlSetTermio(int(fd), unix.TCGETA, &termio)
+ return err == nil
+}
diff --git a/vendor/github.com/mattn/go-isatty/isatty_windows.go b/vendor/github.com/mattn/go-isatty/isatty_windows.go
index 562ee39ca..83c398b16 100644
--- a/vendor/github.com/mattn/go-isatty/isatty_windows.go
+++ b/vendor/github.com/mattn/go-isatty/isatty_windows.go
@@ -1,4 +1,5 @@
// +build windows
+// +build !appengine
package isatty
diff --git a/vendor/github.com/rs/cors/README.md b/vendor/github.com/rs/cors/README.md
index 521d903d1..4bf56724e 100644
--- a/vendor/github.com/rs/cors/README.md
+++ b/vendor/github.com/rs/cors/README.md
@@ -1,4 +1,4 @@
-# Go CORS handler [![godoc](http://img.shields.io/badge/godoc-reference-blue.svg?style=flat)](https://godoc.org/github.com/rs/cors) [![license](http://img.shields.io/badge/license-MIT-red.svg?style=flat)](https://raw.githubusercontent.com/rs/cors/master/LICENSE) [![build](https://img.shields.io/travis/rs/cors.svg?style=flat)](https://travis-ci.org/rs/cors)
+# Go CORS handler [![godoc](http://img.shields.io/badge/godoc-reference-blue.svg?style=flat)](https://godoc.org/github.com/rs/cors) [![license](http://img.shields.io/badge/license-MIT-red.svg?style=flat)](https://raw.githubusercontent.com/rs/cors/master/LICENSE) [![build](https://img.shields.io/travis/rs/cors.svg?style=flat)](https://travis-ci.org/rs/cors) [![Coverage](http://gocover.io/_badge/github.com/rs/cors)](http://gocover.io/github.com/rs/cors)
CORS is a `net/http` handler implementing [Cross Origin Resource Sharing W3 specification](http://www.w3.org/TR/cors/) in Golang.
diff --git a/vendor/github.com/rs/cors/cors.go b/vendor/github.com/rs/cors/cors.go
index dffa73fa0..4bb22d8fc 100644
--- a/vendor/github.com/rs/cors/cors.go
+++ b/vendor/github.com/rs/cors/cors.go
@@ -26,6 +26,9 @@ import (
"os"
"strconv"
"strings"
+
+ "github.com/rs/xhandler"
+ "golang.org/x/net/context"
)
// Options is a configuration container to setup the CORS middleware.
@@ -68,7 +71,7 @@ type Options struct {
// Cors http handler
type Cors struct {
// Debug logger
- log *log.Logger
+ Log *log.Logger
// Set to true when allowed origins contains a "*"
allowedOriginsAll bool
// Normalized list of plain allowed origins
@@ -100,7 +103,7 @@ func New(options Options) *Cors {
optionPassthrough: options.OptionsPassthrough,
}
if options.Debug {
- c.log = log.New(os.Stdout, "[cors] ", log.LstdFlags)
+ c.Log = log.New(os.Stdout, "[cors] ", log.LstdFlags)
}
// Normalize options
@@ -178,6 +181,8 @@ func (c *Cors) Handler(h http.Handler) http.Handler {
// headers (see #1)
if c.optionPassthrough {
h.ServeHTTP(w, r)
+ } else {
+ w.WriteHeader(http.StatusOK)
}
} else {
c.logf("Handler: Actual request")
@@ -187,6 +192,29 @@ func (c *Cors) Handler(h http.Handler) http.Handler {
})
}
+// HandlerC is net/context aware handler
+func (c *Cors) HandlerC(h xhandler.HandlerC) xhandler.HandlerC {
+ return xhandler.HandlerFuncC(func(ctx context.Context, w http.ResponseWriter, r *http.Request) {
+ if r.Method == "OPTIONS" {
+ c.logf("Handler: Preflight request")
+ c.handlePreflight(w, r)
+ // Preflight requests are standalone and should stop the chain as some other
+ // middleware may not handle OPTIONS requests correctly. One typical example
+ // is authentication middleware ; OPTIONS requests won't carry authentication
+ // headers (see #1)
+ if c.optionPassthrough {
+ h.ServeHTTPC(ctx, w, r)
+ } else {
+ w.WriteHeader(http.StatusOK)
+ }
+ } else {
+ c.logf("Handler: Actual request")
+ c.handleActualRequest(w, r)
+ h.ServeHTTPC(ctx, w, r)
+ }
+ })
+}
+
// HandlerFunc provides Martini compatible handler
func (c *Cors) HandlerFunc(w http.ResponseWriter, r *http.Request) {
if r.Method == "OPTIONS" {
@@ -209,6 +237,8 @@ func (c *Cors) ServeHTTP(w http.ResponseWriter, r *http.Request, next http.Handl
// headers (see #1)
if c.optionPassthrough {
next(w, r)
+ } else {
+ w.WriteHeader(http.StatusOK)
}
} else {
c.logf("ServeHTTP: Actual request")
@@ -296,10 +326,7 @@ func (c *Cors) handleActualRequest(w http.ResponseWriter, r *http.Request) {
// spec doesn't instruct to check the allowed methods for simple cross-origin requests.
// We think it's a nice feature to be able to have control on those methods though.
if !c.isMethodAllowed(r.Method) {
- if c.log != nil {
- c.logf(" Actual request no headers added: method '%s' not allowed",
- r.Method)
- }
+ c.logf(" Actual request no headers added: method '%s' not allowed", r.Method)
return
}
@@ -315,8 +342,8 @@ func (c *Cors) handleActualRequest(w http.ResponseWriter, r *http.Request) {
// convenience method. checks if debugging is turned on before printing
func (c *Cors) logf(format string, a ...interface{}) {
- if c.log != nil {
- c.log.Printf(format, a...)
+ if c.Log != nil {
+ c.Log.Printf(format, a...)
}
}
diff --git a/vendor/github.com/rs/cors/utils.go b/vendor/github.com/rs/cors/utils.go
index cd24831fc..c7a0aa060 100644
--- a/vendor/github.com/rs/cors/utils.go
+++ b/vendor/github.com/rs/cors/utils.go
@@ -51,7 +51,7 @@ func parseHeaderList(headerList string) []string {
} else {
h = append(h, b)
}
- } else if b == '-' || (b >= '0' && b <= '9') {
+ } else if b == '-' || b == '_' || (b >= '0' && b <= '9') {
h = append(h, b)
}
@@ -63,7 +63,7 @@ func parseHeaderList(headerList string) []string {
upper = true
}
} else {
- upper = b == '-'
+ upper = b == '-' || b == '_'
}
}
return headers
diff --git a/vendor/github.com/rs/xhandler/LICENSE b/vendor/github.com/rs/xhandler/LICENSE
new file mode 100644
index 000000000..47c5e9d2d
--- /dev/null
+++ b/vendor/github.com/rs/xhandler/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2015 Olivier Poitrey
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/vendor/github.com/rs/xhandler/README.md b/vendor/github.com/rs/xhandler/README.md
new file mode 100644
index 000000000..91c594bd2
--- /dev/null
+++ b/vendor/github.com/rs/xhandler/README.md
@@ -0,0 +1,134 @@
+# XHandler
+
+[![godoc](http://img.shields.io/badge/godoc-reference-blue.svg?style=flat)](https://godoc.org/github.com/rs/xhandler) [![license](http://img.shields.io/badge/license-MIT-red.svg?style=flat)](https://raw.githubusercontent.com/rs/xhandler/master/LICENSE) [![Build Status](https://travis-ci.org/rs/xhandler.svg?branch=master)](https://travis-ci.org/rs/xhandler) [![Coverage](http://gocover.io/_badge/github.com/rs/xhandler)](http://gocover.io/github.com/rs/xhandler)
+
+XHandler is a bridge between [net/context](https://godoc.org/golang.org/x/net/context) and `http.Handler`.
+
+It lets you enforce `net/context` in your handlers without sacrificing compatibility with existing `http.Handlers` nor imposing a specific router.
+
+Thanks to `net/context` deadline management, `xhandler` is able to enforce a per request deadline and will cancel the context when the client closes the connection unexpectedly.
+
+You may create your own `net/context` aware handler pretty much the same way as you would do with http.Handler.
+
+Read more about xhandler on [Dailymotion engineering blog](http://engineering.dailymotion.com/our-way-to-go/).
+
+## Installing
+
+ go get -u github.com/rs/xhandler
+
+## Usage
+
+```go
+package main
+
+import (
+ "log"
+ "net/http"
+ "time"
+
+ "github.com/rs/cors"
+ "github.com/rs/xhandler"
+ "golang.org/x/net/context"
+)
+
+type myMiddleware struct {
+ next xhandler.HandlerC
+}
+
+func (h myMiddleware) ServeHTTPC(ctx context.Context, w http.ResponseWriter, r *http.Request) {
+ ctx = context.WithValue(ctx, "test", "World")
+ h.next.ServeHTTPC(ctx, w, r)
+}
+
+func main() {
+ c := xhandler.Chain{}
+
+ // Add close notifier handler so context is cancelled when the client closes
+ // the connection
+ c.UseC(xhandler.CloseHandler)
+
+ // Add timeout handler
+ c.UseC(xhandler.TimeoutHandler(2 * time.Second))
+
+ // Middleware putting something in the context
+ c.UseC(func(next xhandler.HandlerC) xhandler.HandlerC {
+ return myMiddleware{next: next}
+ })
+
+ // Mix it with a non-context-aware middleware handler
+ c.Use(cors.Default().Handler)
+
+ // Final handler (using handlerFuncC), reading from the context
+ xh := xhandler.HandlerFuncC(func(ctx context.Context, w http.ResponseWriter, r *http.Request) {
+ value := ctx.Value("test").(string)
+ w.Write([]byte("Hello " + value))
+ })
+
+ // Bridge context aware handlers with http.Handler using xhandler.Handle()
+ http.Handle("/test", c.Handler(xh))
+
+ if err := http.ListenAndServe(":8080", nil); err != nil {
+ log.Fatal(err)
+ }
+}
+```
+
+### Using xmux
+
+Xhandler comes with an optional context aware [muxer](https://github.com/rs/xmux) forked from [httprouter](https://github.com/julienschmidt/httprouter):
+
+```go
+package main
+
+import (
+ "fmt"
+ "log"
+ "net/http"
+ "time"
+
+ "github.com/rs/xhandler"
+ "github.com/rs/xmux"
+ "golang.org/x/net/context"
+)
+
+func main() {
+ c := xhandler.Chain{}
+
+ // Append a context-aware middleware handler
+ c.UseC(xhandler.CloseHandler)
+
+ // Another context-aware middleware handler
+ c.UseC(xhandler.TimeoutHandler(2 * time.Second))
+
+ mux := xmux.New()
+
+ // Use c.Handler to terminate the chain with your final handler
+ mux.GET("/welcome/:name", xhandler.HandlerFuncC(func(ctx context.Context, w http.ResponseWriter, req *http.Request) {
+ fmt.Fprintf(w, "Welcome %s!", xmux.Params(ctx).Get("name"))
+ }))
+
+ if err := http.ListenAndServe(":8080", c.Handler(mux)); err != nil {
+ log.Fatal(err)
+ }
+}
+```
+
+See [xmux](https://github.com/rs/xmux) for more examples.
+
+## Context Aware Middleware
+
+Here is a list of `net/context` aware middleware handlers implementing `xhandler.HandlerC` interface.
+
+Feel free to put up a PR linking your middleware if you have built one:
+
+| Middleware | Author | Description |
+| ---------- | ------ | ----------- |
+| [xmux](https://github.com/rs/xmux) | [Olivier Poitrey](https://github.com/rs) | HTTP request muxer |
+| [xlog](https://github.com/rs/xlog) | [Olivier Poitrey](https://github.com/rs) | HTTP handler logger |
+| [xstats](https://github.com/rs/xstats) | [Olivier Poitrey](https://github.com/rs) | A generic client for service instrumentation |
+| [xaccess](https://github.com/rs/xaccess) | [Olivier Poitrey](https://github.com/rs) | HTTP handler access logger with [xlog](https://github.com/rs/xlog) and [xstats](https://github.com/rs/xstats) |
+| [cors](https://github.com/rs/cors) | [Olivier Poitrey](https://github.com/rs) | [Cross Origin Resource Sharing](http://www.w3.org/TR/cors/) (CORS) support |
+
+## Licenses
+
+All source code is licensed under the [MIT License](https://raw.github.com/rs/xhandler/master/LICENSE).
diff --git a/vendor/github.com/rs/xhandler/chain.go b/vendor/github.com/rs/xhandler/chain.go
new file mode 100644
index 000000000..3e4bd359c
--- /dev/null
+++ b/vendor/github.com/rs/xhandler/chain.go
@@ -0,0 +1,121 @@
+package xhandler
+
+import (
+ "net/http"
+
+ "golang.org/x/net/context"
+)
+
+// Chain is a helper for chaining middleware handlers together for easier
+// management.
+type Chain []func(next HandlerC) HandlerC
+
+// Add appends a variable number of additional middleware handlers
+// to the middleware chain. Middleware handlers can either be
+// context-aware or non-context aware handlers with the appropriate
+// function signatures.
+func (c *Chain) Add(f ...interface{}) {
+ for _, h := range f {
+ switch v := h.(type) {
+ case func(http.Handler) http.Handler:
+ c.Use(v)
+ case func(HandlerC) HandlerC:
+ c.UseC(v)
+ default:
+ panic("Adding invalid handler to the middleware chain")
+ }
+ }
+}
+
+// With creates a new middleware chain from an existing chain,
+// extending it with additional middleware. Middleware handlers
+// can either be context-aware or non-context aware handlers
+// with the appropriate function signatures.
+func (c *Chain) With(f ...interface{}) *Chain {
+ n := make(Chain, len(*c))
+ copy(n, *c)
+ n.Add(f...)
+ return &n
+}
+
+// UseC appends a context-aware handler to the middleware chain.
+func (c *Chain) UseC(f func(next HandlerC) HandlerC) {
+ *c = append(*c, f)
+}
+
+// Use appends a standard http.Handler to the middleware chain without
+// losing track of the context when inserted between two context aware handlers.
+//
+// Caveat: the f function will be called on each request so you are better off putting
+// any initialization sequence outside of this function.
+func (c *Chain) Use(f func(next http.Handler) http.Handler) {
+ xf := func(next HandlerC) HandlerC {
+ return HandlerFuncC(func(ctx context.Context, w http.ResponseWriter, r *http.Request) {
+ n := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ next.ServeHTTPC(ctx, w, r)
+ })
+ f(n).ServeHTTP(w, r)
+ })
+ }
+ *c = append(*c, xf)
+}
+
+// Handler wraps the provided final handler with all the middleware appended to
+// the chain and returns a new standard http.Handler instance.
+// The context.Background() context is injected automatically.
+func (c Chain) Handler(xh HandlerC) http.Handler {
+ ctx := context.Background()
+ return c.HandlerCtx(ctx, xh)
+}
+
+// HandlerFC is a helper to provide a function (HandlerFuncC) to Handler().
+//
+// HandlerFC is equivalent to:
+// c.Handler(xhandler.HandlerFuncC(xhc))
+func (c Chain) HandlerFC(xhf HandlerFuncC) http.Handler {
+ ctx := context.Background()
+ return c.HandlerCtx(ctx, HandlerFuncC(xhf))
+}
+
+// HandlerH is a helper to provide a standard http handler (http.HandlerFunc)
+// to Handler(). Your final handler won't have access to the context though.
+func (c Chain) HandlerH(h http.Handler) http.Handler {
+ ctx := context.Background()
+ return c.HandlerCtx(ctx, HandlerFuncC(func(ctx context.Context, w http.ResponseWriter, r *http.Request) {
+ h.ServeHTTP(w, r)
+ }))
+}
+
+// HandlerF is a helper to provide a standard http handler function
+// (http.HandlerFunc) to Handler(). Your final handler won't have access
+// to the context though.
+func (c Chain) HandlerF(hf http.HandlerFunc) http.Handler {
+ ctx := context.Background()
+ return c.HandlerCtx(ctx, HandlerFuncC(func(ctx context.Context, w http.ResponseWriter, r *http.Request) {
+ hf(w, r)
+ }))
+}
+
+// HandlerCtx wraps the provided final handler with all the middleware appended to
+// the chain and returns a new standard http.Handler instance.
+func (c Chain) HandlerCtx(ctx context.Context, xh HandlerC) http.Handler {
+ return New(ctx, c.HandlerC(xh))
+}
+
+// HandlerC wraps the provided final handler with all the middleware appended to
+// the chain and returns a HandlerC instance.
+func (c Chain) HandlerC(xh HandlerC) HandlerC {
+ for i := len(c) - 1; i >= 0; i-- {
+ xh = c[i](xh)
+ }
+ return xh
+}
+
+// HandlerCF wraps the provided final handler func with all the middleware appended to
+// the chain and returns a HandlerC instance.
+//
+// HandlerCF is equivalent to:
+// c.HandlerC(xhandler.HandlerFuncC(xhc))
+func (c Chain) HandlerCF(xhc HandlerFuncC) HandlerC {
+ return c.HandlerC(HandlerFuncC(xhc))
+}
diff --git a/vendor/github.com/rs/xhandler/middleware.go b/vendor/github.com/rs/xhandler/middleware.go
new file mode 100644
index 000000000..7ad8fba62
--- /dev/null
+++ b/vendor/github.com/rs/xhandler/middleware.go
@@ -0,0 +1,59 @@
+package xhandler
+
+import (
+ "net/http"
+ "time"
+
+ "golang.org/x/net/context"
+)
+
+// CloseHandler returns a Handler, cancelling the context when the client
+// connection closes unexpectedly.
+func CloseHandler(next HandlerC) HandlerC {
+ return HandlerFuncC(func(ctx context.Context, w http.ResponseWriter, r *http.Request) {
+ // Cancel the context if the client closes the connection
+ if wcn, ok := w.(http.CloseNotifier); ok {
+ var cancel context.CancelFunc
+ ctx, cancel = context.WithCancel(ctx)
+ defer cancel()
+
+ notify := wcn.CloseNotify()
+ go func() {
+ select {
+ case <-notify:
+ cancel()
+ case <-ctx.Done():
+ }
+ }()
+ }
+
+ next.ServeHTTPC(ctx, w, r)
+ })
+}
+
+// TimeoutHandler returns a Handler which adds a timeout to the context.
+//
+// Child handlers have the responsability of obeying the context deadline and to return
+// an appropriate error (or not) response in case of timeout.
+func TimeoutHandler(timeout time.Duration) func(next HandlerC) HandlerC {
+ return func(next HandlerC) HandlerC {
+ return HandlerFuncC(func(ctx context.Context, w http.ResponseWriter, r *http.Request) {
+ ctx, _ = context.WithTimeout(ctx, timeout)
+ next.ServeHTTPC(ctx, w, r)
+ })
+ }
+}
+
+// If is a special handler that will skip insert the condNext handler only if a condition
+// applies at runtime.
+func If(cond func(ctx context.Context, w http.ResponseWriter, r *http.Request) bool, condNext func(next HandlerC) HandlerC) func(next HandlerC) HandlerC {
+ return func(next HandlerC) HandlerC {
+ return HandlerFuncC(func(ctx context.Context, w http.ResponseWriter, r *http.Request) {
+ if cond(ctx, w, r) {
+ condNext(next).ServeHTTPC(ctx, w, r)
+ } else {
+ next.ServeHTTPC(ctx, w, r)
+ }
+ })
+ }
+}
diff --git a/vendor/github.com/rs/xhandler/xhandler.go b/vendor/github.com/rs/xhandler/xhandler.go
new file mode 100644
index 000000000..bc832cb1f
--- /dev/null
+++ b/vendor/github.com/rs/xhandler/xhandler.go
@@ -0,0 +1,42 @@
+// Package xhandler provides a bridge between http.Handler and net/context.
+//
+// xhandler enforces net/context in your handlers without sacrificing
+// compatibility with existing http.Handlers nor imposing a specific router.
+//
+// Thanks to net/context deadline management, xhandler is able to enforce
+// a per request deadline and will cancel the context in when the client close
+// the connection unexpectedly.
+//
+// You may create net/context aware middlewares pretty much the same way as
+// you would with http.Handler.
+package xhandler // import "github.com/rs/xhandler"
+
+import (
+ "net/http"
+
+ "golang.org/x/net/context"
+)
+
+// HandlerC is a net/context aware http.Handler
+type HandlerC interface {
+ ServeHTTPC(context.Context, http.ResponseWriter, *http.Request)
+}
+
+// HandlerFuncC type is an adapter to allow the use of ordinary functions
+// as an xhandler.Handler. If f is a function with the appropriate signature,
+// xhandler.HandlerFuncC(f) is a xhandler.Handler object that calls f.
+type HandlerFuncC func(context.Context, http.ResponseWriter, *http.Request)
+
+// ServeHTTPC calls f(ctx, w, r).
+func (f HandlerFuncC) ServeHTTPC(ctx context.Context, w http.ResponseWriter, r *http.Request) {
+ f(ctx, w, r)
+}
+
+// New creates a conventional http.Handler injecting the provided root
+// context to sub handlers. This handler is used as a bridge between conventional
+// http.Handler and context aware handlers.
+func New(ctx context.Context, h HandlerC) http.Handler {
+ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ h.ServeHTTPC(ctx, w, r)
+ })
+}
diff --git a/vendor/golang.org/x/net/LICENSE b/vendor/golang.org/x/net/LICENSE
new file mode 100644
index 000000000..6a66aea5e
--- /dev/null
+++ b/vendor/golang.org/x/net/LICENSE
@@ -0,0 +1,27 @@
+Copyright (c) 2009 The Go 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.
+ * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+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
+OWNER 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/golang.org/x/net/PATENTS b/vendor/golang.org/x/net/PATENTS
new file mode 100644
index 000000000..733099041
--- /dev/null
+++ b/vendor/golang.org/x/net/PATENTS
@@ -0,0 +1,22 @@
+Additional IP Rights Grant (Patents)
+
+"This implementation" means the copyrightable works distributed by
+Google as part of the Go project.
+
+Google hereby grants to You a perpetual, worldwide, non-exclusive,
+no-charge, royalty-free, irrevocable (except as stated in this section)
+patent license to make, have made, use, offer to sell, sell, import,
+transfer and otherwise run, modify and propagate the contents of this
+implementation of Go, where such license applies only to those patent
+claims, both currently owned or controlled by Google and acquired in
+the future, licensable by Google that are necessarily infringed by this
+implementation of Go. This grant does not include claims that would be
+infringed only as a consequence of further modification of this
+implementation. If you or your agent or exclusive licensee institute or
+order or agree to the institution of patent litigation against any
+entity (including a cross-claim or counterclaim in a lawsuit) alleging
+that this implementation of Go or any code incorporated within this
+implementation of Go constitutes direct or contributory patent
+infringement, or inducement of patent infringement, then any patent
+rights granted to you under this License for this implementation of Go
+shall terminate as of the date such litigation is filed.
diff --git a/vendor/golang.org/x/net/context/context.go b/vendor/golang.org/x/net/context/context.go
new file mode 100644
index 000000000..134654cf7
--- /dev/null
+++ b/vendor/golang.org/x/net/context/context.go
@@ -0,0 +1,156 @@
+// 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.
+//
+// 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"
+
+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{}
+}
+
+// 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
+}
+
+// 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/context/go17.go b/vendor/golang.org/x/net/context/go17.go
new file mode 100644
index 000000000..f8cda19ad
--- /dev/null
+++ b/vendor/golang.org/x/net/context/go17.go
@@ -0,0 +1,72 @@
+// 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/pre_go17.go b/vendor/golang.org/x/net/context/pre_go17.go
new file mode 100644
index 000000000..5a30acabd
--- /dev/null
+++ b/vendor/golang.org/x/net/context/pre_go17.go
@@ -0,0 +1,300 @@
+// 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/vendor.json b/vendor/vendor.json
index 641c65a33..308a3ad72 100644
--- a/vendor/vendor.json
+++ b/vendor/vendor.json
@@ -4,23 +4,28 @@
"package": [
{
"path": "github.com/Sirupsen/logrus",
- "revision": "418b41d23a1bf978c06faea5313ba194650ac088",
- "revisionTime": "2015-09-08T20:46:18Z"
+ "revision": "32055c351ea8b00b96d70f28db48d9840feaf0ec",
+ "revisionTime": "2016-07-12T20:17:32-04:00"
},
{
"path": "github.com/cheggaaa/pb",
- "revision": "c1f48d5ce4f292dfb775ef52aaedd15be323510d",
- "revisionTime": "2016-05-20T13:10:51+03:00"
+ "revision": "73ae1d68fe0bd482ab11913a9828634f795b987f",
+ "revisionTime": "2016-07-13T13:44:25+03:00"
},
{
"path": "github.com/dgrijalva/jwt-go",
- "revision": "afef698c326bfd906b11659432544e5aae441d44",
- "revisionTime": "2015-12-30T10:00:00-08:00"
+ "revision": "01aeca54ebda6e0fbfafd0a524d234159c05ec20",
+ "revisionTime": "2016-07-05T13:30:06-07:00"
+ },
+ {
+ "path": "github.com/dgrijalva/jwt-go/request",
+ "revision": "01aeca54ebda6e0fbfafd0a524d234159c05ec20",
+ "revisionTime": "2016-07-05T13:30:06-07:00"
},
{
"path": "github.com/dustin/go-humanize",
- "revision": "c20a8bde38c8f5ba06f6600edf473705c96829d1",
- "revisionTime": "2015-08-24T01:38:10-07:00"
+ "revision": "fef948f2d241bd1fd0631108ecc2c9553bae60bf",
+ "revisionTime": "2016-06-23T09:40:21+08:00"
},
{
"path": "github.com/elazarl/go-bindata-assetfs",
@@ -29,33 +34,33 @@
},
{
"path": "github.com/fatih/color",
- "revision": "7a5857db0b2752a436d8461d88c42dea0ee191c0",
- "revisionTime": "2016-02-12T11:24:09+02:00"
+ "revision": "87d4004f2ab62d0d255e0a38f1680aa534549fe3",
+ "revisionTime": "2016-06-10T14:06:02+03:00"
},
{
"path": "github.com/gorilla/context",
- "revision": "1c83b3eabd45b6d76072b66b746c20815fb2872d",
- "revisionTime": "2015-08-19T22:12:45-07:00"
+ "revision": "aed02d124ae4a0e94fea4541c8effd05bf0c8296",
+ "revisionTime": "2016-05-25T13:33:19-07:00"
},
{
"path": "github.com/gorilla/handlers",
- "revision": "ee54c7b44cab12289237fb8631314790076e728b",
- "revisionTime": "2016-02-28T09:16:04-08:00"
+ "revision": "66e6c6f01d8da976ee113437745ca029c2b585a6",
+ "revisionTime": "2016-04-10T11:53:17-07:00"
},
{
"path": "github.com/gorilla/mux",
- "revision": "ee1815431e497d3850809578c93ab6705f1a19f7",
- "revisionTime": "2015-08-19T22:15:06-07:00"
+ "revision": "9fa818a44c2bf1396a17f9d5a3c0f6dd39d2ff8e",
+ "revisionTime": "2016-06-05T16:35:21-07:00"
},
{
"path": "github.com/gorilla/rpc/v2",
- "revision": "64e20900b8aa38bb0771dec71ba3bcc2b07fc8ec",
- "revisionTime": "2015-11-05T07:45:51+08:00"
+ "revision": "bd3317b8f6704b1b40e4e705ec9e987a535cd5d3",
+ "revisionTime": "2016-05-16T23:23:31-07:00"
},
{
"path": "github.com/gorilla/rpc/v2/json2",
- "revision": "64e20900b8aa38bb0771dec71ba3bcc2b07fc8ec",
- "revisionTime": "2015-11-05T07:45:51+08:00"
+ "revision": "bd3317b8f6704b1b40e4e705ec9e987a535cd5d3",
+ "revisionTime": "2016-05-16T23:23:31-07:00"
},
{
"path": "github.com/hashicorp/go-version",
@@ -69,18 +74,18 @@
},
{
"path": "github.com/klauspost/reedsolomon",
- "revision": "2fde63d2889a399426862a16611c489b1fed87bc",
- "revisionTime": "2016-06-04T08:05:20+02:00"
+ "revision": "467733eb9c209042fb37d2074a5b6be33a529be0",
+ "revisionTime": "2016-07-06T21:06:00+02:00"
},
{
"path": "github.com/mattn/go-colorable",
- "revision": "9cbef7c35391cca05f15f8181dc0b18bc9736dbb",
- "revisionTime": "2016-02-20T16:59:35+09:00"
+ "revision": "9056b7a9f2d1f2d96498d6d146acd1f9d5ed3d59",
+ "revisionTime": "2016-06-03T00:08:27+09:00"
},
{
"path": "github.com/mattn/go-isatty",
- "revision": "7fcbc72f853b92b5720db4a6b8482be612daef24",
- "revisionTime": "2015-08-14T09:26:29+09:00"
+ "revision": "56b76bdf51f7708750eac80fa38b952bb9f32639",
+ "revisionTime": "2015-12-11T09:06:21+09:00"
},
{
"path": "github.com/minio/blake2b-simd",
@@ -119,8 +124,13 @@
},
{
"path": "github.com/rs/cors",
- "revision": "eb527c8097e0f19a3ff7b253a3fe70545070f420",
- "revisionTime": "2015-08-29T22:34:20-07:00"
+ "revision": "a62a804a8a009876ca59105f7899938a1349f4b3",
+ "revisionTime": "2016-06-18T04:49:35+05:30"
+ },
+ {
+ "path": "github.com/rs/xhandler",
+ "revision": "ed27b6fd65218132ee50cd95f38474a3d8a2cd12",
+ "revisionTime": "2016-06-18T12:32:21-07:00"
},
{
"checksumSHA1": "u0hXGADM3JDza8YjgiyNJpAJk8g=",
@@ -138,6 +148,11 @@
"revision": "7b85b097bf7527677d54d3220065e966a0e3b613",
"revisionTime": "2015-11-30T17:07:01-05:00"
},
+ {
+ "path": "golang.org/x/net/context",
+ "revision": "a728288923b47049b2ce791836767ffbe964a5bd",
+ "revisionTime": "2016-07-07T15:24:52-07:00"
+ },
{
"path": "gopkg.in/check.v1",
"revision": "11d3bc7aa68e238947792f30573146a3231fc0f1",
diff --git a/web-handlers.go b/web-handlers.go
index d5e6ad893..4b1c85ba0 100644
--- a/web-handlers.go
+++ b/web-handlers.go
@@ -27,6 +27,7 @@ import (
"time"
jwtgo "github.com/dgrijalva/jwt-go"
+ jwtreq "github.com/dgrijalva/jwt-go/request"
"github.com/dustin/go-humanize"
"github.com/gorilla/mux"
"github.com/gorilla/rpc/v2/json2"
@@ -42,14 +43,16 @@ func isJWTReqAuthenticated(req *http.Request) bool {
return false
}
- token, e := jwtgo.ParseFromRequest(req, func(token *jwtgo.Token) (interface{}, error) {
+ var reqCallback jwtgo.Keyfunc
+ reqCallback = func(token *jwtgo.Token) (interface{}, error) {
if _, ok := token.Method.(*jwtgo.SigningMethodHMAC); !ok {
return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"])
}
return []byte(jwt.SecretAccessKey), nil
- })
- if e != nil {
- errorIf(e, "token parsing failed")
+ }
+ token, err := jwtreq.ParseFromRequest(req, jwtreq.AuthorizationHeaderExtractor, reqCallback)
+ if err != nil {
+ errorIf(err, "token parsing failed")
return false
}
return token.Valid
@@ -382,7 +385,7 @@ func (web *webAPIHandlers) Download(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
bucket := vars["bucket"]
object := vars["object"]
- token := r.URL.Query().Get("token")
+ tokenStr := r.URL.Query().Get("token")
jwt, err := newJWT()
if err != nil {
@@ -390,13 +393,13 @@ func (web *webAPIHandlers) Download(w http.ResponseWriter, r *http.Request) {
return
}
- jwttoken, e := jwtgo.Parse(token, func(token *jwtgo.Token) (interface{}, error) {
+ token, e := jwtgo.Parse(tokenStr, func(token *jwtgo.Token) (interface{}, error) {
if _, ok := token.Method.(*jwtgo.SigningMethodHMAC); !ok {
return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"])
}
return []byte(jwt.SecretAccessKey), nil
})
- if e != nil || !jwttoken.Valid {
+ if e != nil || !token.Valid {
writeWebErrorResponse(w, errInvalidToken)
return
}