diff --git a/.golangci.yml b/.golangci.yml
index 19e95c8f212..f064425fb39 100644
--- a/.golangci.yml
+++ b/.golangci.yml
@@ -121,10 +121,10 @@ linters-settings:
list-type: blacklist
include-go-root: false
packages:
- - github.com/sirupsen/logrus
+ - github.com/Sirupsen/logrus
packages-with-error-messages:
# specify an error message to output when a blacklisted package is used
- github.com/sirupsen/logrus: "logging is allowed only by logutils.Log"
+ github.com/Sirupsen/logrus: "must use github.com/sirupsen/logrus"
misspell:
# Correct spellings using locale preferences for US or UK.
# Default is to use a neutral variety of English.
diff --git a/cmd/daprd/main.go b/cmd/daprd/main.go
index af4f4945829..bcceab04a53 100644
--- a/cmd/daprd/main.go
+++ b/cmd/daprd/main.go
@@ -14,7 +14,7 @@ import (
"syscall"
"time"
- log "github.com/Sirupsen/logrus"
+ log "github.com/sirupsen/logrus"
global_config "github.com/dapr/dapr/pkg/config"
"github.com/dapr/dapr/pkg/modes"
daprd "github.com/dapr/dapr/pkg/runtime"
diff --git a/cmd/injector/main.go b/cmd/injector/main.go
index b1a1dee11eb..3feafb1d7dc 100644
--- a/cmd/injector/main.go
+++ b/cmd/injector/main.go
@@ -9,7 +9,7 @@ import (
"flag"
"time"
- log "github.com/Sirupsen/logrus"
+ log "github.com/sirupsen/logrus"
"github.com/dapr/dapr/pkg/injector"
"github.com/dapr/dapr/pkg/signals"
"github.com/dapr/dapr/pkg/version"
diff --git a/cmd/operator/main.go b/cmd/operator/main.go
index ec07aa4328a..09ec0f7d247 100644
--- a/cmd/operator/main.go
+++ b/cmd/operator/main.go
@@ -9,7 +9,7 @@ import (
"flag"
"time"
- log "github.com/Sirupsen/logrus"
+ log "github.com/sirupsen/logrus"
scheme "github.com/dapr/dapr/pkg/client/clientset/versioned"
k8s "github.com/dapr/dapr/pkg/kubernetes"
"github.com/dapr/dapr/pkg/operator"
diff --git a/cmd/placement/main.go b/cmd/placement/main.go
index b1d37524a8c..5da0dcc4fdd 100644
--- a/cmd/placement/main.go
+++ b/cmd/placement/main.go
@@ -10,7 +10,7 @@ import (
"os"
"os/signal"
- log "github.com/Sirupsen/logrus"
+ log "github.com/sirupsen/logrus"
"github.com/dapr/dapr/pkg/placement"
"github.com/dapr/dapr/pkg/version"
)
diff --git a/go.mod b/go.mod
index acb845f63b3..73017d44b41 100644
--- a/go.mod
+++ b/go.mod
@@ -5,9 +5,8 @@ go 1.13
require (
github.com/AdhityaRamadhanus/fasthttpcors v0.0.0-20170121111917-d4c07198763a
github.com/DataDog/zstd v1.4.1 // indirect
- github.com/Sirupsen/logrus v1.0.6
github.com/cenkalti/backoff v2.2.1+incompatible
- github.com/dapr/components-contrib v0.0.0-20191128051247-c4bd2a47eae0
+ github.com/dapr/components-contrib v0.0.0-20191217174314-701f12e52994
github.com/eapache/go-resiliency v1.2.0 // indirect
github.com/emicklei/go-restful v2.10.0+incompatible // indirect
github.com/evanphx/json-patch v4.2.0+incompatible // indirect
@@ -30,20 +29,17 @@ require (
github.com/jcmturner/gofork v1.0.0 // indirect
github.com/json-iterator/go v1.1.7
github.com/kelseyhightower/envconfig v1.4.0
- github.com/klauspost/compress v1.5.0 // indirect
- github.com/klauspost/cpuid v1.2.1 // indirect
github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect
github.com/mailru/easyjson v0.7.0 // indirect
github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1
github.com/mitchellh/mapstructure v1.1.2
- github.com/onsi/ginkgo v1.10.1 // indirect
- github.com/onsi/gomega v1.7.0 // indirect
github.com/phayes/freeport v0.0.0-20171002181615-b8543db493a5
github.com/pierrec/lz4 v2.3.0+incompatible // indirect
github.com/qiangxue/fasthttp-routing v0.0.0-20160225050629-6ccdc2a18d87
github.com/rcrowley/go-metrics v0.0.0-20190826022208-cac0b30c2563 // indirect
+ github.com/sirupsen/logrus v1.4.2
github.com/stretchr/testify v1.4.0
- github.com/valyala/fasthttp v1.4.0
+ github.com/valyala/fasthttp v1.6.0
go.opencensus.io v0.22.1
golang.org/x/exp v0.0.0-20190927203820-447a159532ef // indirect
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e // indirect
diff --git a/go.sum b/go.sum
index 1bd0e424cbe..c5374d93850 100644
--- a/go.sum
+++ b/go.sum
@@ -1,7 +1,6 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
-cloud.google.com/go v0.40.0/go.mod h1:Tk58MuI9rbLMKlAjeO/bDnteAx7tX2gJIXw4T5Jwlro=
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
@@ -15,11 +14,9 @@ cloud.google.com/go/pubsub v1.0.1 h1:W9tAK3E57P75u0XLLR82LZyw8VpAnhmyTOxW9qzmyj8
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
cloud.google.com/go/storage v1.0.0 h1:VV2nUM3wwLLGh9lSABFgZMjInyUbJeaRSE64WuAIQ+4=
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
-contrib.go.opencensus.io/exporter/ocagent v0.4.12/go.mod h1:450APlNTSR6FrvC3CTRqYosuDstRB9un7SOx2k/9ckA=
contrib.go.opencensus.io/exporter/ocagent v0.5.0/go.mod h1:ImxhfLRpxoYiSq891pBrLVhN+qmP8BTVvdH2YLs7Gl0=
contrib.go.opencensus.io/exporter/ocagent v0.6.0 h1:Z1n6UAyr0QwM284yUuh5Zd8JlvxUGAhFZcgMJkMPrGM=
contrib.go.opencensus.io/exporter/ocagent v0.6.0/go.mod h1:zmKjrJcdo0aYcVS7bmEeSEBLPA9YJp5bjrofdU3pIXs=
-contrib.go.opencensus.io/exporter/prometheus v0.1.0/go.mod h1:cGFniUXGZlKRjzOyuZJ6mgB+PgBcCIa79kEKR8YCW+A=
contrib.go.opencensus.io/exporter/zipkin v0.1.1 h1:PR+1zWqY8ceXs1qDQQIlgXe+sdiwCf0n32bH4+Epk8g=
contrib.go.opencensus.io/exporter/zipkin v0.1.1/go.mod h1:GMvdSl3eJ2gapOaLKzTKE3qDgUkJ86k9k3yY2eqwkzc=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
@@ -46,12 +43,12 @@ github.com/Azure/azure-service-bus-go v0.9.1/go.mod h1:yzBx6/BUGfjfeqbRZny9AQIbI
github.com/Azure/azure-storage-blob-go v0.0.0-20181023070848-cf01652132cc/go.mod h1:oGfmITT1V6x//CswqY2gtAHND+xIP64/qL7a5QJix0Y=
github.com/Azure/azure-storage-blob-go v0.8.0 h1:53qhf0Oxa0nOjgbDeeYPUeyiNmafAFEY95rZLK0Tj6o=
github.com/Azure/azure-storage-blob-go v0.8.0/go.mod h1:lPI3aLPpuLTeUwh1sViKXFxwl2B6teiRqI0deQUvsw0=
+github.com/Azure/azure-storage-queue-go v0.0.0-20191125232315-636801874cdd/go.mod h1:K6am8mT+5iFXgingS9LUc7TmbsW6XBw3nxaRyaMyWc8=
github.com/Azure/go-autorest v13.3.0+incompatible h1:8Ix0VdeOllBx9jEcZ2Wb1uqWUpE1awmJiaHztwaJCPk=
github.com/Azure/go-autorest v13.3.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI=
github.com/Azure/go-autorest/autorest v0.9.2 h1:6AWuh3uWrsZJcNoCHrCF/+g4aKPCU39kaMO6/qrnK/4=
github.com/Azure/go-autorest/autorest v0.9.2/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI=
-github.com/Azure/go-autorest/autorest/adal v0.1.0/go.mod h1:MeS4XhScH55IST095THyTxElntu7WqB7pNbZo8Q5G3E=
github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0=
github.com/Azure/go-autorest/autorest/adal v0.6.0 h1:UCTq22yE3RPgbU/8u4scfnnzuCW6pwQ9n+uBtV78ouo=
github.com/Azure/go-autorest/autorest/adal v0.6.0/go.mod h1:Z6vX6WXXuyieHAXwMj0S6HY6e6wcHn37qQMBQlvY3lc=
@@ -68,15 +65,12 @@ github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxB
github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=
github.com/Azure/go-autorest/autorest/mocks v0.3.0 h1:qJumjCaCudz+OcqE9/XtEPfvtOjOmKaui4EOpFI6zZc=
github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM=
-github.com/Azure/go-autorest/autorest/to v0.2.0/go.mod h1:GunWKJp1AEqgMaGLV+iocmRAJWqST1wQYhyyjXJ3SJc=
github.com/Azure/go-autorest/autorest/to v0.3.0 h1:zebkZaadz7+wIQYgC7GXaz3Wb28yKYfVkkBKwc38VF8=
github.com/Azure/go-autorest/autorest/to v0.3.0/go.mod h1:MgwOyqaIuKdG4TL/2ywSsIWKAfJfgHDo8ObuUk3t5sA=
-github.com/Azure/go-autorest/autorest/validation v0.1.0/go.mod h1:Ha3z/SqBeaalWQvokg3NZAlQTalVMtOIAs1aGK7G6u8=
github.com/Azure/go-autorest/autorest/validation v0.2.0 h1:15vMO4y76dehZSq7pAaOLQxC6dZYsSrj2GQpflyM/L4=
github.com/Azure/go-autorest/autorest/validation v0.2.0/go.mod h1:3EEqHnBxQGHXRYq3HT1WyXAvT7LLY3tl70hw6tQIbjI=
github.com/Azure/go-autorest/logger v0.1.0 h1:ruG4BSDXONFRrZZJ2GUXDiUyVpayPmb1GnWeHDdaNKY=
github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc=
-github.com/Azure/go-autorest/tracing v0.1.0/go.mod h1:ROEEAFwXycQw7Sn3DXNtEedEvdeRAgDr0izn4z5Ij88=
github.com/Azure/go-autorest/tracing v0.5.0 h1:TRn4WjSnkcSy5AEG3pnbtFSwNtwzjr4VYyQflFE619k=
github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk=
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
@@ -97,16 +91,15 @@ github.com/Shopify/sarama v1.23.1 h1:XxJBCZEoWJtoWjf/xRbmGUpAmTZGnuuF0ON0EvxxBrs
github.com/Shopify/sarama v1.23.1/go.mod h1:XLH1GYJnLVE0XCr6KdJGVJRTwY30moWNJ4sERjXX6fs=
github.com/Shopify/toxiproxy v2.1.4+incompatible h1:TKdv8HiTLgE5wdJuEML90aBgNWsokNbMijUGhmcoBJc=
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
-github.com/Sirupsen/logrus v1.0.6 h1:HCAGQRk48dRVPA5Y+Yh0qdCSTzPOyU1tBJ7Q9YzotII=
-github.com/Sirupsen/logrus v1.0.6/go.mod h1:rmk17hk6i8ZSAJkSDa7nOxamrG+SP4P0mm+DAvExv4U=
github.com/a8m/documentdb v1.2.0 h1:3ooHoXI6ww5d5Itr39V+bBmX4xm0nKrv0XMKbXw8vwE=
github.com/a8m/documentdb v1.2.0/go.mod h1:4Z0mpi7fkyqjxUdGiNMO3vagyiUoiwLncaIX6AsW5z0=
+github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU=
+github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY=
github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
-github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da h1:8GUt8eRujhVEGZFFEjBj46YV4rDjvGrNxb0KMWYkL2I=
@@ -144,8 +137,8 @@ github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f h1:JOrtw2xFKzlg+
github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f h1:lBNOc5arjvs8E5mO2tbpBpLoyyu8B6e44T7hJy6potg=
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
-github.com/dapr/components-contrib v0.0.0-20191128051247-c4bd2a47eae0 h1:aK0PVXVrTXIEsAXwlA/SOeyLgBN9zZRLCCCrEXn0+wY=
-github.com/dapr/components-contrib v0.0.0-20191128051247-c4bd2a47eae0/go.mod h1:0Cq4xU8Rocgpk1AkDQcTxhwkGbmkj2nL0RGyhcnVe5M=
+github.com/dapr/components-contrib v0.0.0-20191217174314-701f12e52994 h1:d2fRwR67v8d8/y89d73+GnHS5iicRRro20oJCjvW/Ys=
+github.com/dapr/components-contrib v0.0.0-20191217174314-701f12e52994/go.mod h1:2h+01vONvUWWUKDD7z+Gzu5oBDizoh+Mw+lqo+8otII=
github.com/davecgh/go-spew v0.0.0-20151105211317-5215b55f46b2/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
@@ -179,7 +172,13 @@ github.com/emicklei/go-restful v2.10.0+incompatible/go.mod h1:otzb+WCGbkyDHkqmQm
github.com/evanphx/json-patch v0.0.0-20190203023257-5858425f7550/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/evanphx/json-patch v4.2.0+incompatible h1:fUDGZCv/7iAN7u0puUVhvKCcsR6vRfwrJatElLBEf0I=
github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
+github.com/fasthttp-contrib/sessions v0.0.0-20160905201309-74f6ac73d5d5 h1:M4CVMQ5ueVmGZAtkW2bsO+ftesCYpfxl27JTqtzKBzE=
+github.com/fasthttp-contrib/sessions v0.0.0-20160905201309-74f6ac73d5d5/go.mod h1:MQXNGeXkpojWTxbN7vXoE3f7EmlA11MlJbsrJpVBINA=
+github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072 h1:DddqAaWDpywytcG8w/qoQ5sAN8X12d3Z3koB0C3Rxsc=
+github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
+github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo=
+github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
github.com/fortytw2/leaktest v1.2.0 h1:cj6GCiwJDH7l3tMHLjZDo0QqPtrXJiWSI9JgpeQKw+Q=
github.com/fortytw2/leaktest v1.2.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
@@ -191,6 +190,8 @@ github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/garyburd/redigo v1.6.0 h1:0VruCpn7yAIIu7pWVClQC8wxCJEcG3nyzpMSHKi1PQc=
github.com/garyburd/redigo v1.6.0/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY=
+github.com/gavv/httpexpect v2.0.0+incompatible h1:1X9kcRshkSKEjNJJxX9Y9mQ5BRfbxU5kORdjhlA1yX8=
+github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc=
github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
@@ -265,6 +266,8 @@ github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=
+github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw=
@@ -285,6 +288,8 @@ github.com/googleapis/gnostic v0.3.1 h1:WeAefnSUHlBb0iJKwxFDZdbfGwkd7xRNuV+IpXMJ
github.com/googleapis/gnostic v0.3.1/go.mod h1:on+2t9HRStVgn95RSsFWFz+6Q0Snyqv1awfrALZdbtU=
github.com/gophercloud/gophercloud v0.0.0-20190126172459-c818fa66e4c8 h1:L9JPKrtsHMQ4VCRQfHvbbHBfB2Urn8xf6QZeXZ+OrN4=
github.com/gophercloud/gophercloud v0.0.0-20190126172459-c818fa66e4c8/go.mod h1:3WdhXV3rUYy9p6AUW8d94kr+HS62Y4VL9mBnFxsD8q4=
+github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
+github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/mux v1.7.1 h1:Dw4jY2nghMMRsh1ol8dv1axHkDwMQK2DHerMNJsIpJU=
@@ -348,6 +353,8 @@ github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpO
github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/imdario/mergo v0.3.7 h1:Y+UAYTZ7gDEuOfhxKWy+dvb5dRQ6rJjFSdX2HZY1/gI=
github.com/imdario/mergo v0.3.7/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
+github.com/imkira/go-interpol v1.1.0 h1:KIiKr0VSG2CUW1hl1jpiyuzuJeKUUpC8iM1AIE7N1Vk=
+github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA=
github.com/jcmturner/gofork v0.0.0-20190328161633-dc7c13fece03/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o=
github.com/jcmturner/gofork v1.0.0 h1:J7uCkflzTEhUZ64xqKnkDxq3kzc96ajM1Gli5ktUem8=
github.com/jcmturner/gofork v1.0.0/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o=
@@ -371,17 +378,23 @@ github.com/json-iterator/go v1.1.7 h1:KfgG9LzI+pYjr4xvmz/5H4FXjokeP+rlHLhv3iH62F
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024 h1:rBMNdlhTLzJjJSDIjNEXX1Pz3Hmwmz91v+zycvx9PJc=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
+github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
+github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes=
+github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88 h1:uC1QfSlInpQF+M0ao65imhwqKnz3Q2z/d8PWZRMQvDM=
+github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k=
+github.com/kataras/go-errors v0.0.3 h1:RQSGEb5AHjsGbwhNW8mFC7a9JrgoCLHC8CBQ4keXJYU=
+github.com/kataras/go-errors v0.0.3/go.mod h1:K3ncz8UzwI3bpuksXt5tQLmrRlgxfv+52ARvAu1+I+o=
+github.com/kataras/go-serializer v0.0.4 h1:isugggrY3DSac67duzQ/tn31mGAUtYqNpE2ob6Xt/SY=
+github.com/kataras/go-serializer v0.0.4/go.mod h1:/EyLBhXKQOJ12dZwpUZZje3lGy+3wnvG7QKaVJtm/no=
github.com/kelseyhightower/envconfig v1.4.0 h1:Im6hONhd3pLkfDFsbRgu68RDNkGF1r3dvMUtDTo2cv8=
github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg=
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
-github.com/klauspost/compress v1.4.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
-github.com/klauspost/compress v1.5.0 h1:iDac0ZKbmSA4PRrRuXXjZL8C7UoJan8oBYxXkMzEQrI=
-github.com/klauspost/compress v1.5.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
-github.com/klauspost/cpuid v0.0.0-20180405133222-e7e905edc00e/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
+github.com/klauspost/compress v1.8.2 h1:Bx0qjetmNjdFXASH02NSAREKpiaDwkO1DRZ3dV2KCcs=
+github.com/klauspost/compress v1.8.2/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
github.com/klauspost/cpuid v1.2.1 h1:vJi+O/nMdFt0vqm8NZBI6wzALWdA2X+egi0ogNyrC/w=
github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
github.com/konsorten/go-windows-terminal-sequences v0.0.0-20180402223658-b729f2633dfe/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
@@ -405,14 +418,18 @@ github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.7.0 h1:aizVhC/NAAcKWb+5QsU1iNOZb4Yws5UO2I+aIprQITM=
github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs=
+github.com/mattn/go-colorable v0.0.9 h1:UVL0vNpWh04HeJXV0KLcaT7r06gOH2l4OW6ddYRUIY4=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149 h1:HfxbT6/JcvIljmERptWhwa8XzP7H3T+Z2N26gTsaDaA=
github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc=
+github.com/mattn/go-isatty v0.0.3 h1:ns/ykhmWi7G9O+8a448SecJU3nSMBXJfqQkl0upE1jI=
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/mediocregopher/radix.v2 v0.0.0-20181115013041-b67df6e626f9 h1:ViNuGS149jgnttqhc6XQNPwdupEMBXqCx9wtlW7P3sA=
github.com/mediocregopher/radix.v2 v0.0.0-20181115013041-b67df6e626f9/go.mod h1:fLRUbhbSd5Px2yKUaGYYPltlyxi1guJz1vCmo1RQL50=
+github.com/microcosm-cc/bluemonday v1.0.2 h1:5lPfLTTAvAbtS0VqT+94yOtFnGfUWYyx0+iToC3Os3s=
+github.com/microcosm-cc/bluemonday v1.0.2/go.mod h1:iVP4YcDBq+n/5fb23BhYFvIMq/leAFZyRl6bYmGDlGc=
github.com/miekg/dns v1.0.14 h1:9jZdLNd/P4+SfEJ0TNyxYpsK8N4GtfylBLqtbYN1sbA=
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 h1:lYpkrQH5ajf0OXOcUbGjvZxxijuBwbbmlSxLiuofa+g=
@@ -436,6 +453,8 @@ github.com/modern-go/reflect2 v0.0.0-20180320133207-05fbef0ca5da/go.mod h1:bx2lN
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
+github.com/moul/http2curl v1.0.0 h1:dRMWoAtb+ePxMlLkrCbAqh4TlPHXvoGUSQ323/9Zahs=
+github.com/moul/http2curl v1.0.0/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ=
github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
@@ -443,21 +462,19 @@ github.com/nats-io/gnatsd v1.4.1 h1:RconcfDeWpKCD6QIIwiVFcvForlXpWeJP7i5/lDLy44=
github.com/nats-io/gnatsd v1.4.1/go.mod h1:nqco77VO78hLCJpIcVfygDP2rPGfsEHkGTUk94uh5DQ=
github.com/nats-io/go-nats v1.7.2 h1:cJujlwCYR8iMz5ofZSD/p2WLW8FabhkQ2lIEVbSvNSA=
github.com/nats-io/go-nats v1.7.2/go.mod h1:+t7RHT5ApZebkrQdnn6AhQJmhJJiKAvJUio1PiiCtj0=
-github.com/nats-io/jwt v0.2.6/go.mod h1:mQxQ0uHQ9FhEVPIcTSKwx2lqZEpXWWcCgA7R6NrWvvY=
-github.com/nats-io/nats-server/v2 v2.0.0/go.mod h1:RyVdsHHvY4B6c9pWG+uRLpZ0h0XsqiuKp2XCTurP5LI=
-github.com/nats-io/nats.go v1.8.1/go.mod h1:BrFz9vVn0fU3AcH9Vn4Kd7W0NpJ651tD5omQ3M8LwxM=
-github.com/nats-io/nkeys v0.0.2/go.mod h1:dab7URMsZm6Z/jp9Z5UGa87Uutgc2mVpXLC4B7TDb/4=
github.com/nats-io/nkeys v0.1.0 h1:qMd4+pRHgdr1nAClu+2h/2a5F2TmKcCzjCDazVgRoX4=
github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw=
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
+github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs=
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
-github.com/onsi/ginkgo v1.10.1 h1:q/mM8GF/n0shIN8SaAZ0V+jnLPzen6WIVZdiwrRlMlo=
-github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
+github.com/onsi/ginkgo v1.10.2 h1:uqH7bpe+ERSiDa34FDOF7RikN6RzXgduUF8yarlZp94=
+github.com/onsi/ginkgo v1.10.2/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
github.com/onsi/gomega v0.0.0-20190113212917-5533ce8a0da3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
+github.com/onsi/gomega v1.4.3 h1:RE1xgDvH7imwFD45h+u2SgIfERHlS2yNG4DObb5BSKU=
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.7.0 h1:XPnZz8VVBHjVsy1vzJmRwIcSwiUO+JFfrv/xGiigmME=
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
@@ -485,26 +502,19 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
-github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM=
-github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs=
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
github.com/prometheus/client_golang v1.2.1 h1:JnMpQc6ppsNgw9QPAGF6Dod479itz7lvlsMzzNayLOI=
github.com/prometheus/client_golang v1.2.1/go.mod h1:XMU6Z2MjaRKVu/dC1qupJI9SiNkDYzz3xecMgSW/F+U=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
-github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4 h1:gQz4mCbXsO+nc9n1hCxHcGA3Zx3Eo+UHZoInFGUIXNM=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
-github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
-github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.7.0 h1:L+1lyG48J1zAQXA3RBX/nG/B3gjlHq0zTt2tlbJLyCY=
github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA=
github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
-github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
-github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.0.5 h1:3+auTFlqw+ZaQYJARz6ArODtkaIwtvBTx3N2NehQlL8=
github.com/prometheus/procfs v0.0.5/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ=
@@ -517,6 +527,8 @@ github.com/rcrowley/go-metrics v0.0.0-20190826022208-cac0b30c2563/go.mod h1:bCqn
github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446/go.mod h1:uYEyJGbgTkfkS4+E/PavXkNJcbFIpEtjt2B0KDQ5+9M=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
+github.com/russross/blackfriday v2.0.0+incompatible h1:cBXrhZNUf9C+La9/YpS+UHpUT8YD6Td9ZMSU9APFcsk=
+github.com/russross/blackfriday v2.0.0+incompatible/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da h1:p3Vo3i64TCLY7gIfzeQaUJ+kppEO5WQG3cL8iE8tGHU=
github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E=
@@ -524,11 +536,19 @@ github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww=
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
+github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ=
+github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
+github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
+github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.1.1/go.mod h1:zrgwTnHtNr00buQ1vSptGe8m1f/BbgsPukg8qsT7A+A=
github.com/sirupsen/logrus v1.2.0 h1:juTguoYk5qI21pwyTXY3B3Y5cOTH3ZUyZCg1v/mihuo=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
+github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
+github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
+github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
+github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/soheilhy/cmux v0.1.4 h1:0HKaf1o97UwFjHH9o5XsHUOF+tqmdA7KEzXLpiyaw0E=
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
@@ -555,15 +575,29 @@ github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5 h1:LnC5Kc
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
-github.com/valyala/fasthttp v1.4.0 h1:PuaTGZIw3mjYhhhbVbCQp8aciRZN9YdoB7MGX9Ko76A=
-github.com/valyala/fasthttp v1.4.0/go.mod h1:4vX61m6KN+xDduDNwXrhIAVZaZaZiQ1luJk8LWSxF3s=
+github.com/valyala/fasthttp v1.6.0 h1:uWF8lgKmeaIewWVPwi4GRq2P6+R46IgYZdxWtM+GtEY=
+github.com/valyala/fasthttp v1.6.0/go.mod h1:FstJa9V+Pj9vQ7OJie2qMHdwemEDaDiSdBnvPM1Su9w=
github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio=
github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c h1:u40Z8hqBAAQyv+vATcGgV0YCnDjqSL7/q/JyPhhJSPk=
github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I=
github.com/xdg/stringprep v1.0.0 h1:d9X0esnoa3dFsV0FG35rAT0RIhYFlPq7MiP+DW89La0=
github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y=
+github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c=
+github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
+github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0=
+github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
+github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74=
+github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
+github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0 h1:6fRhSjgLCkTD3JnJxvaJ4Sj+TYblw757bqYgZaOq5ZY=
+github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI=
+github.com/yudai/gojsondiff v1.0.0 h1:27cbfqXLVEJ1o8I6v3y9lg8Ydm53EKqHXAOMxEGlCOA=
+github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg=
+github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 h1:BHyfKlQyqbsFN5p3IfnEUduWvb9is428/nNb5L3U01M=
+github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM=
+github.com/yudai/pp v2.0.1+incompatible h1:Q4//iY4pNF6yPLZIigmvcl7k/bPgrcTPIFIcmawg5bI=
+github.com/yudai/pp v2.0.1+incompatible/go.mod h1:PuxR/8QJ7cyCkFp/aUDS+JY727OFEZkTdatxwunjIkc=
go.etcd.io/bbolt v1.3.3 h1:MUGmc65QhB3pIlaQ5bB4LwqSj6GIonVJXpZiaKNyaKk=
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.etcd.io/etcd v3.3.17+incompatible h1:g8iRku1SID8QAW8cDlV0L/PkZlw63LSiYEHYHoE6j/s=
@@ -572,8 +606,6 @@ go.mongodb.org/mongo-driver v1.1.2 h1:jxcFYjlkl8xaERsgLo+RNquI0epW6zuy/ZRQs6jnrF
go.mongodb.org/mongo-driver v1.1.2/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
go.opencensus.io v0.15.0/go.mod h1:UffZAU+4sDEINUGP/B7UfBBkq4fqLu9zXAX7ke6CHW0=
go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA=
-go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
-go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
go.opencensus.io v0.21.0 h1:mU6zScU4U1YAFPHEHYk+3JC4SY7JxgkqS10ZOSyksNg=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
@@ -590,12 +622,10 @@ golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnf
golang.org/x/crypto v0.0.0-20181001203147-e3636079e1a4/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181025213731-e84da0312774/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
-golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190404164418-38d8ce5564a5/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
golang.org/x/crypto v0.0.0-20190418165655-df01cb2cc480/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
-golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8 h1:1wopBVtVdWnn03fZelqdXTqk7U7zPQCb+T4rbU9ZEoU=
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
@@ -631,13 +661,11 @@ golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73r
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
-golang.org/x/net v0.0.0-20180911220305-26e67e76b6c3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
-golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190206173232-65e2d4e15006/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
@@ -718,6 +746,7 @@ golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
@@ -742,7 +771,6 @@ gonum.org/v1/netlib v0.0.0-20190331212654-76723241ea4e h1:jRyg0XfpwWlhEV8mDfdNGB
gonum.org/v1/netlib v0.0.0-20190331212654-76723241ea4e/go.mod h1:kS+toOQn6AQKjmKJ7gzohV1XkqsFehRA2FbsbkopSuQ=
gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc=
google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
-google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
google.golang.org/api v0.6.0/go.mod h1:btoxGiFvQNVUZQ8W08zLtrVS08CNpINPEfxXxgJL1Q4=
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
@@ -764,7 +792,6 @@ google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRn
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb h1:i1Ppqkc3WQXikh8bXiwHqAN5Rv3/qDCcRk0/Otx73BY=
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
-google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s=
google.golang.org/genproto v0.0.0-20190620144150-6af8c5fc6601/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s=
google.golang.org/genproto v0.0.0-20190716160619-c506a9f90610/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
@@ -775,15 +802,12 @@ google.golang.org/genproto v0.0.0-20190927181202-20e1ac93f88c/go.mod h1:IbNlFCBr
google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
-google.golang.org/grpc v1.19.1/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1 h1:Hz2g2wirWK7H0qIIhGIqRGTuMwTE8HEKFnDZZ7lm9NU=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
google.golang.org/grpc v1.22.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.24.0 h1:vb/1TCsVn3DcJlQ0Gs1yB1pKI6Do2/QNwxdKqmc/b0s=
google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA=
-gopkg.in/airbrake/gobrake.v2 v2.0.9 h1:7z2uVWwn7oVeeugY1DtlPAy5H+KYgB1KeKTnqjNatLo=
-gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
@@ -799,8 +823,6 @@ gopkg.in/couchbaselabs/jsonx.v1 v1.0.0/go.mod h1:oR201IRovxvLW/eISevH12/+MiKHtNQ
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
-gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2 h1:OAj3g0cR6Dx/R07QgQe8wkA9RNjB2u4i700xBkIT4e0=
-gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo=
gopkg.in/inf.v0 v0.9.0/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
@@ -815,6 +837,8 @@ gopkg.in/jcmturner/gokrb5.v7 v7.3.0 h1:0709Jtq/6QXEuWRfAm260XqlpcwL1vxtO1tUE2qK8
gopkg.in/jcmturner/gokrb5.v7 v7.3.0/go.mod h1:l8VISx+WGYp+Fp7KRbsiUuXTTOnxIc3Tuvyavf11/WM=
gopkg.in/jcmturner/rpc.v1 v1.1.0 h1:QHIUxTX1ISuAv9dD2wJ9HWQVuWDX/Zc0PfeC2tjc4rU=
gopkg.in/jcmturner/rpc.v1 v1.1.0/go.mod h1:YIdkC4XfD6GXbzje11McwsDuOlZQSb9W4vfLvuNnlv8=
+gopkg.in/kataras/go-serializer.v0 v0.0.4 h1:mVy3gjU4zZZBe+8JbZDRTMPJdrB0lzBNsLLREBcKGgU=
+gopkg.in/kataras/go-serializer.v0 v0.0.4/go.mod h1:v2jHg/3Wp7uncDNzenTsX75PRDxhzlxoo/qDvM4ZGxk=
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
diff --git a/pkg/actors/actors.go b/pkg/actors/actors.go
index f3c09d0cfde..69f4407edf4 100644
--- a/pkg/actors/actors.go
+++ b/pkg/actors/actors.go
@@ -15,7 +15,7 @@ import (
"sync"
"time"
- log "github.com/Sirupsen/logrus"
+ log "github.com/sirupsen/logrus"
"github.com/dapr/components-contrib/state"
"github.com/dapr/dapr/pkg/channel"
"github.com/dapr/dapr/pkg/channel/http"
diff --git a/pkg/apis/configuration/v1alpha1/types.go b/pkg/apis/configuration/v1alpha1/types.go
index 906365deef1..7ec0fe231f0 100644
--- a/pkg/apis/configuration/v1alpha1/types.go
+++ b/pkg/apis/configuration/v1alpha1/types.go
@@ -38,6 +38,7 @@ type PipelineSpec struct {
// HandlerSpec defines a request handlers
type HandlerSpec struct {
Name string `json:"name"`
+ Type string `json:"type"`
SelectorSpec SelectorSpec `json:"selector,omitempty"`
}
diff --git a/pkg/components/kubernetes_loader.go b/pkg/components/kubernetes_loader.go
index 965382c4011..668f639d94e 100644
--- a/pkg/components/kubernetes_loader.go
+++ b/pkg/components/kubernetes_loader.go
@@ -10,7 +10,7 @@ import (
"fmt"
"time"
- log "github.com/Sirupsen/logrus"
+ log "github.com/sirupsen/logrus"
"github.com/cenkalti/backoff"
components_v1alpha1 "github.com/dapr/dapr/pkg/apis/components/v1alpha1"
config "github.com/dapr/dapr/pkg/config/modes"
diff --git a/pkg/components/middleware/http/loader.go b/pkg/components/middleware/http/loader.go
index f24aae81144..d006172f641 100644
--- a/pkg/components/middleware/http/loader.go
+++ b/pkg/components/middleware/http/loader.go
@@ -8,13 +8,15 @@ package http
import (
"strings"
+ middleware "github.com/dapr/components-contrib/middleware"
+ "github.com/dapr/components-contrib/middleware/http/oauth2"
http_middleware "github.com/dapr/dapr/pkg/middleware/http"
"github.com/valyala/fasthttp"
)
// Load HTTP middleware
func Load() {
- RegisterMiddleware("uppercase", func() http_middleware.Middleware {
+ RegisterMiddleware("uppercase", func(metadata middleware.Metadata) http_middleware.Middleware {
return func(h fasthttp.RequestHandler) fasthttp.RequestHandler {
return func(ctx *fasthttp.RequestCtx) {
body := string(ctx.PostBody())
@@ -23,4 +25,8 @@ func Load() {
}
}
})
+ RegisterMiddleware("oauth2", func(metadata middleware.Metadata) http_middleware.Middleware {
+ handler, _ := oauth2.NewOAuth2Middleware().GetHandler(metadata)
+ return handler
+ })
}
diff --git a/pkg/components/middleware/http/registry.go b/pkg/components/middleware/http/registry.go
index 7878298469f..94ba5e7570b 100644
--- a/pkg/components/middleware/http/registry.go
+++ b/pkg/components/middleware/http/registry.go
@@ -9,16 +9,17 @@ import (
"fmt"
"sync"
+ middleware "github.com/dapr/components-contrib/middleware"
http_middleware "github.com/dapr/dapr/pkg/middleware/http"
)
// Registry is the interface for callers to get registered HTTP middleware
type Registry interface {
- CreateMiddleware(name string) (http_middleware.Middleware, error)
+ CreateMiddleware(name string, metadata middleware.Metadata) (http_middleware.Middleware, error)
}
type httpMiddlewareRegistry struct {
- middleware map[string]func() http_middleware.Middleware
+ middleware map[string]func(middleware.Metadata) http_middleware.Middleware
}
var instance *httpMiddlewareRegistry
@@ -28,14 +29,14 @@ var once sync.Once
func NewRegistry() Registry {
once.Do(func() {
instance = &httpMiddlewareRegistry{
- middleware: map[string]func() http_middleware.Middleware{},
+ middleware: map[string]func(middleware.Metadata) http_middleware.Middleware{},
}
})
return instance
}
// RegisterMiddleware registers a new HTTP middleware
-func RegisterMiddleware(name string, factoryMethod func() http_middleware.Middleware) {
+func RegisterMiddleware(name string, factoryMethod func(metadata middleware.Metadata) http_middleware.Middleware) {
instance.middleware[createFullName(name)] = factoryMethod
}
@@ -43,9 +44,9 @@ func createFullName(name string) string {
return fmt.Sprintf("middleware.http.%s", name)
}
-func (p *httpMiddlewareRegistry) CreateMiddleware(name string) (http_middleware.Middleware, error) {
+func (p *httpMiddlewareRegistry) CreateMiddleware(name string, metadata middleware.Metadata) (http_middleware.Middleware, error) {
if method, ok := p.middleware[name]; ok {
- return method(), nil
+ return method(metadata), nil
}
return nil, fmt.Errorf("couldn't find HTTP middleware %s", name)
}
diff --git a/pkg/components/standalone_loader.go b/pkg/components/standalone_loader.go
index 1cf164e2eaa..d7d20e852f5 100644
--- a/pkg/components/standalone_loader.go
+++ b/pkg/components/standalone_loader.go
@@ -9,7 +9,7 @@ import (
"fmt"
"io/ioutil"
- log "github.com/Sirupsen/logrus"
+ log "github.com/sirupsen/logrus"
components_v1alpha1 "github.com/dapr/dapr/pkg/apis/components/v1alpha1"
config "github.com/dapr/dapr/pkg/config/modes"
"github.com/ghodss/yaml"
diff --git a/pkg/config/configuration.go b/pkg/config/configuration.go
index a8aa3dbbad1..0351e7966c2 100644
--- a/pkg/config/configuration.go
+++ b/pkg/config/configuration.go
@@ -31,6 +31,7 @@ type PipelineSpec struct {
type HandlerSpec struct {
Name string `json:"name"`
+ Type string `json:"type"`
SelectorSpec SelectorSpec `json:"selector,omitempty"`
}
diff --git a/pkg/discovery/mdns.go b/pkg/discovery/mdns.go
index 3f14d40f64b..14680f354fb 100644
--- a/pkg/discovery/mdns.go
+++ b/pkg/discovery/mdns.go
@@ -13,7 +13,7 @@ import (
"syscall"
"time"
- log "github.com/Sirupsen/logrus"
+ log "github.com/sirupsen/logrus"
"github.com/grandcat/zeroconf"
)
diff --git a/pkg/grpc/server.go b/pkg/grpc/server.go
index e81b4a10e9a..18c2f1580de 100644
--- a/pkg/grpc/server.go
+++ b/pkg/grpc/server.go
@@ -9,7 +9,7 @@ import (
"fmt"
"net"
- log "github.com/Sirupsen/logrus"
+ log "github.com/sirupsen/logrus"
"github.com/dapr/dapr/pkg/config"
diag "github.com/dapr/dapr/pkg/diagnostics"
dapr_pb "github.com/dapr/dapr/pkg/proto/dapr"
diff --git a/pkg/http/api_test.go b/pkg/http/api_test.go
index ad1c1c2f281..6d99eee195a 100644
--- a/pkg/http/api_test.go
+++ b/pkg/http/api_test.go
@@ -22,6 +22,7 @@ import (
"github.com/dapr/components-contrib/bindings"
"github.com/dapr/components-contrib/exporters"
"github.com/dapr/components-contrib/exporters/stringexporter"
+ "github.com/dapr/components-contrib/middleware"
"github.com/dapr/components-contrib/state"
"github.com/dapr/dapr/pkg/actors"
"github.com/dapr/dapr/pkg/channel/http"
@@ -967,7 +968,7 @@ func buildHTTPPineline(spec config.PipelineSpec) http_middleware.Pipeline {
http_middleware_loader.Load()
var handlers []http_middleware.Middleware
for i := 0; i < len(spec.Handlers); i++ {
- handler, err := registry.CreateMiddleware(spec.Handlers[i].Name)
+ handler, err := registry.CreateMiddleware(spec.Handlers[i].Type, middleware.Metadata{})
if err != nil {
return http_middleware.Pipeline{}
}
@@ -996,6 +997,7 @@ func TestSinglePipelineWithTracer(t *testing.T) {
pipeline := buildHTTPPineline(config.PipelineSpec{
Handlers: []config.HandlerSpec{
config.HandlerSpec{
+ Type: "middleware.http.uppercase",
Name: "middleware.http.uppercase",
},
},
diff --git a/pkg/http/server.go b/pkg/http/server.go
index 4b52f82cc49..f2416dc3210 100644
--- a/pkg/http/server.go
+++ b/pkg/http/server.go
@@ -10,7 +10,7 @@ import (
"strings"
cors "github.com/AdhityaRamadhanus/fasthttpcors"
- log "github.com/Sirupsen/logrus"
+ log "github.com/sirupsen/logrus"
"github.com/dapr/dapr/pkg/config"
diag "github.com/dapr/dapr/pkg/diagnostics"
http_middleware "github.com/dapr/dapr/pkg/middleware/http"
diff --git a/pkg/injector/injector.go b/pkg/injector/injector.go
index 68e8602634e..f71e4a6dd57 100644
--- a/pkg/injector/injector.go
+++ b/pkg/injector/injector.go
@@ -13,7 +13,7 @@ import (
"net/http"
"time"
- log "github.com/Sirupsen/logrus"
+ log "github.com/sirupsen/logrus"
"k8s.io/api/admission/v1beta1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
diff --git a/pkg/injector/pod_patch.go b/pkg/injector/pod_patch.go
index a854b0cf20e..c030e55d7aa 100644
--- a/pkg/injector/pod_patch.go
+++ b/pkg/injector/pod_patch.go
@@ -11,7 +11,7 @@ import (
"strconv"
"strings"
- log "github.com/Sirupsen/logrus"
+ log "github.com/sirupsen/logrus"
"k8s.io/api/admission/v1beta1"
corev1 "k8s.io/api/core/v1"
)
diff --git a/pkg/operator/api/api.go b/pkg/operator/api/api.go
index ae7ca861c76..e07ac37f93c 100644
--- a/pkg/operator/api/api.go
+++ b/pkg/operator/api/api.go
@@ -13,7 +13,7 @@ import (
"net/http"
"time"
- log "github.com/Sirupsen/logrus"
+ log "github.com/sirupsen/logrus"
scheme "github.com/dapr/dapr/pkg/client/clientset/versioned"
"github.com/gorilla/mux"
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -45,6 +45,7 @@ type PipelineSpec struct {
type HandlerSpec struct {
Name string `json:"name"`
+ Type string `json:"type"`
SelectorSpec SelectorSpec `json:"selector,omitempty"`
}
diff --git a/pkg/operator/handlers/components.go b/pkg/operator/handlers/components.go
index 9022a8b6a80..728ed376f07 100644
--- a/pkg/operator/handlers/components.go
+++ b/pkg/operator/handlers/components.go
@@ -5,7 +5,7 @@ import (
"fmt"
"time"
- log "github.com/Sirupsen/logrus"
+ log "github.com/sirupsen/logrus"
components_v1alpha1 "github.com/dapr/dapr/pkg/apis/components/v1alpha1"
pb "github.com/dapr/dapr/pkg/proto/daprinternal"
"google.golang.org/grpc"
diff --git a/pkg/operator/handlers/dapr_handler.go b/pkg/operator/handlers/dapr_handler.go
index 605bf783300..a57c72ced85 100644
--- a/pkg/operator/handlers/dapr_handler.go
+++ b/pkg/operator/handlers/dapr_handler.go
@@ -5,7 +5,7 @@ import (
"strings"
"sync"
- log "github.com/Sirupsen/logrus"
+ log "github.com/sirupsen/logrus"
"github.com/dapr/dapr/pkg/kubernetes"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
diff --git a/pkg/operator/operator.go b/pkg/operator/operator.go
index 726b0d3581b..023a9a747e4 100644
--- a/pkg/operator/operator.go
+++ b/pkg/operator/operator.go
@@ -8,7 +8,7 @@ package operator
import (
"context"
- log "github.com/Sirupsen/logrus"
+ log "github.com/sirupsen/logrus"
scheme "github.com/dapr/dapr/pkg/client/clientset/versioned"
k8s "github.com/dapr/dapr/pkg/kubernetes"
"github.com/dapr/dapr/pkg/operator/api"
diff --git a/pkg/placement/placement.go b/pkg/placement/placement.go
index 4bf576d2317..ac94728f86c 100644
--- a/pkg/placement/placement.go
+++ b/pkg/placement/placement.go
@@ -11,7 +11,7 @@ import (
"net"
"sync"
- log "github.com/Sirupsen/logrus"
+ log "github.com/sirupsen/logrus"
daprinternal_pb "github.com/dapr/dapr/pkg/proto/daprinternal"
"google.golang.org/grpc"
"google.golang.org/grpc/metadata"
diff --git a/pkg/runtime/runtime.go b/pkg/runtime/runtime.go
index 86a82fa12a0..85b7b53d9d4 100644
--- a/pkg/runtime/runtime.go
+++ b/pkg/runtime/runtime.go
@@ -16,9 +16,11 @@ import (
"sync"
"time"
- log "github.com/Sirupsen/logrus"
+ log "github.com/sirupsen/logrus"
"github.com/dapr/components-contrib/bindings"
"github.com/dapr/components-contrib/exporters"
+ "github.com/dapr/components-contrib/middleware"
+
"github.com/dapr/components-contrib/pubsub"
"github.com/dapr/components-contrib/secretstores"
"github.com/dapr/components-contrib/servicediscovery"
@@ -200,7 +202,14 @@ func (a *DaprRuntime) buildHTTPPipeline() (http_middleware.Pipeline, error) {
http_middleware_loader.Load()
var handlers []http_middleware.Middleware
for i := 0; i < len(a.globalConfig.Spec.HTTPPipelineSpec.Handlers); i++ {
- handler, err := a.httpMiddlewareRegistry.CreateMiddleware(a.globalConfig.Spec.HTTPPipelineSpec.Handlers[i].Name)
+ component := a.getComponent(a.globalConfig.Spec.HTTPPipelineSpec.Handlers[i].Type, a.globalConfig.Spec.HTTPPipelineSpec.Handlers[i].Name)
+ if component == nil {
+ return http_middleware.Pipeline{}, fmt.Errorf("couldn't find middleware %s of type %s",
+ a.globalConfig.Spec.HTTPPipelineSpec.Handlers[i].Name,
+ a.globalConfig.Spec.HTTPPipelineSpec.Handlers[i].Type)
+ }
+ handler, err := a.httpMiddlewareRegistry.CreateMiddleware(a.globalConfig.Spec.HTTPPipelineSpec.Handlers[i].Type,
+ middleware.Metadata{Properties: a.convertMetadataItemsToProperties(component.Spec.Metadata)})
if err != nil {
return http_middleware.Pipeline{}, err
}
@@ -1048,3 +1057,13 @@ func (a *DaprRuntime) convertMetadataItemsToProperties(items []components_v1alph
}
return properties
}
+
+func (a *DaprRuntime) getComponent(componentType string, name string) *components_v1alpha1.Component {
+ for _, c := range a.components {
+ fmt.Printf("COMPONENT TYPE: %s, NAME: %s\n", c.Spec.Type, c.ObjectMeta.Name)
+ if c.Spec.Type == componentType && c.ObjectMeta.Name == name {
+ return &c
+ }
+ }
+ return nil
+}
diff --git a/pkg/signals/signals.go b/pkg/signals/signals.go
index 6362c6a037a..c274b242203 100644
--- a/pkg/signals/signals.go
+++ b/pkg/signals/signals.go
@@ -11,7 +11,7 @@ import (
"os/signal"
"syscall"
- log "github.com/Sirupsen/logrus"
+ log "github.com/sirupsen/logrus"
)
// Context returns a context which will be canceled when either the SIGINT or
diff --git a/tests/platforms/kubernetes/appmanager.go b/tests/platforms/kubernetes/appmanager.go
index 6feea93ba92..a35ba4bf155 100644
--- a/tests/platforms/kubernetes/appmanager.go
+++ b/tests/platforms/kubernetes/appmanager.go
@@ -10,7 +10,7 @@ import (
"os"
"time"
- log "github.com/Sirupsen/logrus"
+ log "github.com/sirupsen/logrus"
appsv1 "k8s.io/api/apps/v1"
apiv1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors"
diff --git a/tests/runner/kube_testplatform.go b/tests/runner/kube_testplatform.go
index 1268edd4040..89fc9aa7228 100644
--- a/tests/runner/kube_testplatform.go
+++ b/tests/runner/kube_testplatform.go
@@ -9,7 +9,7 @@ import (
"fmt"
"os"
- log "github.com/Sirupsen/logrus"
+ log "github.com/sirupsen/logrus"
kube "github.com/dapr/dapr/tests/platforms/kubernetes"
)
diff --git a/tests/runner/testresource.go b/tests/runner/testresource.go
index 5ddada99736..5f4d268fabc 100644
--- a/tests/runner/testresource.go
+++ b/tests/runner/testresource.go
@@ -8,7 +8,7 @@ package runner
import (
"sync"
- log "github.com/Sirupsen/logrus"
+ log "github.com/sirupsen/logrus"
)
// Disposable is an interface representing the disposable test resources
diff --git a/tests/runner/testrunner.go b/tests/runner/testrunner.go
index 9d1c3754daa..324a0a368f1 100644
--- a/tests/runner/testrunner.go
+++ b/tests/runner/testrunner.go
@@ -6,7 +6,7 @@
package runner
import (
- log "github.com/Sirupsen/logrus"
+ log "github.com/sirupsen/logrus"
kube "github.com/dapr/dapr/tests/platforms/kubernetes"
)
diff --git a/vendor/github.com/Sirupsen/logrus/.travis.yml b/vendor/github.com/Sirupsen/logrus/.travis.yml
deleted file mode 100644
index 2f19b4a757a..00000000000
--- a/vendor/github.com/Sirupsen/logrus/.travis.yml
+++ /dev/null
@@ -1,13 +0,0 @@
-language: go
-go:
- - 1.9.x
- - 1.10.x
-env:
- - GOMAXPROCS=4 GORACE=halt_on_error=1
-install:
- - go get github.com/stretchr/testify/assert
- - go get gopkg.in/gemnasium/logrus-airbrake-hook.v2
- - go get golang.org/x/sys/unix
- - go get golang.org/x/sys/windows
-script:
- - go test -race -v ./...
diff --git a/vendor/github.com/Sirupsen/logrus/CHANGELOG.md b/vendor/github.com/Sirupsen/logrus/CHANGELOG.md
deleted file mode 100644
index 1bd1deb2947..00000000000
--- a/vendor/github.com/Sirupsen/logrus/CHANGELOG.md
+++ /dev/null
@@ -1,123 +0,0 @@
-# 1.0.5
-
-* Fix hooks race (#707)
-* Fix panic deadlock (#695)
-
-# 1.0.4
-
-* Fix race when adding hooks (#612)
-* Fix terminal check in AppEngine (#635)
-
-# 1.0.3
-
-* Replace example files with testable examples
-
-# 1.0.2
-
-* bug: quote non-string values in text formatter (#583)
-* Make (*Logger) SetLevel a public method
-
-# 1.0.1
-
-* bug: fix escaping in text formatter (#575)
-
-# 1.0.0
-
-* Officially changed name to lower-case
-* bug: colors on Windows 10 (#541)
-* bug: fix race in accessing level (#512)
-
-# 0.11.5
-
-* feature: add writer and writerlevel to entry (#372)
-
-# 0.11.4
-
-* bug: fix undefined variable on solaris (#493)
-
-# 0.11.3
-
-* formatter: configure quoting of empty values (#484)
-* formatter: configure quoting character (default is `"`) (#484)
-* bug: fix not importing io correctly in non-linux environments (#481)
-
-# 0.11.2
-
-* bug: fix windows terminal detection (#476)
-
-# 0.11.1
-
-* bug: fix tty detection with custom out (#471)
-
-# 0.11.0
-
-* performance: Use bufferpool to allocate (#370)
-* terminal: terminal detection for app-engine (#343)
-* feature: exit handler (#375)
-
-# 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)
-* logrus/doc: small typo fixes and doc improvements
-
-
-# 0.8.6
-
-* hooks/raven: allow passing an initialized client
-
-# 0.8.5
-
-* logrus/core: revert #208
-
-# 0.8.4
-
-* formatter/text: fix data race (#218)
-
-# 0.8.3
-
-* logrus/core: fix entry log level (#208)
-* logrus/core: improve performance of text formatter by 40%
-* logrus/core: expose `LevelHooks` type
-* logrus/core: add support for DragonflyBSD and NetBSD
-* formatter/text: print structs more verbosely
-
-# 0.8.2
-
-* logrus: fix more Fatal family functions
-
-# 0.8.1
-
-* logrus: fix not exiting on `Fatalf` and `Fatalln`
-
-# 0.8.0
-
-* logrus: defaults to stderr instead of stdout
-* hooks/sentry: add special field for `*http.Request`
-* formatter/text: ignore Windows for colors
-
-# 0.7.3
-
-* formatter/\*: allow configuration of timestamp layout
-
-# 0.7.2
-
-* formatter/text: Add configuration option for time format (#158)
diff --git a/vendor/github.com/Sirupsen/logrus/terminal_bsd.go b/vendor/github.com/Sirupsen/logrus/terminal_bsd.go
deleted file mode 100644
index 4880d13d26d..00000000000
--- a/vendor/github.com/Sirupsen/logrus/terminal_bsd.go
+++ /dev/null
@@ -1,10 +0,0 @@
-// +build darwin freebsd openbsd netbsd dragonfly
-// +build !appengine,!gopherjs
-
-package logrus
-
-import "golang.org/x/sys/unix"
-
-const ioctlReadTermios = unix.TIOCGETA
-
-type Termios unix.Termios
diff --git a/vendor/github.com/Sirupsen/logrus/terminal_linux.go b/vendor/github.com/Sirupsen/logrus/terminal_linux.go
deleted file mode 100644
index f29a0097c81..00000000000
--- a/vendor/github.com/Sirupsen/logrus/terminal_linux.go
+++ /dev/null
@@ -1,14 +0,0 @@
-// Based on ssh/terminal:
-// Copyright 2013 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build !appengine,!gopherjs
-
-package logrus
-
-import "golang.org/x/sys/unix"
-
-const ioctlReadTermios = unix.TCGETS
-
-type Termios unix.Termios
diff --git a/vendor/github.com/Sirupsen/logrus/text_formatter.go b/vendor/github.com/Sirupsen/logrus/text_formatter.go
deleted file mode 100644
index 3e55040304d..00000000000
--- a/vendor/github.com/Sirupsen/logrus/text_formatter.go
+++ /dev/null
@@ -1,195 +0,0 @@
-package logrus
-
-import (
- "bytes"
- "fmt"
- "sort"
- "strings"
- "sync"
- "time"
-)
-
-const (
- nocolor = 0
- red = 31
- green = 32
- yellow = 33
- blue = 36
- gray = 37
-)
-
-var (
- baseTimestamp time.Time
- emptyFieldMap FieldMap
-)
-
-func init() {
- baseTimestamp = time.Now()
-}
-
-// TextFormatter formats logs into text
-type TextFormatter struct {
- // Set to true to bypass checking for a TTY before outputting colors.
- ForceColors bool
-
- // Force disabling colors.
- DisableColors bool
-
- // Disable timestamp logging. useful when output is redirected to logging
- // system that already adds timestamps.
- DisableTimestamp bool
-
- // Enable logging the full timestamp when a TTY is attached instead of just
- // the time passed since beginning of execution.
- FullTimestamp bool
-
- // TimestampFormat to use for display when a full timestamp is printed
- TimestampFormat string
-
- // The fields are sorted by default for a consistent output. For applications
- // that log extremely frequently and don't use the JSON formatter this may not
- // be desired.
- DisableSorting bool
-
- // Disables the truncation of the level text to 4 characters.
- DisableLevelTruncation bool
-
- // QuoteEmptyFields will wrap empty fields in quotes if true
- QuoteEmptyFields bool
-
- // Whether the logger's out is to a terminal
- isTerminal bool
-
- // FieldMap allows users to customize the names of keys for default fields.
- // As an example:
- // formatter := &TextFormatter{
- // FieldMap: FieldMap{
- // FieldKeyTime: "@timestamp",
- // FieldKeyLevel: "@level",
- // FieldKeyMsg: "@message"}}
- FieldMap FieldMap
-
- sync.Once
-}
-
-func (f *TextFormatter) init(entry *Entry) {
- if entry.Logger != nil {
- f.isTerminal = checkIfTerminal(entry.Logger.Out)
- }
-}
-
-// Format renders a single log entry
-func (f *TextFormatter) Format(entry *Entry) ([]byte, error) {
- prefixFieldClashes(entry.Data, f.FieldMap)
-
- keys := make([]string, 0, len(entry.Data))
- for k := range entry.Data {
- keys = append(keys, k)
- }
-
- if !f.DisableSorting {
- sort.Strings(keys)
- }
-
- var b *bytes.Buffer
- if entry.Buffer != nil {
- b = entry.Buffer
- } else {
- b = &bytes.Buffer{}
- }
-
- f.Do(func() { f.init(entry) })
-
- isColored := (f.ForceColors || f.isTerminal) && !f.DisableColors
-
- timestampFormat := f.TimestampFormat
- if timestampFormat == "" {
- timestampFormat = defaultTimestampFormat
- }
- if isColored {
- f.printColored(b, entry, keys, timestampFormat)
- } else {
- if !f.DisableTimestamp {
- f.appendKeyValue(b, f.FieldMap.resolve(FieldKeyTime), entry.Time.Format(timestampFormat))
- }
- f.appendKeyValue(b, f.FieldMap.resolve(FieldKeyLevel), entry.Level.String())
- if entry.Message != "" {
- f.appendKeyValue(b, f.FieldMap.resolve(FieldKeyMsg), entry.Message)
- }
- for _, key := range keys {
- f.appendKeyValue(b, key, entry.Data[key])
- }
- }
-
- b.WriteByte('\n')
- return b.Bytes(), nil
-}
-
-func (f *TextFormatter) printColored(b *bytes.Buffer, entry *Entry, keys []string, timestampFormat string) {
- var levelColor int
- switch entry.Level {
- case DebugLevel:
- levelColor = gray
- case WarnLevel:
- levelColor = yellow
- case ErrorLevel, FatalLevel, PanicLevel:
- levelColor = red
- default:
- levelColor = blue
- }
-
- levelText := strings.ToUpper(entry.Level.String())
- if !f.DisableLevelTruncation {
- levelText = levelText[0:4]
- }
-
- if f.DisableTimestamp {
- fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m %-44s ", levelColor, levelText, entry.Message)
- } else if !f.FullTimestamp {
- fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%04d] %-44s ", levelColor, levelText, int(entry.Time.Sub(baseTimestamp)/time.Second), entry.Message)
- } else {
- fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%s] %-44s ", levelColor, levelText, entry.Time.Format(timestampFormat), entry.Message)
- }
- for _, k := range keys {
- v := entry.Data[k]
- fmt.Fprintf(b, " \x1b[%dm%s\x1b[0m=", levelColor, k)
- f.appendValue(b, v)
- }
-}
-
-func (f *TextFormatter) needsQuoting(text string) bool {
- if f.QuoteEmptyFields && len(text) == 0 {
- return true
- }
- for _, ch := range text {
- if !((ch >= 'a' && ch <= 'z') ||
- (ch >= 'A' && ch <= 'Z') ||
- (ch >= '0' && ch <= '9') ||
- ch == '-' || ch == '.' || ch == '_' || ch == '/' || ch == '@' || ch == '^' || ch == '+') {
- return true
- }
- }
- return false
-}
-
-func (f *TextFormatter) appendKeyValue(b *bytes.Buffer, key string, value interface{}) {
- if b.Len() > 0 {
- b.WriteByte(' ')
- }
- b.WriteString(key)
- b.WriteByte('=')
- f.appendValue(b, value)
-}
-
-func (f *TextFormatter) appendValue(b *bytes.Buffer, value interface{}) {
- stringVal, ok := value.(string)
- if !ok {
- stringVal = fmt.Sprint(value)
- }
-
- if !f.needsQuoting(stringVal) {
- b.WriteString(stringVal)
- } else {
- b.WriteString(fmt.Sprintf("%q", stringVal))
- }
-}
diff --git a/vendor/github.com/dapr/components-contrib/bindings/aws/s3/s3.go b/vendor/github.com/dapr/components-contrib/bindings/aws/s3/s3.go
index bc6860df50c..f6cd2da624c 100644
--- a/vendor/github.com/dapr/components-contrib/bindings/aws/s3/s3.go
+++ b/vendor/github.com/dapr/components-contrib/bindings/aws/s3/s3.go
@@ -9,7 +9,7 @@ import (
"bytes"
"encoding/json"
- log "github.com/Sirupsen/logrus"
+ log "github.com/sirupsen/logrus"
"github.com/aws/aws-sdk-go/service/s3/s3manager"
"github.com/google/uuid"
diff --git a/vendor/github.com/dapr/components-contrib/bindings/aws/sqs/sqs.go b/vendor/github.com/dapr/components-contrib/bindings/aws/sqs/sqs.go
index 6cd033b89e9..9007bb21aa7 100644
--- a/vendor/github.com/dapr/components-contrib/bindings/aws/sqs/sqs.go
+++ b/vendor/github.com/dapr/components-contrib/bindings/aws/sqs/sqs.go
@@ -11,7 +11,7 @@ import (
"github.com/aws/aws-sdk-go/aws/credentials"
- log "github.com/Sirupsen/logrus"
+ log "github.com/sirupsen/logrus"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/sqs"
diff --git a/vendor/github.com/dapr/components-contrib/bindings/azure/blobstorage/blobstorage.go b/vendor/github.com/dapr/components-contrib/bindings/azure/blobstorage/blobstorage.go
index b38c5089a44..e741243d263 100644
--- a/vendor/github.com/dapr/components-contrib/bindings/azure/blobstorage/blobstorage.go
+++ b/vendor/github.com/dapr/components-contrib/bindings/azure/blobstorage/blobstorage.go
@@ -13,7 +13,7 @@ import (
"github.com/google/uuid"
- log "github.com/Sirupsen/logrus"
+ log "github.com/sirupsen/logrus"
"github.com/Azure/azure-storage-blob-go/azblob"
"github.com/dapr/components-contrib/bindings"
diff --git a/vendor/github.com/dapr/components-contrib/bindings/azure/eventhubs/eventhubs.go b/vendor/github.com/dapr/components-contrib/bindings/azure/eventhubs/eventhubs.go
index f64d65d5da3..e498de66cc9 100644
--- a/vendor/github.com/dapr/components-contrib/bindings/azure/eventhubs/eventhubs.go
+++ b/vendor/github.com/dapr/components-contrib/bindings/azure/eventhubs/eventhubs.go
@@ -14,7 +14,7 @@ import (
"time"
eventhub "github.com/Azure/azure-event-hubs-go"
- log "github.com/Sirupsen/logrus"
+ log "github.com/sirupsen/logrus"
"github.com/dapr/components-contrib/bindings"
)
diff --git a/vendor/github.com/dapr/components-contrib/bindings/kafka/kafka.go b/vendor/github.com/dapr/components-contrib/bindings/kafka/kafka.go
index 025838b1fea..93daac875e8 100644
--- a/vendor/github.com/dapr/components-contrib/bindings/kafka/kafka.go
+++ b/vendor/github.com/dapr/components-contrib/bindings/kafka/kafka.go
@@ -17,7 +17,7 @@ import (
"syscall"
"github.com/Shopify/sarama"
- log "github.com/Sirupsen/logrus"
+ log "github.com/sirupsen/logrus"
"github.com/dapr/components-contrib/bindings"
)
diff --git a/vendor/github.com/dapr/components-contrib/middleware/http/oauth2/oauth2_middleware.go b/vendor/github.com/dapr/components-contrib/middleware/http/oauth2/oauth2_middleware.go
new file mode 100644
index 00000000000..95b1e2fd81b
--- /dev/null
+++ b/vendor/github.com/dapr/components-contrib/middleware/http/oauth2/oauth2_middleware.go
@@ -0,0 +1,115 @@
+// ------------------------------------------------------------
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+// ------------------------------------------------------------
+
+package oauth2
+
+import (
+ "encoding/json"
+ "strings"
+
+ "context"
+
+ "github.com/dapr/components-contrib/middleware"
+ "github.com/fasthttp-contrib/sessions"
+ "github.com/google/uuid"
+ "github.com/valyala/fasthttp"
+ "golang.org/x/oauth2"
+)
+
+// Metadata is the oAuth middleware config
+type oAuth2MiddlewareMetadata struct {
+ ClientID string `json:"clientID"`
+ ClientSecret string `json:"clientSecret"`
+ Scopes string `json:"scopes"`
+ AuthURL string `json:"authURL"`
+ TokenURL string `json:"tokenURL"`
+ AuthHeaderName string `json:"authHeaderName"`
+ RedirectURL string `json:"redirectURL"`
+}
+
+// NewOAuth2Middleware returns a new oAuth2 middleware
+func NewOAuth2Middleware() *Middleware {
+ return &Middleware{}
+}
+
+// Middleware is an oAuth2 authentication middleware
+type Middleware struct {
+}
+
+const (
+ stateParam = "state"
+ savedState = "auth-state"
+ redirectPath = "redirect-url"
+ codeParam = "code"
+)
+
+// GetHandler retruns the HTTP handler provided by the middleware
+func (m *Middleware) GetHandler(metadata middleware.Metadata) (func(h fasthttp.RequestHandler) fasthttp.RequestHandler, error) {
+ meta, err := m.getNativeMetadata(metadata)
+ if err != nil {
+ return nil, err
+ }
+
+ return func(h fasthttp.RequestHandler) fasthttp.RequestHandler {
+ return func(ctx *fasthttp.RequestCtx) {
+ conf := &oauth2.Config{
+ ClientID: meta.ClientID,
+ ClientSecret: meta.ClientSecret,
+ Scopes: strings.Split(meta.Scopes, ","),
+ RedirectURL: meta.RedirectURL,
+ Endpoint: oauth2.Endpoint{
+ AuthURL: meta.AuthURL,
+ TokenURL: meta.TokenURL,
+ },
+ }
+ session := sessions.StartFasthttp(ctx)
+ if session.GetString(meta.AuthHeaderName) != "" {
+ h(ctx)
+ return
+ }
+ state := string(ctx.FormValue(stateParam))
+ if state == "" {
+ id, _ := uuid.NewUUID()
+ session.Set(savedState, id.String())
+ session.Set(redirectPath, string(ctx.RequestURI()))
+ url := conf.AuthCodeURL(id.String(), oauth2.AccessTypeOffline)
+ ctx.Redirect(url, 302)
+ } else {
+ authState := session.GetString(savedState)
+ redirectURL := session.GetString(redirectPath)
+ if state != authState {
+ ctx.Error("invalid state", fasthttp.StatusBadRequest)
+ } else {
+ code := string(ctx.FormValue(codeParam))
+ if code == "" {
+ ctx.Error("code not found", fasthttp.StatusBadRequest)
+ } else {
+ token, err := conf.Exchange(context.Background(), code)
+ if err != nil {
+ ctx.Error(err.Error(), fasthttp.StatusInternalServerError)
+ }
+ session.Set(meta.AuthHeaderName, token.Type()+" "+token.AccessToken)
+ ctx.Request.Header.Add(meta.AuthHeaderName, token.Type()+" "+token.AccessToken)
+ ctx.Redirect(redirectURL, 302)
+ }
+ }
+ }
+ }
+ }, nil
+}
+
+func (m *Middleware) getNativeMetadata(metadata middleware.Metadata) (*oAuth2MiddlewareMetadata, error) {
+ b, err := json.Marshal(metadata.Properties)
+ if err != nil {
+ return nil, err
+ }
+
+ var middlewareMetadata oAuth2MiddlewareMetadata
+ err = json.Unmarshal(b, &middlewareMetadata)
+ if err != nil {
+ return nil, err
+ }
+ return &middlewareMetadata, nil
+}
diff --git a/vendor/github.com/dapr/components-contrib/middleware/metadata.go b/vendor/github.com/dapr/components-contrib/middleware/metadata.go
new file mode 100644
index 00000000000..816a35fcae5
--- /dev/null
+++ b/vendor/github.com/dapr/components-contrib/middleware/metadata.go
@@ -0,0 +1,11 @@
+// ------------------------------------------------------------
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+// ------------------------------------------------------------
+
+package middleware
+
+// Metadata represents a set of middleware specific properties
+type Metadata struct {
+ Properties map[string]string `json:"properties"`
+}
diff --git a/vendor/github.com/dapr/components-contrib/middleware/middleware.go b/vendor/github.com/dapr/components-contrib/middleware/middleware.go
new file mode 100644
index 00000000000..f5eb2aaac00
--- /dev/null
+++ b/vendor/github.com/dapr/components-contrib/middleware/middleware.go
@@ -0,0 +1,15 @@
+// ------------------------------------------------------------
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+// ------------------------------------------------------------
+
+package middleware
+
+import (
+ "github.com/valyala/fasthttp"
+)
+
+// Middleware is the interface for a middleware
+type Middleware interface {
+ GetHandler(metadata Metadata) (func(h fasthttp.RequestHandler) fasthttp.RequestHandler, error)
+}
diff --git a/vendor/github.com/dapr/components-contrib/pubsub/azure/servicebus/servicebus.go b/vendor/github.com/dapr/components-contrib/pubsub/azure/servicebus/servicebus.go
index 637870cdfd1..f417e1d7754 100644
--- a/vendor/github.com/dapr/components-contrib/pubsub/azure/servicebus/servicebus.go
+++ b/vendor/github.com/dapr/components-contrib/pubsub/azure/servicebus/servicebus.go
@@ -12,7 +12,7 @@ import (
"time"
azservicebus "github.com/Azure/azure-service-bus-go"
- log "github.com/Sirupsen/logrus"
+ log "github.com/sirupsen/logrus"
"github.com/dapr/components-contrib/pubsub"
)
diff --git a/vendor/github.com/dapr/components-contrib/pubsub/nats/nats.go b/vendor/github.com/dapr/components-contrib/pubsub/nats/nats.go
index f894365f5f9..fcf12042a8a 100644
--- a/vendor/github.com/dapr/components-contrib/pubsub/nats/nats.go
+++ b/vendor/github.com/dapr/components-contrib/pubsub/nats/nats.go
@@ -9,7 +9,7 @@ import (
"errors"
"fmt"
- log "github.com/Sirupsen/logrus"
+ log "github.com/sirupsen/logrus"
"github.com/dapr/components-contrib/pubsub"
nats "github.com/nats-io/go-nats"
)
diff --git a/vendor/github.com/dapr/components-contrib/pubsub/rabbitmq/rabbitmq.go b/vendor/github.com/dapr/components-contrib/pubsub/rabbitmq/rabbitmq.go
index 7cf60f44540..2dd73e3e59e 100644
--- a/vendor/github.com/dapr/components-contrib/pubsub/rabbitmq/rabbitmq.go
+++ b/vendor/github.com/dapr/components-contrib/pubsub/rabbitmq/rabbitmq.go
@@ -3,7 +3,7 @@ package rabbitmq
import (
"fmt"
- log "github.com/Sirupsen/logrus"
+ log "github.com/sirupsen/logrus"
"github.com/dapr/components-contrib/pubsub"
"github.com/streadway/amqp"
)
@@ -85,7 +85,6 @@ func (r *rabbitMQ) Publish(req *pubsub.PublishRequest) error {
}
func (r *rabbitMQ) Subscribe(req pubsub.SubscribeRequest, handler func(msg *pubsub.NewMessage) error) error {
-
err := r.ensureExchangeDeclared(req.Topic)
if err != nil {
return err
@@ -160,7 +159,6 @@ func (r *rabbitMQ) handleMessage(d amqp.Delivery, topic string, handler func(msg
}
func (r *rabbitMQ) ensureExchangeDeclared(exchange string) error {
-
if _, exists := r.declaredExchanges[exchange]; !exists {
log.Debugf("%s declaring exchange '%s' of kind '%s'", logMessagePrefix, exchange, fanoutExchangeKind)
err := r.channel.ExchangeDeclare(exchange, fanoutExchangeKind, true, false, false, false, nil)
diff --git a/vendor/github.com/dapr/components-contrib/pubsub/redis/redis.go b/vendor/github.com/dapr/components-contrib/pubsub/redis/redis.go
index 17ac8721a60..7cefb19f0ea 100644
--- a/vendor/github.com/dapr/components-contrib/pubsub/redis/redis.go
+++ b/vendor/github.com/dapr/components-contrib/pubsub/redis/redis.go
@@ -12,7 +12,7 @@ import (
"strconv"
"time"
- log "github.com/Sirupsen/logrus"
+ log "github.com/sirupsen/logrus"
"github.com/dapr/components-contrib/pubsub"
"github.com/go-redis/redis"
diff --git a/vendor/github.com/dapr/components-contrib/secretstores/Readme.md b/vendor/github.com/dapr/components-contrib/secretstores/Readme.md
index 41b9bdc4b33..73ec0875fde 100644
--- a/vendor/github.com/dapr/components-contrib/secretstores/Readme.md
+++ b/vendor/github.com/dapr/components-contrib/secretstores/Readme.md
@@ -7,6 +7,7 @@ Currently supported secret stores are:
* Kubernetes
* Azure KeyVault
* AWS Secret manager
+* GCP Cloud KMS
## Implementing a new Secret Store
diff --git a/vendor/github.com/fasthttp-contrib/sessions/.gitignore b/vendor/github.com/fasthttp-contrib/sessions/.gitignore
new file mode 100644
index 00000000000..4f0682f705f
--- /dev/null
+++ b/vendor/github.com/fasthttp-contrib/sessions/.gitignore
@@ -0,0 +1,2 @@
+.project
+.settings
diff --git a/vendor/github.com/fasthttp-contrib/sessions/.travis.yml b/vendor/github.com/fasthttp-contrib/sessions/.travis.yml
new file mode 100644
index 00000000000..2b77402de78
--- /dev/null
+++ b/vendor/github.com/fasthttp-contrib/sessions/.travis.yml
@@ -0,0 +1,5 @@
+language: go
+
+go:
+ - go1.7
+ - tip
diff --git a/vendor/github.com/fasthttp-contrib/sessions/LICENSE b/vendor/github.com/fasthttp-contrib/sessions/LICENSE
new file mode 100644
index 00000000000..2b54a589885
--- /dev/null
+++ b/vendor/github.com/fasthttp-contrib/sessions/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2016 Gerasimos Maropoulos
+
+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/fasthttp-contrib/sessions/README.md b/vendor/github.com/fasthttp-contrib/sessions/README.md
new file mode 100644
index 00000000000..351f47a4ed5
--- /dev/null
+++ b/vendor/github.com/fasthttp-contrib/sessions/README.md
@@ -0,0 +1,339 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Fast, unique & cross-framework http sessions for Go.
+Easy to learn, while providing robust set of features.
+
+Ideally suited for both experienced and novice Developers.
+
+
+
+
+Quick view
+-----------
+
+```go
+import "github.com/fasthttp-contrib/sessions"
+
+sess := sessions.StartFasthttp(*fasthttp.RequestCtx)
+sess.ID() string
+sess.Get(string) interface{}
+sess.GetString(key string) string
+sess.GetInt(key string) int
+sess.GetAll() map[string]interface{}
+sess.VisitAll(cb func(k string, v interface{}))
+sess.Set(string, interface{})
+sess.Delete(string)
+sess.Clear()
+
+```
+
+Installation
+------------
+The only requirement is the [Go Programming Language](https://golang.org/dl), at least v1.7.
+
+```bash
+$ go get -u github.com/fasthttp-contrib/sessions
+```
+
+Features
+------------
+- Focus on simplicity and performance, it's the fastest sessions provider in Go world.
+- Cleans the temp memory when a session is idle, and re-allocates it to the temp memory when it's necessary.
+- The most used sessions are optimized to be in the front of the memory's list.
+- Supports any type of [external database](https://github.com/kataras/go-sessions/tree/master/examples/3_redis_sessiondb).
+- Works with both [net/http](https://golang.org/pkg/net/http/) and [valyala/fasthttp](https://github.com/valyala/fasthttp).
+
+
+Docs
+------------
+
+Take a look at the [./examples](https://github.com/kataras/go-sessions/tree/master/examples).
+
+
+**OUTLINE**
+
+```go
+
+// StartFasthttp starts the session for the particular valyala/fasthttp request
+StartFasthttp(*fasthttp.RequestCtx) Session
+// DestroyFasthttp kills the valyala/fasthttp session and remove the associated cookie
+DestroyFasthttp(*fasthttp.RequestCtx)
+
+// Start starts the session for the particular net/http request
+Start(http.ResponseWriter, *http.Request) Session
+// Destroy kills the net/http session and remove the associated cookie
+Destroy(http.ResponseWriter, *http.Request)
+
+
+// UseDatabase ,optionally, adds a session database to the manager's provider,
+// a session db doesn't have write access
+// see https://github.com/kataras/go-sessions/tree/master/sessiondb
+UseDatabase(Database)
+
+// UpdateConfig updates the configuration field (Config does not receives a pointer, so this is a way to update a pre-defined configuration)
+UpdateConfig(Config)
+```
+
+
+Usage FASTHTTP
+------------
+
+`StartFasthttp` returns again `Session`, **Session outline**
+
+```go
+type Session interface {
+ ID() string
+ Get(string) interface{}
+ GetString(key string) string
+ GetInt(key string) int
+ GetAll() map[string]interface{}
+ VisitAll(cb func(k string, v interface{}))
+ Set(string, interface{})
+ Delete(string)
+ Clear()
+}
+```
+
+```go
+package main
+
+import (
+ "fmt"
+ "github.com/kataras/go-sessions"
+ "github.com/valyala/fasthttp"
+)
+
+func main() {
+
+ // set some values to the session
+ setHandler := func(reqCtx *fasthttp.RequestCtx) {
+ values := map[string]interface{}{
+ "Name": "go-sessions",
+ "Days": "1",
+ "Secret": "dsads£2132215£%%Ssdsa",
+ }
+
+ sess := sessions.StartFasthttp(reqCtx) // init the session
+ // sessions.StartFasthttp returns:
+ // type Session interface {
+ // ID() string
+ // Get(string) interface{}
+ // GetString(key string) string
+ // GetInt(key string) int
+ // GetAll() map[string]interface{}
+ // VisitAll(cb func(k string, v interface{}))
+ // Set(string, interface{})
+ // Delete(string)
+ // Clear()
+ //}
+
+ for k, v := range values {
+ sess.Set(k, v) // fill session, set each of the key-value pair
+ }
+ reqCtx.WriteString("Session saved, go to /get to view the results")
+ }
+
+ // get the values from the session
+ getHandler := func(reqCtx *fasthttp.RequestCtx) {
+ sess := sessions.StartFasthttp(reqCtx) // init the session
+ sessValues := sess.GetAll() // get all values from this session
+
+ reqCtx.WriteString(fmt.Sprintf("%#v", sessValues))
+ }
+
+ // clear all values from the session
+ clearHandler := func(reqCtx *fasthttp.RequestCtx) {
+ sess := sessions.StartFasthttp(reqCtx)
+ sess.Clear()
+ }
+
+ // destroys the session, clears the values and removes the server-side entry and client-side sessionid cookie
+ destroyHandler := func(reqCtx *fasthttp.RequestCtx) {
+ sessions.DestroyFasthttp(reqCtx)
+ }
+
+ fmt.Println("Open a browser tab and navigate to the localhost:8080/set")
+ fasthttp.ListenAndServe(":8080", func(reqCtx *fasthttp.RequestCtx) {
+ path := string(reqCtx.Path())
+
+ if path == "/set" {
+ setHandler(reqCtx)
+ } else if path == "/get" {
+ getHandler(reqCtx)
+ } else if path == "/clear" {
+ clearHandler(reqCtx)
+ } else if path == "/destroy" {
+ destroyHandler(reqCtx)
+ } else {
+ reqCtx.WriteString("Please navigate to /set or /get or /clear or /destroy")
+ }
+ })
+}
+
+
+```
+
+Usage NET/HTTP
+------------
+
+
+`Start` returns a `Session`, **Session outline**
+
+```go
+type Session interface {
+ ID() string
+ Get(string) interface{}
+ GetString(key string) string
+ GetInt(key string) int
+ GetAll() map[string]interface{}
+ VisitAll(cb func(k string, v interface{}))
+ Set(string, interface{})
+ Delete(string)
+ Clear()
+}
+```
+
+```go
+package main
+
+import (
+ "fmt"
+ "github.com/kataras/go-sessions"
+ "net/http"
+)
+
+func main() {
+
+ // set some values to the session
+ setHandler := http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) {
+ values := map[string]interface{}{
+ "Name": "go-sessions",
+ "Days": "1",
+ "Secret": "dsads£2132215£%%Ssdsa",
+ }
+
+ sess := sessions.Start(res, req) // init the session
+ // sessions.Start returns:
+ // type Session interface {
+ // ID() string
+ // Get(string) interface{}
+ // GetString(key string) string
+ // GetInt(key string) int
+ // GetAll() map[string]interface{}
+ // VisitAll(cb func(k string, v interface{}))
+ // Set(string, interface{})
+ // Delete(string)
+ // Clear()
+ //}
+
+ for k, v := range values {
+ sess.Set(k, v) // fill session, set each of the key-value pair
+ }
+ res.Write([]byte("Session saved, go to /get to view the results"))
+ })
+ http.Handle("/set/", setHandler)
+
+ // get the values from the session
+ getHandler := http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) {
+ sess := sessions.Start(res, req) // init the session
+ sessValues := sess.GetAll() // get all values from this session
+
+ res.Write([]byte(fmt.Sprintf("%#v", sessValues)))
+ })
+ http.Handle("/get/", getHandler)
+
+ // clear all values from the session
+ clearHandler := http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) {
+ sess := sessions.Start(res, req)
+ sess.Clear()
+ })
+ http.Handle("/clear/", clearHandler)
+
+ // destroys the session, clears the values and removes the server-side entry and client-side sessionid cookie
+ destroyHandler := http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) {
+ sessions.Destroy(res, req)
+ })
+ http.Handle("/destroy/", destroyHandler)
+
+ fmt.Println("Open a browser tab and navigate to the localhost:8080/set/")
+ http.ListenAndServe(":8080", nil)
+}
+
+```
+
+
+
+
+FAQ
+------------
+
+If you'd like to discuss this package, or ask questions about it, feel free to
+
+ * Explore [these questions](https://github.com/kataras/go-sessions/issues?go-sessions=label%3Aquestion).
+ * Post an issue or idea [here](https://github.com/kataras/go-sessions/issues).
+ * Navigate to the [Chat][Chat].
+
+
+
+Versioning
+------------
+
+Current: **v0.0.3**
+
+Read more about Semantic Versioning 2.0.0
+
+ - http://semver.org/
+ - https://en.wikipedia.org/wiki/Software_versioning
+ - https://wiki.debian.org/UpstreamGuide#Releases_and_Versions
+
+
+
+People
+------------
+The author of go-sessions is [@kataras](https://github.com/kataras).
+
+
+Contributing
+------------
+If you are interested in contributing to the go-sessions project, please make a PR.
+
+License
+------------
+
+This project is licensed under the MIT License.
+
+License can be found [here](LICENSE).
+
+[Travis Widget]: https://img.shields.io/travis/kataras/go-sessions.svg?style=flat-square
+[Travis]: http://travis-ci.org/kataras/go-sessions
+[License Widget]: https://img.shields.io/badge/license-MIT%20%20License%20-E91E63.svg?style=flat-square
+[License]: https://github.com/kataras/go-sessions/blob/master/LICENSE
+[Release Widget]: https://img.shields.io/badge/release-v0.0.3-blue.svg?style=flat-square
+[Release]: https://github.com/kataras/go-sessions/releases
+[Chat Widget]: https://img.shields.io/badge/community-chat-00BCD4.svg?style=flat-square
+[Chat]: https://kataras.rocket.chat/channel/go-sessions
+[ChatMain]: https://kataras.rocket.chat/channel/go-sessions
+[ChatAlternative]: https://gitter.im/kataras/go-sessions
+[Report Widget]: https://img.shields.io/badge/report%20card-A%2B-F44336.svg?style=flat-square
+[Report]: http://goreportcard.com/report/kataras/go-sessions
+[Documentation Widget]: https://img.shields.io/badge/docs-reference-5272B4.svg?style=flat-square
+[Documentation]: https://godoc.org/github.com/kataras/go-sessions
+[Language Widget]: https://img.shields.io/badge/powered_by-Go-3362c2.svg?style=flat-square
+[Language]: http://golang.org
+[Platform Widget]: https://img.shields.io/badge/platform-Any--OS-yellow.svg?style=flat-square
diff --git a/vendor/github.com/fasthttp-contrib/sessions/config.go b/vendor/github.com/fasthttp-contrib/sessions/config.go
new file mode 100644
index 00000000000..74f2e5eadea
--- /dev/null
+++ b/vendor/github.com/fasthttp-contrib/sessions/config.go
@@ -0,0 +1,78 @@
+package sessions
+
+import (
+ "encoding/base64"
+ "time"
+)
+
+const (
+ // DefaultCookieName the secret cookie's name for sessions
+ DefaultCookieName = "gosessionsid"
+ // DefaultGcDuration is the default Session Manager's GCDuration , which is 2 hours
+ DefaultGcDuration = time.Duration(2) * time.Hour
+ // DefaultCookieExpires is the default Session Manager's Cookie expire , which is 2 hours
+ DefaultCookieExpires = DefaultGcDuration
+ // DefaultCookieLength is the default Session Manager's CookieLength, which is 32
+ DefaultCookieLength = 32
+)
+
+// Config the configuration for sessions
+// has 6 fields
+// first is the cookieName, the session's name (string) ["mysessionsecretcookieid"]
+// second enable if you want to decode the cookie's key also
+// third is the time which the client's cookie expires
+// forth is the cookie length (sessionid) int, defaults to 32, do not change if you don't have any reason to do
+// fifth is the gcDuration (time.Duration) when this time passes it removes the unused sessions from the memory until the user come back
+// sixth is the DisableSubdomainPersistence which you can set it to true in order dissallow your q subdomains to have access to the session cook
+//
+type Config struct {
+ // Cookie string, the session's client cookie name, for example: "qsessionid"
+ Cookie string
+ // DecodeCookie set it to true to decode the cookie key with base64 URLEncoding
+ // Defaults to false
+ DecodeCookie bool
+
+ // Expires the duration of which the cookie must expires (created_time.Add(Expires)).
+ // If you want to delete the cookie when the browser closes, set it to -1 but in this case, the server side's session duration is up to GcDuration
+ //
+ // Default infinitive/unlimited life duration(0)
+ Expires time.Duration
+
+ // CookieLength the length of the sessionid's cookie's value, let it to 0 if you don't want to change it
+ // Defaults to 32
+ CookieLength int
+
+ // GcDuration every how much duration(GcDuration) the memory should be clear for unused cookies (GcDuration)
+ // for example: time.Duration(2)*time.Hour. it will check every 2 hours if cookie hasn't be used for 2 hours,
+ // deletes it from backend memory until the user comes back, then the session continue to work as it was
+ //
+ // Default 2 hours
+ GcDuration time.Duration
+
+ // DisableSubdomainPersistence set it to true in order dissallow your q subdomains to have access to the session cookie
+ // defaults to false
+ DisableSubdomainPersistence bool
+}
+
+// Validate corrects missing fields configuration fields and returns the right configuration
+func (c Config) Validate() Config {
+ if c.Cookie == "" {
+ c.Cookie = DefaultCookieName
+ }
+ if c.GcDuration <= 0 {
+ c.GcDuration = DefaultGcDuration
+ }
+ if c.Expires <= 0 {
+ c.Expires = DefaultCookieExpires
+ }
+ if c.DecodeCookie {
+ c.Cookie = base64.URLEncoding.EncodeToString([]byte(c.Cookie)) // change the cookie's name/key to a more safe(?)
+ // get the real value for your tests by:
+ //sessIdKey := url.QueryEscape(base64.URLEncoding.EncodeToString([]byte(Sessions.Cookie)))
+ }
+
+ if c.CookieLength <= 0 {
+ c.CookieLength = DefaultCookieLength
+ }
+ return c
+}
diff --git a/vendor/github.com/fasthttp-contrib/sessions/cookie.go b/vendor/github.com/fasthttp-contrib/sessions/cookie.go
new file mode 100644
index 00000000000..69d616ce68a
--- /dev/null
+++ b/vendor/github.com/fasthttp-contrib/sessions/cookie.go
@@ -0,0 +1,233 @@
+package sessions
+
+import (
+ "bytes"
+ "encoding/base64"
+ "encoding/gob"
+ "github.com/valyala/fasthttp"
+ "math/rand"
+ "net/http"
+ "strconv"
+ "strings"
+ "sync"
+ "time"
+)
+
+var (
+ // CookieExpireDelete may be set on Cookie.Expire for expiring the given cookie.
+ CookieExpireDelete = time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)
+
+ // CookieExpireUnlimited indicates that the cookie doesn't expire.
+ CookieExpireUnlimited = time.Now().AddDate(23, 0, 0)
+)
+
+// GetCookie returns cookie's value by it's name
+// returns empty string if nothing was found
+func GetCookie(name string, req *http.Request) string {
+ c, err := req.Cookie(name)
+ if err != nil {
+ return ""
+ }
+ return c.Value
+}
+
+// AddCookie adds a cookie
+func AddCookie(cookie *http.Cookie, res http.ResponseWriter) {
+ if v := cookie.String(); v != "" {
+ res.Header().Add("Set-Cookie", v)
+ }
+}
+
+// RemoveCookie deletes a cookie by it's name/key
+func RemoveCookie(name string, res http.ResponseWriter, req *http.Request) {
+ c, err := req.Cookie(name)
+ if err != nil {
+ return
+ }
+
+ c.Expires = CookieExpireDelete
+ c.MaxAge = -1
+ c.Value = ""
+ c.Path = "/"
+ AddCookie(c, res)
+}
+
+var cookiePool sync.Pool
+
+// AcquireCookie returns an empty Cookie object from the pool.
+//
+// The returned object may be returned back to the pool with ReleaseCookie.
+// This allows reducing GC load.
+func AcquireCookie() *http.Cookie {
+ v := cookiePool.Get()
+ if v == nil {
+ return &http.Cookie{}
+ }
+
+ cookie := v.(*http.Cookie)
+ cookie.HttpOnly = true
+ cookie.Path = ""
+ cookie.HttpOnly = false
+ cookie.Name = ""
+ cookie.Raw = ""
+ cookie.Value = ""
+ cookie.Domain = ""
+ cookie.MaxAge = -1
+ cookie.Expires = CookieExpireUnlimited
+ return cookie
+}
+
+// ReleaseCookie returns the Cookie object acquired with AcquireCookie back
+// to the pool.
+//
+// Do not access released Cookie object, otherwise data races may occur.
+func ReleaseCookie(cookie *http.Cookie) {
+ cookiePool.Put(cookie)
+}
+
+// FastHTTP
+
+// GetFasthttpCookie returns cookie's value by it's name
+// returns empty string if nothing was found
+func GetFasthttpCookie(name string, reqCtx *fasthttp.RequestCtx) (val string) {
+ bcookie := reqCtx.Request.Header.Cookie(name)
+ if bcookie != nil {
+ val = string(bcookie)
+ }
+ return
+}
+
+// AddFasthttpCookie adds a cookie to the client
+func AddFasthttpCookie(c *fasthttp.Cookie, reqCtx *fasthttp.RequestCtx) {
+ reqCtx.Response.Header.SetCookie(c)
+}
+
+// RemoveFasthttpCookie deletes a cookie by it's name/key
+func RemoveFasthttpCookie(name string, reqCtx *fasthttp.RequestCtx) {
+ reqCtx.Response.Header.DelCookie(name)
+
+ cookie := fasthttp.AcquireCookie()
+ //cookie := &fasthttp.Cookie{}
+ cookie.SetKey(name)
+ cookie.SetValue("")
+ cookie.SetPath("/")
+ cookie.SetHTTPOnly(true)
+ exp := time.Now().Add(-time.Duration(1) * time.Minute) //RFC says 1 second, but let's do it 1 minute to make sure is working...
+ cookie.SetExpire(exp)
+ AddFasthttpCookie(cookie, reqCtx)
+ fasthttp.ReleaseCookie(cookie)
+ // delete request's cookie also, which is temporarly available
+ reqCtx.Request.Header.DelCookie(name)
+}
+
+// IsValidCookieDomain returns true if the receiver is a valid domain to set
+// valid means that is recognised as 'domain' by the browser, so it(the cookie) can be shared with subdomains also
+func IsValidCookieDomain(domain string) bool {
+ if domain == "0.0.0.0" || domain == "127.0.0.1" {
+ // for these type of hosts, we can't allow subdomains persistance,
+ // the web browser doesn't understand the mysubdomain.0.0.0.0 and mysubdomain.127.0.0.1 mysubdomain.32.196.56.181. as scorrectly ubdomains because of the many dots
+ // so don't set a cookie domain here, let browser handle this
+ return false
+ }
+
+ dotLen := strings.Count(domain, ".")
+ if dotLen == 0 {
+ // we don't have a domain, maybe something like 'localhost', browser doesn't see the .localhost as wildcard subdomain+domain
+ return false
+ }
+ if dotLen >= 3 {
+ if lastDotIdx := strings.LastIndexByte(domain, '.'); lastDotIdx != -1 {
+ // chekc the last part, if it's number then propably it's ip
+ if len(domain) > lastDotIdx+1 {
+ _, err := strconv.Atoi(domain[lastDotIdx+1:])
+ if err == nil {
+ return false
+ }
+ }
+ }
+ }
+
+ return true
+}
+
+func encodeCookieValue(value string) string {
+ return base64.URLEncoding.EncodeToString([]byte(value))
+}
+
+func decodeCookieValue(value string) (string, error) {
+ v, err := base64.URLEncoding.DecodeString(value)
+ if err != nil {
+ return "", err
+ }
+ return string(v), nil
+}
+
+// -------------------------------------------------------------------------------------
+// -------------------------------------------------------------------------------------
+// ----------------------------------Strings & Serialization----------------------------
+// -------------------------------------------------------------------------------------
+// -------------------------------------------------------------------------------------
+
+const (
+ letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ letterIdxBits = 6 // 6 bits to represent a letter index
+ letterIdxMask = 1<= 0; {
+ if remain == 0 {
+ cache, remain = src.Int63(), letterIdxMax
+ }
+ if idx := int(cache & letterIdxMask); idx < len(letterBytes) {
+ b[i] = letterBytes[idx]
+ i--
+ }
+ cache >>= letterIdxBits
+ remain--
+ }
+
+ return b
+}
+
+// RandomString accepts a number(10 for example) and returns a random string using simple but fairly safe random algorithm
+func RandomString(n int) string {
+ return string(Random(n))
+}
+
+// Serialize serialize any type to gob bytes and after returns its the base64 encoded string
+func Serialize(m interface{}) (string, error) {
+ b := bytes.Buffer{}
+ encoder := gob.NewEncoder(&b)
+ err := encoder.Encode(m)
+ if err != nil {
+ return "", err
+ }
+ return base64.StdEncoding.EncodeToString(b.Bytes()), nil
+}
+
+// Deserialize accepts an encoded string and a data struct which will be filled with the desierialized string
+// using gob decoder
+func Deserialize(str string, m interface{}) error {
+ by, err := base64.StdEncoding.DecodeString(str)
+ if err != nil {
+ return err
+ }
+ b := bytes.Buffer{}
+ b.Write(by)
+ d := gob.NewDecoder(&b)
+ // d := gob.NewDecoder(bytes.NewBufferString(str))
+ err = d.Decode(&m)
+ if err != nil {
+ return err
+ }
+ return nil
+}
diff --git a/vendor/github.com/fasthttp-contrib/sessions/database.go b/vendor/github.com/fasthttp-contrib/sessions/database.go
new file mode 100644
index 00000000000..1db77a85ed9
--- /dev/null
+++ b/vendor/github.com/fasthttp-contrib/sessions/database.go
@@ -0,0 +1,12 @@
+package sessions
+
+// Database is the interface which all session databases should implement
+// By design it doesn't support any type of cookie session like other frameworks, I want to protect you, believe me, no context access (although we could)
+// The scope of the database is to session somewhere the sessions in order to keep them after restarting the server, nothing more.
+// the values are sessiond by the underline session, the check for new sessions, or 'this session value should added' are made automatically by q, you are able just to set the values to your backend database with Load function.
+// session database doesn't have any write or read access to the session, the loading of the initial data is done by the Load(string) map[string]interfface{} function
+// synchronization are made automatically, you can register more than one session database but the first non-empty Load return data will be used as the session values.
+type Database interface {
+ Load(string) map[string]interface{}
+ Update(string, map[string]interface{})
+}
diff --git a/vendor/github.com/fasthttp-contrib/sessions/logo_900_273_bg_white.png b/vendor/github.com/fasthttp-contrib/sessions/logo_900_273_bg_white.png
new file mode 100644
index 00000000000..6fee984ab50
Binary files /dev/null and b/vendor/github.com/fasthttp-contrib/sessions/logo_900_273_bg_white.png differ
diff --git a/vendor/github.com/fasthttp-contrib/sessions/provider.go b/vendor/github.com/fasthttp-contrib/sessions/provider.go
new file mode 100644
index 00000000000..d05646e1ec4
--- /dev/null
+++ b/vendor/github.com/fasthttp-contrib/sessions/provider.go
@@ -0,0 +1,143 @@
+package sessions
+
+import (
+ "container/list"
+ "sync"
+ "time"
+)
+
+type (
+ // Provider contains the sessions memory store and any external databases
+ Provider struct {
+ mu sync.Mutex
+ sessions map[string]*list.Element // underline TEMPORARY memory store used to give advantage on sessions used more times than others
+ list *list.List // for GC
+ databases []Database
+ Expires time.Duration
+ }
+)
+
+// NewProvider returns a new sessions provider
+func NewProvider(expires time.Duration) *Provider {
+ return &Provider{list: list.New(), sessions: make(map[string]*list.Element, 0), databases: make([]Database, 0), Expires: expires}
+}
+
+// RegisterDatabase adds a session database
+// a session db doesn't have write access
+func (p *Provider) RegisterDatabase(db Database) {
+ p.mu.Lock() // for any case
+ p.databases = append(p.databases, db)
+ p.mu.Unlock()
+}
+
+// NewSession returns a new session from sessionid
+func (p *Provider) NewSession(sid string) Session {
+
+ sess := &session{
+ sid: sid,
+ provider: p,
+ lastAccessedTime: time.Now(),
+ values: p.loadSessionValues(sid),
+ }
+ if p.Expires > 0 { // if not unlimited life duration and no -1 (cookie remove action is based on browser's session)
+ time.AfterFunc(p.Expires, func() {
+ // the destroy makes the check if this session is exists then or not,
+ // this is used to destroy the session from the server-side also
+ // it's good to have here for security reasons, I didn't add it on the gc function to separate its action
+ p.Destroy(sid)
+
+ })
+ }
+
+ return sess
+
+}
+
+func (p *Provider) loadSessionValues(sid string) map[string]interface{} {
+
+ for i, n := 0, len(p.databases); i < n; i++ {
+ if dbValues := p.databases[i].Load(sid); dbValues != nil && len(dbValues) > 0 {
+ return dbValues // return the first non-empty from the registered stores.
+ }
+ }
+ values := make(map[string]interface{})
+ return values
+}
+
+func (p *Provider) updateDatabases(sid string, newValues map[string]interface{}) {
+ for i, n := 0, len(p.databases); i < n; i++ {
+ p.databases[i].Update(sid, newValues)
+ }
+}
+
+// Init creates the session and returns it
+func (p *Provider) Init(sid string) Session {
+ newSession := p.NewSession(sid)
+ elem := p.list.PushBack(newSession)
+ p.mu.Lock()
+ p.sessions[sid] = elem
+ p.mu.Unlock()
+ return newSession
+}
+
+// Read returns the store which sid parameter is belongs
+func (p *Provider) Read(sid string) Session {
+ p.mu.Lock()
+ if elem, found := p.sessions[sid]; found {
+ p.mu.Unlock() // yes defer is slow
+ elem.Value.(*session).lastAccessedTime = time.Now()
+ return elem.Value.(*session)
+ }
+ p.mu.Unlock()
+ // if not found create new
+ sess := p.Init(sid)
+ return sess
+}
+
+// Destroy destroys the session, removes all sessions values, the session itself and updates the registered session databases, this called from sessionManager which removes the client's cookie also.
+func (p *Provider) Destroy(sid string) {
+ p.mu.Lock()
+ if elem, found := p.sessions[sid]; found {
+ sess := elem.Value.(*session)
+ sess.values = nil
+ p.updateDatabases(sid, nil)
+ delete(p.sessions, sid)
+ p.list.Remove(elem)
+ }
+ p.mu.Unlock()
+}
+
+// Update updates the lastAccessedTime, and moves the memory place element to the front
+// always returns a nil error, for now
+func (p *Provider) update(sid string) {
+ p.mu.Lock()
+ if elem, found := p.sessions[sid]; found {
+ sess := elem.Value.(*session)
+ sess.lastAccessedTime = time.Now()
+ p.list.MoveToFront(elem)
+ p.updateDatabases(sid, sess.values)
+ }
+ p.mu.Unlock()
+}
+
+// GC clears the memory
+func (p *Provider) GC(duration time.Duration) {
+ p.mu.Lock()
+ defer p.mu.Unlock()
+
+ for {
+ elem := p.list.Back()
+ if elem == nil {
+ break
+ }
+
+ // if the time has passed. session was expired, then delete the session and its memory place
+ // we are not destroy the session completely for the case this is re-used after
+ sess := elem.Value.(*session)
+ if time.Now().After(sess.lastAccessedTime.Add(duration)) {
+ p.list.Remove(elem)
+ } else {
+ break
+ }
+ }
+}
diff --git a/vendor/github.com/fasthttp-contrib/sessions/session.go b/vendor/github.com/fasthttp-contrib/sessions/session.go
new file mode 100644
index 00000000000..62ab4c58a24
--- /dev/null
+++ b/vendor/github.com/fasthttp-contrib/sessions/session.go
@@ -0,0 +1,110 @@
+package sessions
+
+import (
+ "sync"
+ "time"
+)
+
+type (
+ // Session is session's session interface, think it like a local store of each session's values
+ // implemented by the internal session iteral, normally the end-user will never use this interface.
+ // gettable by the provider -> sessions -> your app
+ Session interface {
+ ID() string
+ Get(string) interface{}
+ GetString(key string) string
+ GetInt(key string) int
+ GetAll() map[string]interface{}
+ VisitAll(cb func(k string, v interface{}))
+ Set(string, interface{})
+ Delete(string)
+ Clear()
+ }
+ // session is an 'object' which wraps the session provider with its session databases, only frontend user has access to this session object.
+ // implements the Session interface
+ session struct {
+ sid string
+ values map[string]interface{} // here are the real values
+ mu sync.Mutex
+ lastAccessedTime time.Time
+ createdAt time.Time
+ provider *Provider
+ }
+)
+
+// ID returns the session's id
+func (s *session) ID() string {
+ return s.sid
+}
+
+// Get returns the value of an entry by its key
+func (s *session) Get(key string) interface{} {
+ s.provider.update(s.sid)
+ if value, found := s.values[key]; found {
+ return value
+ }
+ return nil
+}
+
+// GetString same as Get but returns as string, if nil then returns an empty string
+func (s *session) GetString(key string) string {
+ if value := s.Get(key); value != nil {
+ if v, ok := value.(string); ok {
+ return v
+ }
+
+ }
+
+ return ""
+}
+
+// GetInt same as Get but returns as int, if nil then returns -1
+func (s *session) GetInt(key string) int {
+ if value := s.Get(key); value != nil {
+ if v, ok := value.(int); ok {
+ return v
+ }
+ }
+
+ return -1
+}
+
+// GetAll returns all session's values
+func (s *session) GetAll() map[string]interface{} {
+ return s.values
+}
+
+// VisitAll loop each one entry and calls the callback function func(key,value)
+func (s *session) VisitAll(cb func(k string, v interface{})) {
+ for key := range s.values {
+ cb(key, s.values[key])
+ }
+}
+
+// Set fills the session with an entry, it receives a key and a value
+// returns an error, which is always nil
+func (s *session) Set(key string, value interface{}) {
+ s.mu.Lock()
+ s.values[key] = value
+ s.mu.Unlock()
+ s.provider.update(s.sid)
+}
+
+// Delete removes an entry by its key
+// returns an error, which is always nil
+func (s *session) Delete(key string) {
+ s.mu.Lock()
+ delete(s.values, key)
+ s.mu.Unlock()
+ s.provider.update(s.sid)
+}
+
+// Clear removes all entries
+func (s *session) Clear() {
+ s.mu.Lock()
+ for key := range s.values {
+ delete(s.values, key)
+ }
+ s.mu.Unlock()
+ s.provider.update(s.sid)
+}
diff --git a/vendor/github.com/fasthttp-contrib/sessions/sessions.go b/vendor/github.com/fasthttp-contrib/sessions/sessions.go
new file mode 100644
index 00000000000..a59cfced61a
--- /dev/null
+++ b/vendor/github.com/fasthttp-contrib/sessions/sessions.go
@@ -0,0 +1,285 @@
+// Package sessions provides sessions support for net/http
+// unique with auto-GC, register unlimited number of databases to Load and Update/Save the sessions in external server or to an external (no/or/and sql) database
+// Usage net/http:
+// // init a new sessions manager( if you use only one web framework inside your app then you can use the package-level functions like: sessions.Start/sessions.Destroy)
+// manager := sessions.New(sessions.Config{})
+// // start a session for a particular client
+// manager.Start(http.ResponseWriter, *http.Request)
+//
+// // destroy a session from the server and client,
+// // don't call it on each handler, only on the handler you want the client to 'logout' or something like this:
+// manager.Destroy(http.ResponseWriter, *http.Request)
+//
+//
+// Usage valyala/fasthttp:
+// // init a new sessions manager( if you use only one web framework inside your app then you can use the package-level functions like: sessions.Start/sessions.Destroy)
+// manager := sessions.New(sessions.Config{})
+// // start a session for a particular client
+// manager.StartFasthttp(*fasthttp.RequestCtx)
+//
+// // destroy a session from the server and client,
+// // don't call it on each handler, only on the handler you want the client to 'logout' or something like this:
+// manager.DestroyFasthttp(*fasthttp.Request)
+//
+// Note that, now, you can use both fasthttp and net/http within the same sessions manager(.New) instance!
+// So now, you can share sessions between a net/http app and valyala/fasthttp app
+package sessions
+
+import (
+ "encoding/base64"
+ "github.com/valyala/fasthttp"
+ "net/http"
+ "strings"
+ "time"
+)
+
+const (
+ // Version current version number
+ Version = "0.0.3"
+)
+
+type (
+ // Sessions is the start point of this package
+ // contains all the registered sessions and manages them
+ Sessions interface {
+ // UpdateConfig updates the configuration field (Config does not receives a pointer, so this is a way to update a pre-defined configuration)
+ UpdateConfig(Config)
+ // UseDatabase ,optionally, adds a session database to the manager's provider,
+ // a session db doesn't have write access
+ // see https://github.com/kataras/go-sessions/tree/master/sessiondb
+ UseDatabase(Database)
+ // Start starts the session for the particular net/http request
+ Start(http.ResponseWriter, *http.Request) Session
+ // Destroy kills the net/http session and remove the associated cookie
+ Destroy(http.ResponseWriter, *http.Request)
+ // Start starts the session for the particular valyala/fasthttp request
+ StartFasthttp(*fasthttp.RequestCtx) Session
+ // Destroy kills the valyala/fasthttp session and remove the associated cookie
+ DestroyFasthttp(*fasthttp.RequestCtx)
+ }
+ // sessions contains the cookie's name, the provider and a duration for GC and cookie life expire
+ sessions struct {
+ config Config
+ provider *Provider
+ }
+)
+
+// New creates & returns a new Sessions(manager) and start its GC
+func New(c Config) Sessions {
+ c = c.Validate()
+ // init and start the sess manager
+ sess := &sessions{config: c, provider: NewProvider(c.Expires)}
+ //run the GC here
+ go sess.gc()
+ return sess
+}
+
+var defaultSessions = New(Config{
+ Cookie: DefaultCookieName,
+ DecodeCookie: false,
+ Expires: DefaultCookieExpires,
+ CookieLength: DefaultCookieLength,
+ GcDuration: DefaultGcDuration,
+ DisableSubdomainPersistence: false,
+})
+
+// UpdateConfig updates the sessions configuration
+func UpdateConfig(c Config) {
+ defaultSessions.UpdateConfig(c)
+}
+
+// UpdateConfig updates the sessions configuration
+func (s *sessions) UpdateConfig(c Config) {
+ s.config = c.Validate()
+}
+
+// UseDatabase adds a session database to the manager's provider,
+// a session db doesn't have write access
+func UseDatabase(db Database) {
+ defaultSessions.UseDatabase(db)
+}
+
+// UseDatabase adds a session database to the manager's provider,
+// a session db doesn't have write access
+func (s *sessions) UseDatabase(db Database) {
+ s.provider.Expires = s.config.Expires // updae the expires confiuration field for any case
+ s.provider.RegisterDatabase(db)
+}
+
+// Start starts the session for the particular net/http request
+func Start(res http.ResponseWriter, req *http.Request) Session {
+ return defaultSessions.Start(res, req)
+}
+
+// Start starts the session for the particular net/http request
+func (s *sessions) Start(res http.ResponseWriter, req *http.Request) Session {
+ var sess Session
+
+ cookieValue := GetCookie(s.config.Cookie, req)
+
+ if cookieValue == "" { // cookie doesn't exists, let's generate a session and add set a cookie
+ sid := GenerateSessionID(s.config.CookieLength)
+ sess = s.provider.Init(sid)
+ //cookie := &http.Cookie{}
+ cookie := AcquireCookie()
+ // The RFC makes no mention of encoding url value, so here I think to encode both sessionid key and the value using the safe(to put and to use as cookie) url-encoding
+ cookie.Name = s.config.Cookie
+ cookie.Value = sid
+ cookie.Path = "/"
+ if !s.config.DisableSubdomainPersistence {
+
+ requestDomain := req.Host
+ if portIdx := strings.IndexByte(requestDomain, ':'); portIdx > 0 {
+ requestDomain = requestDomain[0:portIdx]
+ }
+ if IsValidCookieDomain(requestDomain) {
+
+ // RFC2109, we allow level 1 subdomains, but no further
+ // if we have localhost.com , we want the localhost.cos.
+ // so if we have something like: mysubdomain.localhost.com we want the localhost here
+ // if we have mysubsubdomain.mysubdomain.localhost.com we want the .mysubdomain.localhost.com here
+ // slow things here, especially the 'replace' but this is a good and understable( I hope) way to get the be able to set cookies from subdomains & domain with 1-level limit
+ if dotIdx := strings.LastIndexByte(requestDomain, '.'); dotIdx > 0 {
+ // is mysubdomain.localhost.com || mysubsubdomain.mysubdomain.localhost.com
+ s := requestDomain[0:dotIdx] // set mysubdomain.localhost || mysubsubdomain.mysubdomain.localhost
+ if secondDotIdx := strings.LastIndexByte(s, '.'); secondDotIdx > 0 {
+ //is mysubdomain.localhost || mysubsubdomain.mysubdomain.localhost
+ s = s[secondDotIdx+1:] // set to localhost || mysubdomain.localhost
+ }
+ // replace the s with the requestDomain before the domain's siffux
+ subdomainSuff := strings.LastIndexByte(requestDomain, '.')
+ if subdomainSuff > len(s) { // if it is actual exists as subdomain suffix
+ requestDomain = strings.Replace(requestDomain, requestDomain[0:subdomainSuff], s, 1) // set to localhost.com || mysubdomain.localhost.com
+ }
+ }
+ // finally set the .localhost.com (for(1-level) || .mysubdomain.localhost.com (for 2-level subdomain allow)
+ cookie.Domain = "." + requestDomain // . to allow persistance
+ }
+
+ }
+ cookie.HttpOnly = true
+ if s.config.Expires == 0 {
+ // unlimited life
+ cookie.Expires = CookieExpireUnlimited
+ } else if s.config.Expires > 0 {
+ cookie.Expires = time.Now().Add(s.config.Expires)
+ } // if it's -1 then the cookie is deleted when the browser closes
+
+ AddCookie(cookie, res)
+ ReleaseCookie(cookie)
+ } else {
+ sess = s.provider.Read(cookieValue)
+ }
+ return sess
+}
+
+// Destroy kills the net/http session and remove the associated cookie
+func Destroy(res http.ResponseWriter, req *http.Request) {
+ defaultSessions.Destroy(res, req)
+}
+
+// Destroy kills the net/http session and remove the associated cookie
+func (s *sessions) Destroy(res http.ResponseWriter, req *http.Request) {
+ cookieValue := GetCookie(s.config.Cookie, req)
+ if cookieValue == "" { // nothing to destroy
+ return
+ }
+ RemoveCookie(s.config.Cookie, res, req)
+ s.provider.Destroy(cookieValue)
+}
+
+// StartFasthttp starts the session for the particular valyala/fasthttp request
+func StartFasthttp(reqCtx *fasthttp.RequestCtx) Session {
+ return defaultSessions.StartFasthttp(reqCtx)
+}
+
+// Start starts the session for the particular valyala/fasthttp request
+func (s *sessions) StartFasthttp(reqCtx *fasthttp.RequestCtx) Session {
+ var sess Session
+
+ cookieValue := GetFasthttpCookie(s.config.Cookie, reqCtx)
+
+ if cookieValue == "" { // cookie doesn't exists, let's generate a session and add set a cookie
+ sid := GenerateSessionID(s.config.CookieLength)
+ sess = s.provider.Init(sid)
+ cookie := fasthttp.AcquireCookie()
+ //cookie := &fasthttp.Cookie{}
+ // The RFC makes no mention of encoding url value, so here I think to encode both sessionid key and the value using the safe(to put and to use as cookie) url-encoding
+ cookie.SetKey(s.config.Cookie)
+ cookie.SetValue(sid)
+ cookie.SetPath("/")
+ if !s.config.DisableSubdomainPersistence {
+ requestDomain := string(reqCtx.Host())
+ if portIdx := strings.IndexByte(requestDomain, ':'); portIdx > 0 {
+ requestDomain = requestDomain[0:portIdx]
+ }
+ if IsValidCookieDomain(requestDomain) {
+
+ // RFC2109, we allow level 1 subdomains, but no further
+ // if we have localhost.com , we want the localhost.cos.
+ // so if we have something like: mysubdomain.localhost.com we want the localhost here
+ // if we have mysubsubdomain.mysubdomain.localhost.com we want the .mysubdomain.localhost.com here
+ // slow things here, especially the 'replace' but this is a good and understable( I hope) way to get the be able to set cookies from subdomains & domain with 1-level limit
+ if dotIdx := strings.LastIndexByte(requestDomain, '.'); dotIdx > 0 {
+ // is mysubdomain.localhost.com || mysubsubdomain.mysubdomain.localhost.com
+ s := requestDomain[0:dotIdx] // set mysubdomain.localhost || mysubsubdomain.mysubdomain.localhost
+ if secondDotIdx := strings.LastIndexByte(s, '.'); secondDotIdx > 0 {
+ //is mysubdomain.localhost || mysubsubdomain.mysubdomain.localhost
+ s = s[secondDotIdx+1:] // set to localhost || mysubdomain.localhost
+ }
+ // replace the s with the requestDomain before the domain's siffux
+ subdomainSuff := strings.LastIndexByte(requestDomain, '.')
+ if subdomainSuff > len(s) { // if it is actual exists as subdomain suffix
+ requestDomain = strings.Replace(requestDomain, requestDomain[0:subdomainSuff], s, 1) // set to localhost.com || mysubdomain.localhost.com
+ }
+ }
+ // finally set the .localhost.com (for(1-level) || .mysubdomain.localhost.com (for 2-level subdomain allow)
+ cookie.SetDomain("." + requestDomain) // . to allow persistance
+ }
+
+ }
+ cookie.SetHTTPOnly(true)
+ if s.config.Expires == 0 {
+ // unlimited life
+ cookie.SetExpire(CookieExpireUnlimited)
+ } else if s.config.Expires > 0 {
+ cookie.SetExpire(time.Now().Add(s.config.Expires))
+ } // if it's -1 then the cookie is deleted when the browser closes
+
+ AddFasthttpCookie(cookie, reqCtx)
+ fasthttp.ReleaseCookie(cookie)
+ } else {
+ sess = s.provider.Read(cookieValue)
+ }
+ return sess
+}
+
+// DestroyFasthttp kills the valyala/fasthttp session and remove the associated cookie
+func DestroyFasthttp(reqCtx *fasthttp.RequestCtx) {
+ defaultSessions.DestroyFasthttp(reqCtx)
+}
+
+// DestroyFasthttp kills the valyala/fasthttp session and remove the associated cookie
+func (s *sessions) DestroyFasthttp(reqCtx *fasthttp.RequestCtx) {
+ cookieValue := GetFasthttpCookie(s.config.Cookie, reqCtx)
+ if cookieValue == "" { // nothing to destroy
+ return
+ }
+ RemoveFasthttpCookie(s.config.Cookie, reqCtx)
+ s.provider.Destroy(cookieValue)
+}
+
+// GC tick-tock for the store cleanup
+// it's a blocking function, so run it with go routine, it's totally safe
+func (s *sessions) gc() {
+ s.provider.GC(s.config.GcDuration)
+ // set a timer for the next GC
+ time.AfterFunc(s.config.GcDuration, func() {
+ s.gc()
+ })
+}
+
+// GenerateSessionID returns a random string, used to set the session id
+func GenerateSessionID(length int) string {
+ return base64.URLEncoding.EncodeToString(Random(length))
+}
diff --git a/vendor/github.com/klauspost/compress/LICENSE b/vendor/github.com/klauspost/compress/LICENSE
index 74487567632..1eb75ef68e4 100644
--- a/vendor/github.com/klauspost/compress/LICENSE
+++ b/vendor/github.com/klauspost/compress/LICENSE
@@ -1,4 +1,5 @@
Copyright (c) 2012 The Go Authors. All rights reserved.
+Copyright (c) 2019 Klaus Post. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
diff --git a/vendor/github.com/klauspost/compress/flate/copy.go b/vendor/github.com/klauspost/compress/flate/copy.go
deleted file mode 100644
index a3200a8f49e..00000000000
--- a/vendor/github.com/klauspost/compress/flate/copy.go
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright 2012 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package flate
-
-// forwardCopy is like the built-in copy function except that it always goes
-// forward from the start, even if the dst and src overlap.
-// It is equivalent to:
-// for i := 0; i < n; i++ {
-// mem[dst+i] = mem[src+i]
-// }
-func forwardCopy(mem []byte, dst, src, n int) {
- if dst <= src {
- copy(mem[dst:dst+n], mem[src:src+n])
- return
- }
- for {
- if dst >= src+n {
- copy(mem[dst:dst+n], mem[src:src+n])
- return
- }
- // There is some forward overlap. The destination
- // will be filled with a repeated pattern of mem[src:src+k].
- // We copy one instance of the pattern here, then repeat.
- // Each time around this loop k will double.
- k := dst - src
- copy(mem[dst:dst+k], mem[src:src+k])
- n -= k
- dst += k
- }
-}
diff --git a/vendor/github.com/klauspost/compress/flate/deflate.go b/vendor/github.com/klauspost/compress/flate/deflate.go
index 9e6e7ff0cfe..6287951204e 100644
--- a/vendor/github.com/klauspost/compress/flate/deflate.go
+++ b/vendor/github.com/klauspost/compress/flate/deflate.go
@@ -77,16 +77,14 @@ var levels = []compressionLevel{
{32, 258, 258, 4096, skipNever, 9},
}
-type compressor struct {
- compressionLevel
-
- w *huffmanBitWriter
- bulkHasher func([]byte, []uint32)
-
- // compression algorithm
- fill func(*compressor, []byte) int // copy data to window
- step func(*compressor) // process window
- sync bool // requesting flush
+// advancedState contains state for the advanced levels, with bigger hash tables, etc.
+type advancedState struct {
+ // deflate state
+ length int
+ offset int
+ hash uint32
+ maxInsertIndex int
+ ii uint16 // position of last match, intended to overflow to reset.
// Input hash chains
// hashHead[hashValue] contains the largest inputIndex with the specified hash value
@@ -99,57 +97,64 @@ type compressor struct {
hashOffset int
// input window: unprocessed data is window[index:windowEnd]
- index int
+ index int
+ bulkHasher func([]byte, []uint32)
+ hashMatch [maxMatchLength + minMatchLength]uint32
+}
+
+type compressor struct {
+ compressionLevel
+
+ w *huffmanBitWriter
+
+ // compression algorithm
+ fill func(*compressor, []byte) int // copy data to window
+ step func(*compressor) // process window
+ sync bool // requesting flush
+
window []byte
windowEnd int
blockStart int // window index where current tokens start
byteAvailable bool // if true, still need to process window[index-1].
+ err error
// queued output tokens
tokens tokens
-
- // deflate state
- length int
- offset int
- hash uint32
- maxInsertIndex int
- err error
- ii uint16 // position of last match, intended to overflow to reset.
-
- snap snappyEnc
- hashMatch [maxMatchLength + minMatchLength]uint32
+ snap fastEnc
+ state *advancedState
}
func (d *compressor) fillDeflate(b []byte) int {
- if d.index >= 2*windowSize-(minMatchLength+maxMatchLength) {
+ s := d.state
+ if s.index >= 2*windowSize-(minMatchLength+maxMatchLength) {
// shift the window by windowSize
copy(d.window[:], d.window[windowSize:2*windowSize])
- d.index -= windowSize
+ s.index -= windowSize
d.windowEnd -= windowSize
if d.blockStart >= windowSize {
d.blockStart -= windowSize
} else {
d.blockStart = math.MaxInt32
}
- d.hashOffset += windowSize
- if d.hashOffset > maxHashOffset {
- delta := d.hashOffset - 1
- d.hashOffset -= delta
- d.chainHead -= delta
+ s.hashOffset += windowSize
+ if s.hashOffset > maxHashOffset {
+ delta := s.hashOffset - 1
+ s.hashOffset -= delta
+ s.chainHead -= delta
// Iterate over slices instead of arrays to avoid copying
// the entire table onto the stack (Issue #18625).
- for i, v := range d.hashPrev[:] {
+ for i, v := range s.hashPrev[:] {
if int(v) > delta {
- d.hashPrev[i] = uint32(int(v) - delta)
+ s.hashPrev[i] = uint32(int(v) - delta)
} else {
- d.hashPrev[i] = 0
+ s.hashPrev[i] = 0
}
}
- for i, v := range d.hashHead[:] {
+ for i, v := range s.hashHead[:] {
if int(v) > delta {
- d.hashHead[i] = uint32(int(v) - delta)
+ s.hashHead[i] = uint32(int(v) - delta)
} else {
- d.hashHead[i] = 0
+ s.hashHead[i] = 0
}
}
}
@@ -207,6 +212,7 @@ func (d *compressor) fillWindow(b []byte) {
case 0, 1, 2:
return
}
+ s := d.state
// If we are given too much, cut it.
if len(b) > windowSize {
b = b[len(b)-windowSize:]
@@ -229,28 +235,28 @@ func (d *compressor) fillWindow(b []byte) {
continue
}
- dst := d.hashMatch[:dstSize]
- d.bulkHasher(tocheck, dst)
+ dst := s.hashMatch[:dstSize]
+ s.bulkHasher(tocheck, dst)
var newH uint32
for i, val := range dst {
di := i + startindex
newH = val & hashMask
// Get previous value with the same hash.
// Our chain should point to the previous value.
- d.hashPrev[di&windowMask] = d.hashHead[newH]
+ s.hashPrev[di&windowMask] = s.hashHead[newH]
// Set the head of the hash chain to us.
- d.hashHead[newH] = uint32(di + d.hashOffset)
+ s.hashHead[newH] = uint32(di + s.hashOffset)
}
- d.hash = newH
+ s.hash = newH
}
// Update window information.
d.windowEnd += n
- d.index = n
+ s.index = n
}
// Try to find a match starting at index whose length is greater than prevSize.
// We only look at chainCount possibilities before giving up.
-// pos = d.index, prevHead = d.chainHead-d.hashOffset, prevLength=minMatchLength-1, lookahead
+// pos = s.index, prevHead = s.chainHead-s.hashOffset, prevLength=minMatchLength-1, lookahead
func (d *compressor) findMatch(pos int, prevHead int, prevLength int, lookahead int) (length, offset int, ok bool) {
minMatchLook := maxMatchLength
if lookahead < minMatchLook {
@@ -295,7 +301,7 @@ func (d *compressor) findMatch(pos int, prevHead int, prevLength int, lookahead
// hashPrev[i & windowMask] has already been overwritten, so stop now.
break
}
- i = int(d.hashPrev[i&windowMask]) - d.hashOffset
+ i = int(d.state.hashPrev[i&windowMask]) - d.state.hashOffset
if i < minIndex || i < 0 {
break
}
@@ -305,7 +311,7 @@ func (d *compressor) findMatch(pos int, prevHead int, prevLength int, lookahead
// Try to find a match starting at index whose length is greater than prevSize.
// We only look at chainCount possibilities before giving up.
-// pos = d.index, prevHead = d.chainHead-d.hashOffset, prevLength=minMatchLength-1, lookahead
+// pos = s.index, prevHead = s.chainHead-s.hashOffset, prevLength=minMatchLength-1, lookahead
func (d *compressor) findMatchSSE(pos int, prevHead int, prevLength int, lookahead int) (length, offset int, ok bool) {
minMatchLook := maxMatchLength
if lookahead < minMatchLook {
@@ -350,7 +356,7 @@ func (d *compressor) findMatchSSE(pos int, prevHead int, prevLength int, lookahe
// hashPrev[i & windowMask] has already been overwritten, so stop now.
break
}
- i = int(d.hashPrev[i&windowMask]) - d.hashOffset
+ i = int(d.state.hashPrev[i&windowMask]) - d.state.hashOffset
if i < minIndex || i < 0 {
break
}
@@ -406,52 +412,57 @@ func matchLen(a, b []byte, max int) int {
func (d *compressor) initDeflate() {
d.window = make([]byte, 2*windowSize)
- d.hashOffset = 1
- d.length = minMatchLength - 1
- d.offset = 0
d.byteAvailable = false
- d.index = 0
- d.hash = 0
- d.chainHead = -1
- d.bulkHasher = bulkHash4
+ d.err = nil
+ if d.state == nil {
+ return
+ }
+ s := d.state
+ s.index = 0
+ s.hashOffset = 1
+ s.length = minMatchLength - 1
+ s.offset = 0
+ s.hash = 0
+ s.chainHead = -1
+ s.bulkHasher = bulkHash4
if useSSE42 {
- d.bulkHasher = crc32sseAll
+ s.bulkHasher = crc32sseAll
}
}
// Assumes that d.fastSkipHashing != skipNever,
// otherwise use deflateLazy
func (d *compressor) deflate() {
-
+ s := d.state
// Sanity enables additional runtime tests.
// It's intended to be used during development
// to supplement the currently ad-hoc unit tests.
const sanity = false
- if d.windowEnd-d.index < minMatchLength+maxMatchLength && !d.sync {
+ if d.windowEnd-s.index < minMatchLength+maxMatchLength && !d.sync {
return
}
- d.maxInsertIndex = d.windowEnd - (minMatchLength - 1)
- if d.index < d.maxInsertIndex {
- d.hash = hash4(d.window[d.index : d.index+minMatchLength])
+ s.maxInsertIndex = d.windowEnd - (minMatchLength - 1)
+ if s.index < s.maxInsertIndex {
+ s.hash = hash4(d.window[s.index : s.index+minMatchLength])
}
for {
- if sanity && d.index > d.windowEnd {
+ if sanity && s.index > d.windowEnd {
panic("index > windowEnd")
}
- lookahead := d.windowEnd - d.index
+ lookahead := d.windowEnd - s.index
if lookahead < minMatchLength+maxMatchLength {
if !d.sync {
return
}
- if sanity && d.index > d.windowEnd {
+ if sanity && s.index > d.windowEnd {
panic("index > windowEnd")
}
if lookahead == 0 {
if d.tokens.n > 0 {
- if d.err = d.writeBlockSkip(d.tokens, d.index, false); d.err != nil {
+ if d.err = d.writeBlockSkip(d.tokens, s.index, false); d.err != nil {
return
}
d.tokens.n = 0
@@ -459,55 +470,55 @@ func (d *compressor) deflate() {
return
}
}
- if d.index < d.maxInsertIndex {
+ if s.index < s.maxInsertIndex {
// Update the hash
- d.hash = hash4(d.window[d.index : d.index+minMatchLength])
- ch := d.hashHead[d.hash&hashMask]
- d.chainHead = int(ch)
- d.hashPrev[d.index&windowMask] = ch
- d.hashHead[d.hash&hashMask] = uint32(d.index + d.hashOffset)
+ s.hash = hash4(d.window[s.index : s.index+minMatchLength])
+ ch := s.hashHead[s.hash&hashMask]
+ s.chainHead = int(ch)
+ s.hashPrev[s.index&windowMask] = ch
+ s.hashHead[s.hash&hashMask] = uint32(s.index + s.hashOffset)
}
- d.length = minMatchLength - 1
- d.offset = 0
- minIndex := d.index - windowSize
+ s.length = minMatchLength - 1
+ s.offset = 0
+ minIndex := s.index - windowSize
if minIndex < 0 {
minIndex = 0
}
- if d.chainHead-d.hashOffset >= minIndex && lookahead > minMatchLength-1 {
- if newLength, newOffset, ok := d.findMatch(d.index, d.chainHead-d.hashOffset, minMatchLength-1, lookahead); ok {
- d.length = newLength
- d.offset = newOffset
+ if s.chainHead-s.hashOffset >= minIndex && lookahead > minMatchLength-1 {
+ if newLength, newOffset, ok := d.findMatch(s.index, s.chainHead-s.hashOffset, minMatchLength-1, lookahead); ok {
+ s.length = newLength
+ s.offset = newOffset
}
}
- if d.length >= minMatchLength {
- d.ii = 0
+ if s.length >= minMatchLength {
+ s.ii = 0
// There was a match at the previous step, and the current match is
// not better. Output the previous match.
- // "d.length-3" should NOT be "d.length-minMatchLength", since the format always assume 3
- d.tokens.tokens[d.tokens.n] = matchToken(uint32(d.length-3), uint32(d.offset-minOffsetSize))
+ // "s.length-3" should NOT be "s.length-minMatchLength", since the format always assume 3
+ d.tokens.tokens[d.tokens.n] = matchToken(uint32(s.length-3), uint32(s.offset-minOffsetSize))
d.tokens.n++
// Insert in the hash table all strings up to the end of the match.
// index and index-1 are already inserted. If there is not enough
// lookahead, the last two strings are not inserted into the hash
// table.
- if d.length <= d.fastSkipHashing {
+ if s.length <= d.fastSkipHashing {
var newIndex int
- newIndex = d.index + d.length
+ newIndex = s.index + s.length
// Calculate missing hashes
end := newIndex
- if end > d.maxInsertIndex {
- end = d.maxInsertIndex
+ if end > s.maxInsertIndex {
+ end = s.maxInsertIndex
}
end += minMatchLength - 1
- startindex := d.index + 1
- if startindex > d.maxInsertIndex {
- startindex = d.maxInsertIndex
+ startindex := s.index + 1
+ if startindex > s.maxInsertIndex {
+ startindex = s.maxInsertIndex
}
tocheck := d.window[startindex:end]
dstSize := len(tocheck) - minMatchLength + 1
if dstSize > 0 {
- dst := d.hashMatch[:dstSize]
+ dst := s.hashMatch[:dstSize]
bulkHash4(tocheck, dst)
var newH uint32
for i, val := range dst {
@@ -515,35 +526,35 @@ func (d *compressor) deflate() {
newH = val & hashMask
// Get previous value with the same hash.
// Our chain should point to the previous value.
- d.hashPrev[di&windowMask] = d.hashHead[newH]
+ s.hashPrev[di&windowMask] = s.hashHead[newH]
// Set the head of the hash chain to us.
- d.hashHead[newH] = uint32(di + d.hashOffset)
+ s.hashHead[newH] = uint32(di + s.hashOffset)
}
- d.hash = newH
+ s.hash = newH
}
- d.index = newIndex
+ s.index = newIndex
} else {
// For matches this long, we don't bother inserting each individual
// item into the table.
- d.index += d.length
- if d.index < d.maxInsertIndex {
- d.hash = hash4(d.window[d.index : d.index+minMatchLength])
+ s.index += s.length
+ if s.index < s.maxInsertIndex {
+ s.hash = hash4(d.window[s.index : s.index+minMatchLength])
}
}
if d.tokens.n == maxFlateBlockTokens {
// The block includes the current character
- if d.err = d.writeBlockSkip(d.tokens, d.index, false); d.err != nil {
+ if d.err = d.writeBlockSkip(d.tokens, s.index, false); d.err != nil {
return
}
d.tokens.n = 0
}
} else {
- d.ii++
- end := d.index + int(d.ii>>uint(d.fastSkipHashing)) + 1
+ s.ii++
+ end := s.index + int(s.ii>>uint(d.fastSkipHashing)) + 1
if end > d.windowEnd {
end = d.windowEnd
}
- for i := d.index; i < end; i++ {
+ for i := s.index; i < end; i++ {
d.tokens.tokens[d.tokens.n] = literalToken(uint32(d.window[i]))
d.tokens.n++
if d.tokens.n == maxFlateBlockTokens {
@@ -553,7 +564,7 @@ func (d *compressor) deflate() {
d.tokens.n = 0
}
}
- d.index = end
+ s.index = end
}
}
}
@@ -561,42 +572,43 @@ func (d *compressor) deflate() {
// deflateLazy is the same as deflate, but with d.fastSkipHashing == skipNever,
// meaning it always has lazy matching on.
func (d *compressor) deflateLazy() {
+ s := d.state
// Sanity enables additional runtime tests.
// It's intended to be used during development
// to supplement the currently ad-hoc unit tests.
const sanity = false
- if d.windowEnd-d.index < minMatchLength+maxMatchLength && !d.sync {
+ if d.windowEnd-s.index < minMatchLength+maxMatchLength && !d.sync {
return
}
- d.maxInsertIndex = d.windowEnd - (minMatchLength - 1)
- if d.index < d.maxInsertIndex {
- d.hash = hash4(d.window[d.index : d.index+minMatchLength])
+ s.maxInsertIndex = d.windowEnd - (minMatchLength - 1)
+ if s.index < s.maxInsertIndex {
+ s.hash = hash4(d.window[s.index : s.index+minMatchLength])
}
for {
- if sanity && d.index > d.windowEnd {
+ if sanity && s.index > d.windowEnd {
panic("index > windowEnd")
}
- lookahead := d.windowEnd - d.index
+ lookahead := d.windowEnd - s.index
if lookahead < minMatchLength+maxMatchLength {
if !d.sync {
return
}
- if sanity && d.index > d.windowEnd {
+ if sanity && s.index > d.windowEnd {
panic("index > windowEnd")
}
if lookahead == 0 {
// Flush current output block if any.
if d.byteAvailable {
// There is still one pending token that needs to be flushed
- d.tokens.tokens[d.tokens.n] = literalToken(uint32(d.window[d.index-1]))
+ d.tokens.tokens[d.tokens.n] = literalToken(uint32(d.window[s.index-1]))
d.tokens.n++
d.byteAvailable = false
}
if d.tokens.n > 0 {
- if d.err = d.writeBlock(d.tokens, d.index, false); d.err != nil {
+ if d.err = d.writeBlock(d.tokens, s.index, false); d.err != nil {
return
}
d.tokens.n = 0
@@ -604,30 +616,30 @@ func (d *compressor) deflateLazy() {
return
}
}
- if d.index < d.maxInsertIndex {
+ if s.index < s.maxInsertIndex {
// Update the hash
- d.hash = hash4(d.window[d.index : d.index+minMatchLength])
- ch := d.hashHead[d.hash&hashMask]
- d.chainHead = int(ch)
- d.hashPrev[d.index&windowMask] = ch
- d.hashHead[d.hash&hashMask] = uint32(d.index + d.hashOffset)
+ s.hash = hash4(d.window[s.index : s.index+minMatchLength])
+ ch := s.hashHead[s.hash&hashMask]
+ s.chainHead = int(ch)
+ s.hashPrev[s.index&windowMask] = ch
+ s.hashHead[s.hash&hashMask] = uint32(s.index + s.hashOffset)
}
- prevLength := d.length
- prevOffset := d.offset
- d.length = minMatchLength - 1
- d.offset = 0
- minIndex := d.index - windowSize
+ prevLength := s.length
+ prevOffset := s.offset
+ s.length = minMatchLength - 1
+ s.offset = 0
+ minIndex := s.index - windowSize
if minIndex < 0 {
minIndex = 0
}
- if d.chainHead-d.hashOffset >= minIndex && lookahead > prevLength && prevLength < d.lazy {
- if newLength, newOffset, ok := d.findMatch(d.index, d.chainHead-d.hashOffset, minMatchLength-1, lookahead); ok {
- d.length = newLength
- d.offset = newOffset
+ if s.chainHead-s.hashOffset >= minIndex && lookahead > prevLength && prevLength < d.lazy {
+ if newLength, newOffset, ok := d.findMatch(s.index, s.chainHead-s.hashOffset, minMatchLength-1, lookahead); ok {
+ s.length = newLength
+ s.offset = newOffset
}
}
- if prevLength >= minMatchLength && d.length <= prevLength {
+ if prevLength >= minMatchLength && s.length <= prevLength {
// There was a match at the previous step, and the current match is
// not better. Output the previous match.
d.tokens.tokens[d.tokens.n] = matchToken(uint32(prevLength-3), uint32(prevOffset-minOffsetSize))
@@ -638,21 +650,21 @@ func (d *compressor) deflateLazy() {
// lookahead, the last two strings are not inserted into the hash
// table.
var newIndex int
- newIndex = d.index + prevLength - 1
+ newIndex = s.index + prevLength - 1
// Calculate missing hashes
end := newIndex
- if end > d.maxInsertIndex {
- end = d.maxInsertIndex
+ if end > s.maxInsertIndex {
+ end = s.maxInsertIndex
}
end += minMatchLength - 1
- startindex := d.index + 1
- if startindex > d.maxInsertIndex {
- startindex = d.maxInsertIndex
+ startindex := s.index + 1
+ if startindex > s.maxInsertIndex {
+ startindex = s.maxInsertIndex
}
tocheck := d.window[startindex:end]
dstSize := len(tocheck) - minMatchLength + 1
if dstSize > 0 {
- dst := d.hashMatch[:dstSize]
+ dst := s.hashMatch[:dstSize]
bulkHash4(tocheck, dst)
var newH uint32
for i, val := range dst {
@@ -660,74 +672,74 @@ func (d *compressor) deflateLazy() {
newH = val & hashMask
// Get previous value with the same hash.
// Our chain should point to the previous value.
- d.hashPrev[di&windowMask] = d.hashHead[newH]
+ s.hashPrev[di&windowMask] = s.hashHead[newH]
// Set the head of the hash chain to us.
- d.hashHead[newH] = uint32(di + d.hashOffset)
+ s.hashHead[newH] = uint32(di + s.hashOffset)
}
- d.hash = newH
+ s.hash = newH
}
- d.index = newIndex
+ s.index = newIndex
d.byteAvailable = false
- d.length = minMatchLength - 1
+ s.length = minMatchLength - 1
if d.tokens.n == maxFlateBlockTokens {
// The block includes the current character
- if d.err = d.writeBlock(d.tokens, d.index, false); d.err != nil {
+ if d.err = d.writeBlock(d.tokens, s.index, false); d.err != nil {
return
}
d.tokens.n = 0
}
} else {
// Reset, if we got a match this run.
- if d.length >= minMatchLength {
- d.ii = 0
+ if s.length >= minMatchLength {
+ s.ii = 0
}
// We have a byte waiting. Emit it.
if d.byteAvailable {
- d.ii++
- d.tokens.tokens[d.tokens.n] = literalToken(uint32(d.window[d.index-1]))
+ s.ii++
+ d.tokens.tokens[d.tokens.n] = literalToken(uint32(d.window[s.index-1]))
d.tokens.n++
if d.tokens.n == maxFlateBlockTokens {
- if d.err = d.writeBlock(d.tokens, d.index, false); d.err != nil {
+ if d.err = d.writeBlock(d.tokens, s.index, false); d.err != nil {
return
}
d.tokens.n = 0
}
- d.index++
+ s.index++
// If we have a long run of no matches, skip additional bytes
- // Resets when d.ii overflows after 64KB.
- if d.ii > 31 {
- n := int(d.ii >> 5)
+ // Resets when s.ii overflows after 64KB.
+ if s.ii > 31 {
+ n := int(s.ii >> 5)
for j := 0; j < n; j++ {
- if d.index >= d.windowEnd-1 {
+ if s.index >= d.windowEnd-1 {
break
}
- d.tokens.tokens[d.tokens.n] = literalToken(uint32(d.window[d.index-1]))
+ d.tokens.tokens[d.tokens.n] = literalToken(uint32(d.window[s.index-1]))
d.tokens.n++
if d.tokens.n == maxFlateBlockTokens {
- if d.err = d.writeBlock(d.tokens, d.index, false); d.err != nil {
+ if d.err = d.writeBlock(d.tokens, s.index, false); d.err != nil {
return
}
d.tokens.n = 0
}
- d.index++
+ s.index++
}
// Flush last byte
- d.tokens.tokens[d.tokens.n] = literalToken(uint32(d.window[d.index-1]))
+ d.tokens.tokens[d.tokens.n] = literalToken(uint32(d.window[s.index-1]))
d.tokens.n++
d.byteAvailable = false
- // d.length = minMatchLength - 1 // not needed, since d.ii is reset above, so it should never be > minMatchLength
+ // s.length = minMatchLength - 1 // not needed, since s.ii is reset above, so it should never be > minMatchLength
if d.tokens.n == maxFlateBlockTokens {
- if d.err = d.writeBlock(d.tokens, d.index, false); d.err != nil {
+ if d.err = d.writeBlock(d.tokens, s.index, false); d.err != nil {
return
}
d.tokens.n = 0
}
}
} else {
- d.index++
+ s.index++
d.byteAvailable = true
}
}
@@ -737,36 +749,36 @@ func (d *compressor) deflateLazy() {
// Assumes that d.fastSkipHashing != skipNever,
// otherwise use deflateLazySSE
func (d *compressor) deflateSSE() {
-
+ s := d.state
// Sanity enables additional runtime tests.
// It's intended to be used during development
// to supplement the currently ad-hoc unit tests.
const sanity = false
- if d.windowEnd-d.index < minMatchLength+maxMatchLength && !d.sync {
+ if d.windowEnd-s.index < minMatchLength+maxMatchLength && !d.sync {
return
}
- d.maxInsertIndex = d.windowEnd - (minMatchLength - 1)
- if d.index < d.maxInsertIndex {
- d.hash = crc32sse(d.window[d.index:d.index+minMatchLength]) & hashMask
+ s.maxInsertIndex = d.windowEnd - (minMatchLength - 1)
+ if s.index < s.maxInsertIndex {
+ s.hash = crc32sse(d.window[s.index:s.index+minMatchLength]) & hashMask
}
for {
- if sanity && d.index > d.windowEnd {
+ if sanity && s.index > d.windowEnd {
panic("index > windowEnd")
}
- lookahead := d.windowEnd - d.index
+ lookahead := d.windowEnd - s.index
if lookahead < minMatchLength+maxMatchLength {
if !d.sync {
return
}
- if sanity && d.index > d.windowEnd {
+ if sanity && s.index > d.windowEnd {
panic("index > windowEnd")
}
if lookahead == 0 {
if d.tokens.n > 0 {
- if d.err = d.writeBlockSkip(d.tokens, d.index, false); d.err != nil {
+ if d.err = d.writeBlockSkip(d.tokens, s.index, false); d.err != nil {
return
}
d.tokens.n = 0
@@ -774,55 +786,55 @@ func (d *compressor) deflateSSE() {
return
}
}
- if d.index < d.maxInsertIndex {
+ if s.index < s.maxInsertIndex {
// Update the hash
- d.hash = crc32sse(d.window[d.index:d.index+minMatchLength]) & hashMask
- ch := d.hashHead[d.hash]
- d.chainHead = int(ch)
- d.hashPrev[d.index&windowMask] = ch
- d.hashHead[d.hash] = uint32(d.index + d.hashOffset)
+ s.hash = crc32sse(d.window[s.index:s.index+minMatchLength]) & hashMask
+ ch := s.hashHead[s.hash]
+ s.chainHead = int(ch)
+ s.hashPrev[s.index&windowMask] = ch
+ s.hashHead[s.hash] = uint32(s.index + s.hashOffset)
}
- d.length = minMatchLength - 1
- d.offset = 0
- minIndex := d.index - windowSize
+ s.length = minMatchLength - 1
+ s.offset = 0
+ minIndex := s.index - windowSize
if minIndex < 0 {
minIndex = 0
}
- if d.chainHead-d.hashOffset >= minIndex && lookahead > minMatchLength-1 {
- if newLength, newOffset, ok := d.findMatchSSE(d.index, d.chainHead-d.hashOffset, minMatchLength-1, lookahead); ok {
- d.length = newLength
- d.offset = newOffset
+ if s.chainHead-s.hashOffset >= minIndex && lookahead > minMatchLength-1 {
+ if newLength, newOffset, ok := d.findMatchSSE(s.index, s.chainHead-s.hashOffset, minMatchLength-1, lookahead); ok {
+ s.length = newLength
+ s.offset = newOffset
}
}
- if d.length >= minMatchLength {
- d.ii = 0
+ if s.length >= minMatchLength {
+ s.ii = 0
// There was a match at the previous step, and the current match is
// not better. Output the previous match.
- // "d.length-3" should NOT be "d.length-minMatchLength", since the format always assume 3
- d.tokens.tokens[d.tokens.n] = matchToken(uint32(d.length-3), uint32(d.offset-minOffsetSize))
+ // "s.length-3" should NOT be "s.length-minMatchLength", since the format always assume 3
+ d.tokens.tokens[d.tokens.n] = matchToken(uint32(s.length-3), uint32(s.offset-minOffsetSize))
d.tokens.n++
// Insert in the hash table all strings up to the end of the match.
// index and index-1 are already inserted. If there is not enough
// lookahead, the last two strings are not inserted into the hash
// table.
- if d.length <= d.fastSkipHashing {
+ if s.length <= d.fastSkipHashing {
var newIndex int
- newIndex = d.index + d.length
+ newIndex = s.index + s.length
// Calculate missing hashes
end := newIndex
- if end > d.maxInsertIndex {
- end = d.maxInsertIndex
+ if end > s.maxInsertIndex {
+ end = s.maxInsertIndex
}
end += minMatchLength - 1
- startindex := d.index + 1
- if startindex > d.maxInsertIndex {
- startindex = d.maxInsertIndex
+ startindex := s.index + 1
+ if startindex > s.maxInsertIndex {
+ startindex = s.maxInsertIndex
}
tocheck := d.window[startindex:end]
dstSize := len(tocheck) - minMatchLength + 1
if dstSize > 0 {
- dst := d.hashMatch[:dstSize]
+ dst := s.hashMatch[:dstSize]
crc32sseAll(tocheck, dst)
var newH uint32
@@ -831,35 +843,35 @@ func (d *compressor) deflateSSE() {
newH = val & hashMask
// Get previous value with the same hash.
// Our chain should point to the previous value.
- d.hashPrev[di&windowMask] = d.hashHead[newH]
+ s.hashPrev[di&windowMask] = s.hashHead[newH]
// Set the head of the hash chain to us.
- d.hashHead[newH] = uint32(di + d.hashOffset)
+ s.hashHead[newH] = uint32(di + s.hashOffset)
}
- d.hash = newH
+ s.hash = newH
}
- d.index = newIndex
+ s.index = newIndex
} else {
// For matches this long, we don't bother inserting each individual
// item into the table.
- d.index += d.length
- if d.index < d.maxInsertIndex {
- d.hash = crc32sse(d.window[d.index:d.index+minMatchLength]) & hashMask
+ s.index += s.length
+ if s.index < s.maxInsertIndex {
+ s.hash = crc32sse(d.window[s.index:s.index+minMatchLength]) & hashMask
}
}
if d.tokens.n == maxFlateBlockTokens {
// The block includes the current character
- if d.err = d.writeBlockSkip(d.tokens, d.index, false); d.err != nil {
+ if d.err = d.writeBlockSkip(d.tokens, s.index, false); d.err != nil {
return
}
d.tokens.n = 0
}
} else {
- d.ii++
- end := d.index + int(d.ii>>5) + 1
+ s.ii++
+ end := s.index + int(s.ii>>5) + 1
if end > d.windowEnd {
end = d.windowEnd
}
- for i := d.index; i < end; i++ {
+ for i := s.index; i < end; i++ {
d.tokens.tokens[d.tokens.n] = literalToken(uint32(d.window[i]))
d.tokens.n++
if d.tokens.n == maxFlateBlockTokens {
@@ -869,7 +881,7 @@ func (d *compressor) deflateSSE() {
d.tokens.n = 0
}
}
- d.index = end
+ s.index = end
}
}
}
@@ -877,42 +889,43 @@ func (d *compressor) deflateSSE() {
// deflateLazy is the same as deflate, but with d.fastSkipHashing == skipNever,
// meaning it always has lazy matching on.
func (d *compressor) deflateLazySSE() {
+ s := d.state
// Sanity enables additional runtime tests.
// It's intended to be used during development
// to supplement the currently ad-hoc unit tests.
const sanity = false
- if d.windowEnd-d.index < minMatchLength+maxMatchLength && !d.sync {
+ if d.windowEnd-s.index < minMatchLength+maxMatchLength && !d.sync {
return
}
- d.maxInsertIndex = d.windowEnd - (minMatchLength - 1)
- if d.index < d.maxInsertIndex {
- d.hash = crc32sse(d.window[d.index:d.index+minMatchLength]) & hashMask
+ s.maxInsertIndex = d.windowEnd - (minMatchLength - 1)
+ if s.index < s.maxInsertIndex {
+ s.hash = crc32sse(d.window[s.index:s.index+minMatchLength]) & hashMask
}
for {
- if sanity && d.index > d.windowEnd {
+ if sanity && s.index > d.windowEnd {
panic("index > windowEnd")
}
- lookahead := d.windowEnd - d.index
+ lookahead := d.windowEnd - s.index
if lookahead < minMatchLength+maxMatchLength {
if !d.sync {
return
}
- if sanity && d.index > d.windowEnd {
+ if sanity && s.index > d.windowEnd {
panic("index > windowEnd")
}
if lookahead == 0 {
// Flush current output block if any.
if d.byteAvailable {
// There is still one pending token that needs to be flushed
- d.tokens.tokens[d.tokens.n] = literalToken(uint32(d.window[d.index-1]))
+ d.tokens.tokens[d.tokens.n] = literalToken(uint32(d.window[s.index-1]))
d.tokens.n++
d.byteAvailable = false
}
if d.tokens.n > 0 {
- if d.err = d.writeBlock(d.tokens, d.index, false); d.err != nil {
+ if d.err = d.writeBlock(d.tokens, s.index, false); d.err != nil {
return
}
d.tokens.n = 0
@@ -920,30 +933,30 @@ func (d *compressor) deflateLazySSE() {
return
}
}
- if d.index < d.maxInsertIndex {
+ if s.index < s.maxInsertIndex {
// Update the hash
- d.hash = crc32sse(d.window[d.index:d.index+minMatchLength]) & hashMask
- ch := d.hashHead[d.hash]
- d.chainHead = int(ch)
- d.hashPrev[d.index&windowMask] = ch
- d.hashHead[d.hash] = uint32(d.index + d.hashOffset)
+ s.hash = crc32sse(d.window[s.index:s.index+minMatchLength]) & hashMask
+ ch := s.hashHead[s.hash]
+ s.chainHead = int(ch)
+ s.hashPrev[s.index&windowMask] = ch
+ s.hashHead[s.hash] = uint32(s.index + s.hashOffset)
}
- prevLength := d.length
- prevOffset := d.offset
- d.length = minMatchLength - 1
- d.offset = 0
- minIndex := d.index - windowSize
+ prevLength := s.length
+ prevOffset := s.offset
+ s.length = minMatchLength - 1
+ s.offset = 0
+ minIndex := s.index - windowSize
if minIndex < 0 {
minIndex = 0
}
- if d.chainHead-d.hashOffset >= minIndex && lookahead > prevLength && prevLength < d.lazy {
- if newLength, newOffset, ok := d.findMatchSSE(d.index, d.chainHead-d.hashOffset, minMatchLength-1, lookahead); ok {
- d.length = newLength
- d.offset = newOffset
+ if s.chainHead-s.hashOffset >= minIndex && lookahead > prevLength && prevLength < d.lazy {
+ if newLength, newOffset, ok := d.findMatchSSE(s.index, s.chainHead-s.hashOffset, minMatchLength-1, lookahead); ok {
+ s.length = newLength
+ s.offset = newOffset
}
}
- if prevLength >= minMatchLength && d.length <= prevLength {
+ if prevLength >= minMatchLength && s.length <= prevLength {
// There was a match at the previous step, and the current match is
// not better. Output the previous match.
d.tokens.tokens[d.tokens.n] = matchToken(uint32(prevLength-3), uint32(prevOffset-minOffsetSize))
@@ -954,21 +967,21 @@ func (d *compressor) deflateLazySSE() {
// lookahead, the last two strings are not inserted into the hash
// table.
var newIndex int
- newIndex = d.index + prevLength - 1
+ newIndex = s.index + prevLength - 1
// Calculate missing hashes
end := newIndex
- if end > d.maxInsertIndex {
- end = d.maxInsertIndex
+ if end > s.maxInsertIndex {
+ end = s.maxInsertIndex
}
end += minMatchLength - 1
- startindex := d.index + 1
- if startindex > d.maxInsertIndex {
- startindex = d.maxInsertIndex
+ startindex := s.index + 1
+ if startindex > s.maxInsertIndex {
+ startindex = s.maxInsertIndex
}
tocheck := d.window[startindex:end]
dstSize := len(tocheck) - minMatchLength + 1
if dstSize > 0 {
- dst := d.hashMatch[:dstSize]
+ dst := s.hashMatch[:dstSize]
crc32sseAll(tocheck, dst)
var newH uint32
for i, val := range dst {
@@ -976,74 +989,74 @@ func (d *compressor) deflateLazySSE() {
newH = val & hashMask
// Get previous value with the same hash.
// Our chain should point to the previous value.
- d.hashPrev[di&windowMask] = d.hashHead[newH]
+ s.hashPrev[di&windowMask] = s.hashHead[newH]
// Set the head of the hash chain to us.
- d.hashHead[newH] = uint32(di + d.hashOffset)
+ s.hashHead[newH] = uint32(di + s.hashOffset)
}
- d.hash = newH
+ s.hash = newH
}
- d.index = newIndex
+ s.index = newIndex
d.byteAvailable = false
- d.length = minMatchLength - 1
+ s.length = minMatchLength - 1
if d.tokens.n == maxFlateBlockTokens {
// The block includes the current character
- if d.err = d.writeBlock(d.tokens, d.index, false); d.err != nil {
+ if d.err = d.writeBlock(d.tokens, s.index, false); d.err != nil {
return
}
d.tokens.n = 0
}
} else {
// Reset, if we got a match this run.
- if d.length >= minMatchLength {
- d.ii = 0
+ if s.length >= minMatchLength {
+ s.ii = 0
}
// We have a byte waiting. Emit it.
if d.byteAvailable {
- d.ii++
- d.tokens.tokens[d.tokens.n] = literalToken(uint32(d.window[d.index-1]))
+ s.ii++
+ d.tokens.tokens[d.tokens.n] = literalToken(uint32(d.window[s.index-1]))
d.tokens.n++
if d.tokens.n == maxFlateBlockTokens {
- if d.err = d.writeBlock(d.tokens, d.index, false); d.err != nil {
+ if d.err = d.writeBlock(d.tokens, s.index, false); d.err != nil {
return
}
d.tokens.n = 0
}
- d.index++
+ s.index++
// If we have a long run of no matches, skip additional bytes
- // Resets when d.ii overflows after 64KB.
- if d.ii > 31 {
- n := int(d.ii >> 6)
+ // Resets when s.ii overflows after 64KB.
+ if s.ii > 31 {
+ n := int(s.ii >> 6)
for j := 0; j < n; j++ {
- if d.index >= d.windowEnd-1 {
+ if s.index >= d.windowEnd-1 {
break
}
- d.tokens.tokens[d.tokens.n] = literalToken(uint32(d.window[d.index-1]))
+ d.tokens.tokens[d.tokens.n] = literalToken(uint32(d.window[s.index-1]))
d.tokens.n++
if d.tokens.n == maxFlateBlockTokens {
- if d.err = d.writeBlock(d.tokens, d.index, false); d.err != nil {
+ if d.err = d.writeBlock(d.tokens, s.index, false); d.err != nil {
return
}
d.tokens.n = 0
}
- d.index++
+ s.index++
}
// Flush last byte
- d.tokens.tokens[d.tokens.n] = literalToken(uint32(d.window[d.index-1]))
+ d.tokens.tokens[d.tokens.n] = literalToken(uint32(d.window[s.index-1]))
d.tokens.n++
d.byteAvailable = false
- // d.length = minMatchLength - 1 // not needed, since d.ii is reset above, so it should never be > minMatchLength
+ // s.length = minMatchLength - 1 // not needed, since s.ii is reset above, so it should never be > minMatchLength
if d.tokens.n == maxFlateBlockTokens {
- if d.err = d.writeBlock(d.tokens, d.index, false); d.err != nil {
+ if d.err = d.writeBlock(d.tokens, s.index, false); d.err != nil {
return
}
d.tokens.n = 0
}
}
} else {
- d.index++
+ s.index++
d.byteAvailable = true
}
}
@@ -1167,7 +1180,7 @@ func (d *compressor) init(w io.Writer, level int) (err error) {
d.fill = (*compressor).fillBlock
d.step = (*compressor).storeHuff
case level >= 1 && level <= 4:
- d.snap = newSnappy(level)
+ d.snap = newFastEnc(level)
d.window = make([]byte, maxStoreBlockSize)
d.fill = (*compressor).fillBlock
d.step = (*compressor).storeSnappy
@@ -1175,6 +1188,7 @@ func (d *compressor) init(w io.Writer, level int) (err error) {
level = 5
fallthrough
case 5 <= level && level <= 9:
+ d.state = &advancedState{}
d.compressionLevel = levels[level]
d.initDeflate()
d.fill = (*compressor).fillDeflate
@@ -1215,22 +1229,23 @@ func (d *compressor) reset(w io.Writer) {
// level was NoCompression or ConstantCompresssion.
d.windowEnd = 0
default:
- d.chainHead = -1
- for i := range d.hashHead {
- d.hashHead[i] = 0
+ s := d.state
+ s.chainHead = -1
+ for i := range s.hashHead {
+ s.hashHead[i] = 0
}
- for i := range d.hashPrev {
- d.hashPrev[i] = 0
+ for i := range s.hashPrev {
+ s.hashPrev[i] = 0
}
- d.hashOffset = 1
- d.index, d.windowEnd = 0, 0
+ s.hashOffset = 1
+ s.index, d.windowEnd = 0, 0
d.blockStart, d.byteAvailable = 0, false
d.tokens.n = 0
- d.length = minMatchLength - 1
- d.offset = 0
- d.hash = 0
- d.ii = 0
- d.maxInsertIndex = 0
+ s.length = minMatchLength - 1
+ s.offset = 0
+ s.hash = 0
+ s.ii = 0
+ s.maxInsertIndex = 0
}
}
diff --git a/vendor/github.com/klauspost/compress/flate/huffman_bit_writer.go b/vendor/github.com/klauspost/compress/flate/huffman_bit_writer.go
index f9b2a699a3d..f46c654189f 100644
--- a/vendor/github.com/klauspost/compress/flate/huffman_bit_writer.go
+++ b/vendor/github.com/klauspost/compress/flate/huffman_bit_writer.go
@@ -35,7 +35,7 @@ const (
)
// The number of extra bits needed by length code X - LENGTH_CODES_START.
-var lengthExtraBits = []int8{
+var lengthExtraBits = [32]int8{
/* 257 */ 0, 0, 0,
/* 260 */ 0, 0, 0, 0, 0, 1, 1, 1, 1, 2,
/* 270 */ 2, 2, 2, 3, 3, 3, 3, 4, 4, 4,
@@ -43,14 +43,14 @@ var lengthExtraBits = []int8{
}
// The length indicated by length code X - LENGTH_CODES_START.
-var lengthBase = []uint32{
+var lengthBase = [32]uint8{
0, 1, 2, 3, 4, 5, 6, 7, 8, 10,
12, 14, 16, 20, 24, 28, 32, 40, 48, 56,
64, 80, 96, 112, 128, 160, 192, 224, 255,
}
// offset code word extra bits.
-var offsetExtraBits = []int8{
+var offsetExtraBits = [64]int8{
0, 0, 0, 0, 1, 1, 2, 2, 3, 3,
4, 4, 5, 5, 6, 6, 7, 7, 8, 8,
9, 9, 10, 10, 11, 11, 12, 12, 13, 13,
@@ -58,7 +58,7 @@ var offsetExtraBits = []int8{
14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20,
}
-var offsetBase = []uint32{
+var offsetBase = [64]uint32{
/* normal deflate */
0x000000, 0x000001, 0x000002, 0x000003, 0x000004,
0x000006, 0x000008, 0x00000c, 0x000010, 0x000018,
@@ -86,9 +86,9 @@ type huffmanBitWriter struct {
// and then the low nbits of bits.
bits uint64
nbits uint
- bytes [bufferSize]byte
+ bytes [256]byte
codegenFreq [codegenCodeCount]int32
- nbytes int
+ nbytes uint8
literalFreq []int32
offsetFreq []int32
codegen []uint8
@@ -101,8 +101,8 @@ type huffmanBitWriter struct {
func newHuffmanBitWriter(w io.Writer) *huffmanBitWriter {
return &huffmanBitWriter{
writer: w,
- literalFreq: make([]int32, maxNumLit),
- offsetFreq: make([]int32, offsetCodeCount),
+ literalFreq: make([]int32, lengthCodesStart+32),
+ offsetFreq: make([]int32, 32),
codegen: make([]uint8, maxNumLit+offsetCodeCount+1),
literalEncoding: newHuffmanEncoder(maxNumLit),
codegenEncoding: newHuffmanEncoder(codegenCodeCount),
@@ -113,7 +113,7 @@ func newHuffmanBitWriter(w io.Writer) *huffmanBitWriter {
func (w *huffmanBitWriter) reset(writer io.Writer) {
w.writer = writer
w.bits, w.nbits, w.nbytes, w.err = 0, 0, 0, nil
- w.bytes = [bufferSize]byte{}
+ w.bytes = [256]byte{}
}
func (w *huffmanBitWriter) flush() {
@@ -145,9 +145,6 @@ func (w *huffmanBitWriter) write(b []byte) {
}
func (w *huffmanBitWriter) writeBits(b int32, nb uint) {
- if w.err != nil {
- return
- }
w.bits |= uint64(b) << w.nbits
w.nbits += nb
if w.nbits >= 48 {
@@ -155,15 +152,18 @@ func (w *huffmanBitWriter) writeBits(b int32, nb uint) {
w.bits >>= 48
w.nbits -= 48
n := w.nbytes
- bytes := w.bytes[n : n+6]
- bytes[0] = byte(bits)
- bytes[1] = byte(bits >> 8)
- bytes[2] = byte(bits >> 16)
- bytes[3] = byte(bits >> 24)
- bytes[4] = byte(bits >> 32)
- bytes[5] = byte(bits >> 40)
+ w.bytes[n] = byte(bits)
+ w.bytes[n+1] = byte(bits >> 8)
+ w.bytes[n+2] = byte(bits >> 16)
+ w.bytes[n+3] = byte(bits >> 24)
+ w.bytes[n+4] = byte(bits >> 32)
+ w.bytes[n+5] = byte(bits >> 40)
n += 6
if n >= bufferFlushSize {
+ if w.err != nil {
+ n = 0
+ return
+ }
w.write(w.bytes[:n])
n = 0
}
@@ -333,9 +333,6 @@ func (w *huffmanBitWriter) storedSize(in []byte) (int, bool) {
}
func (w *huffmanBitWriter) writeCode(c hcode) {
- if w.err != nil {
- return
- }
w.bits |= uint64(c.code) << w.nbits
w.nbits += uint(c.len)
if w.nbits >= 48 {
@@ -343,15 +340,18 @@ func (w *huffmanBitWriter) writeCode(c hcode) {
w.bits >>= 48
w.nbits -= 48
n := w.nbytes
- bytes := w.bytes[n : n+6]
- bytes[0] = byte(bits)
- bytes[1] = byte(bits >> 8)
- bytes[2] = byte(bits >> 16)
- bytes[3] = byte(bits >> 24)
- bytes[4] = byte(bits >> 32)
- bytes[5] = byte(bits >> 40)
+ w.bytes[n] = byte(bits)
+ w.bytes[n+1] = byte(bits >> 8)
+ w.bytes[n+2] = byte(bits >> 16)
+ w.bytes[n+3] = byte(bits >> 24)
+ w.bytes[n+4] = byte(bits >> 32)
+ w.bytes[n+5] = byte(bits >> 40)
n += 6
if n >= bufferFlushSize {
+ if w.err != nil {
+ n = 0
+ return
+ }
w.write(w.bytes[:n])
n = 0
}
@@ -460,7 +460,7 @@ func (w *huffmanBitWriter) writeBlock(tokens []token, eof bool, input []byte) {
}
for offsetCode := 4; offsetCode < numOffsets; offsetCode++ {
// First four offset codes have extra size = 0.
- extraBits += int(w.offsetFreq[offsetCode]) * int(offsetExtraBits[offsetCode])
+ extraBits += int(w.offsetFreq[offsetCode]) * int(offsetExtraBits[offsetCode&63])
}
}
@@ -548,15 +548,30 @@ func (w *huffmanBitWriter) indexTokens(tokens []token) (numLiterals, numOffsets
w.offsetFreq[i] = 0
}
+ if len(tokens) == 0 {
+ return
+ }
+
+ // Only last token should be endBlockMarker.
+ if tokens[len(tokens)-1] == endBlockMarker {
+ w.literalFreq[endBlockMarker]++
+ tokens = tokens[:len(tokens)-1]
+ }
+
+ // Create slices up to the next power of two to avoid bounds checks.
+ lits := w.literalFreq[:256]
+ offs := w.offsetFreq[:32]
+ lengths := w.literalFreq[lengthCodesStart:]
+ lengths = lengths[:32]
for _, t := range tokens {
- if t < matchType {
- w.literalFreq[t.literal()]++
+ if t < endBlockMarker {
+ lits[t.literal()]++
continue
}
length := t.length()
offset := t.offset()
- w.literalFreq[lengthCodesStart+lengthCode(length)]++
- w.offsetFreq[offsetCode(offset)]++
+ lengths[lengthCode(length)&31]++
+ offs[offsetCode(offset)&31]++
}
// get the number of literals
@@ -575,8 +590,8 @@ func (w *huffmanBitWriter) indexTokens(tokens []token) (numLiterals, numOffsets
w.offsetFreq[0] = 1
numOffsets = 1
}
- w.literalEncoding.generate(w.literalFreq, 15)
- w.offsetEncoding.generate(w.offsetFreq, 15)
+ w.literalEncoding.generate(w.literalFreq[:maxNumLit], 15)
+ w.offsetEncoding.generate(w.offsetFreq[:offsetCodeCount], 15)
return
}
@@ -586,30 +601,50 @@ func (w *huffmanBitWriter) writeTokens(tokens []token, leCodes, oeCodes []hcode)
if w.err != nil {
return
}
+ if len(tokens) == 0 {
+ return
+ }
+
+ // Only last token should be endBlockMarker.
+ var deferEOB bool
+ if tokens[len(tokens)-1] == endBlockMarker {
+ tokens = tokens[:len(tokens)-1]
+ deferEOB = true
+ }
+
+ // Create slices up to the next power of two to avoid bounds checks.
+ lits := leCodes[:256]
+ offs := oeCodes[:32]
+ lengths := leCodes[lengthCodesStart:]
+ lengths = lengths[:32]
for _, t := range tokens {
if t < matchType {
- w.writeCode(leCodes[t.literal()])
+ w.writeCode(lits[t.literal()])
continue
}
+
// Write the length
length := t.length()
lengthCode := lengthCode(length)
- w.writeCode(leCodes[lengthCode+lengthCodesStart])
- extraLengthBits := uint(lengthExtraBits[lengthCode])
+ w.writeCode(lengths[lengthCode&31])
+ extraLengthBits := uint(lengthExtraBits[lengthCode&31])
if extraLengthBits > 0 {
- extraLength := int32(length - lengthBase[lengthCode])
+ extraLength := int32(length - lengthBase[lengthCode&31])
w.writeBits(extraLength, extraLengthBits)
}
// Write the offset
offset := t.offset()
offsetCode := offsetCode(offset)
- w.writeCode(oeCodes[offsetCode])
- extraOffsetBits := uint(offsetExtraBits[offsetCode])
+ w.writeCode(offs[offsetCode&31])
+ extraOffsetBits := uint(offsetExtraBits[offsetCode&63])
if extraOffsetBits > 0 {
- extraOffset := int32(offset - offsetBase[offsetCode])
+ extraOffset := int32(offset - offsetBase[offsetCode&63])
w.writeBits(extraOffset, extraOffsetBits)
}
}
+ if deferEOB {
+ w.writeCode(leCodes[endBlockMarker])
+ }
}
// huffOffset is a static offset encoder used for huffman only encoding.
@@ -620,7 +655,7 @@ func init() {
w := newHuffmanBitWriter(nil)
w.offsetFreq[0] = 1
huffOffset = newHuffmanEncoder(offsetCodeCount)
- huffOffset.generate(w.offsetFreq, 15)
+ huffOffset.generate(w.offsetFreq[:offsetCodeCount], 15)
}
// writeBlockHuff encodes a block of bytes as either
@@ -644,7 +679,7 @@ func (w *huffmanBitWriter) writeBlockHuff(eof bool, input []byte) {
const numLiterals = endBlockMarker + 1
const numOffsets = 1
- w.literalEncoding.generate(w.literalFreq, 15)
+ w.literalEncoding.generate(w.literalFreq[:maxNumLit], 15)
// Figure out smallest code.
// Always use dynamic Huffman or Store
@@ -679,13 +714,12 @@ func (w *huffmanBitWriter) writeBlockHuff(eof bool, input []byte) {
bits := w.bits
w.bits >>= 48
w.nbits -= 48
- bytes := w.bytes[n : n+6]
- bytes[0] = byte(bits)
- bytes[1] = byte(bits >> 8)
- bytes[2] = byte(bits >> 16)
- bytes[3] = byte(bits >> 24)
- bytes[4] = byte(bits >> 32)
- bytes[5] = byte(bits >> 40)
+ w.bytes[n] = byte(bits)
+ w.bytes[n+1] = byte(bits >> 8)
+ w.bytes[n+2] = byte(bits >> 16)
+ w.bytes[n+3] = byte(bits >> 24)
+ w.bytes[n+4] = byte(bits >> 32)
+ w.bytes[n+5] = byte(bits >> 40)
n += 6
if n < bufferFlushSize {
continue
diff --git a/vendor/github.com/klauspost/compress/flate/huffman_code.go b/vendor/github.com/klauspost/compress/flate/huffman_code.go
index bdcbd823b00..f65f7933614 100644
--- a/vendor/github.com/klauspost/compress/flate/huffman_code.go
+++ b/vendor/github.com/klauspost/compress/flate/huffman_code.go
@@ -6,6 +6,7 @@ package flate
import (
"math"
+ "math/bits"
"sort"
)
@@ -56,7 +57,9 @@ func (h *hcode) set(code uint16, length uint16) {
func maxNode() literalNode { return literalNode{math.MaxUint16, math.MaxInt32} }
func newHuffmanEncoder(size int) *huffmanEncoder {
- return &huffmanEncoder{codes: make([]hcode, size)}
+ // Make capacity to next power of two.
+ c := uint(bits.Len32(uint32(size - 1)))
+ return &huffmanEncoder{codes: make([]hcode, size, 1< maxMatchLength || xoffset > maxMatchOffset {
- panic(fmt.Sprintf("Invalid match: len: %d, offset: %d\n", xlength, xoffset))
- return token(matchType)
- }
- return token(matchType + xlength<> lengthShift) }
+func (t token) length() uint8 { return uint8(t >> lengthShift) }
-func lengthCode(len uint32) uint32 { return lengthCodes[len] }
+// The code is never more than 8 bits, but is returned as uint32 for convenience.
+func lengthCode(len uint8) uint32 { return uint32(lengthCodes[len]) }
// Returns the offset code corresponding to a specific offset
func offsetCode(off uint32) uint32 {
if off < uint32(len(offsetCodes)) {
- return offsetCodes[off]
+ return offsetCodes[off&255]
} else if off>>7 < uint32(len(offsetCodes)) {
- return offsetCodes[off>>7] + 14
+ return offsetCodes[(off>>7)&255] + 14
} else {
- return offsetCodes[off>>14] + 28
+ return offsetCodes[(off>>14)&255] + 28
}
}
diff --git a/vendor/github.com/konsorten/go-windows-terminal-sequences/LICENSE b/vendor/github.com/konsorten/go-windows-terminal-sequences/LICENSE
new file mode 100644
index 00000000000..14127cd831e
--- /dev/null
+++ b/vendor/github.com/konsorten/go-windows-terminal-sequences/LICENSE
@@ -0,0 +1,9 @@
+(The MIT License)
+
+Copyright (c) 2017 marvin + konsorten GmbH (open-source@konsorten.de)
+
+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/konsorten/go-windows-terminal-sequences/README.md b/vendor/github.com/konsorten/go-windows-terminal-sequences/README.md
new file mode 100644
index 00000000000..195333e51d4
--- /dev/null
+++ b/vendor/github.com/konsorten/go-windows-terminal-sequences/README.md
@@ -0,0 +1,41 @@
+# Windows Terminal Sequences
+
+This library allow for enabling Windows terminal color support for Go.
+
+See [Console Virtual Terminal Sequences](https://docs.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences) for details.
+
+## Usage
+
+```go
+import (
+ "syscall"
+
+ sequences "github.com/konsorten/go-windows-terminal-sequences"
+)
+
+func main() {
+ sequences.EnableVirtualTerminalProcessing(syscall.Stdout, true)
+}
+
+```
+
+## Authors
+
+The tool is sponsored by the [marvin + konsorten GmbH](http://www.konsorten.de).
+
+We thank all the authors who provided code to this library:
+
+* Felix Kollmann
+* Nicolas Perraut
+
+## License
+
+(The MIT License)
+
+Copyright (c) 2018 marvin + konsorten GmbH (open-source@konsorten.de)
+
+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/konsorten/go-windows-terminal-sequences/go.mod b/vendor/github.com/konsorten/go-windows-terminal-sequences/go.mod
new file mode 100644
index 00000000000..716c6131256
--- /dev/null
+++ b/vendor/github.com/konsorten/go-windows-terminal-sequences/go.mod
@@ -0,0 +1 @@
+module github.com/konsorten/go-windows-terminal-sequences
diff --git a/vendor/github.com/konsorten/go-windows-terminal-sequences/sequences.go b/vendor/github.com/konsorten/go-windows-terminal-sequences/sequences.go
new file mode 100644
index 00000000000..ef18d8f9787
--- /dev/null
+++ b/vendor/github.com/konsorten/go-windows-terminal-sequences/sequences.go
@@ -0,0 +1,36 @@
+// +build windows
+
+package sequences
+
+import (
+ "syscall"
+ "unsafe"
+)
+
+var (
+ kernel32Dll *syscall.LazyDLL = syscall.NewLazyDLL("Kernel32.dll")
+ setConsoleMode *syscall.LazyProc = kernel32Dll.NewProc("SetConsoleMode")
+)
+
+func EnableVirtualTerminalProcessing(stream syscall.Handle, enable bool) error {
+ const ENABLE_VIRTUAL_TERMINAL_PROCESSING uint32 = 0x4
+
+ var mode uint32
+ err := syscall.GetConsoleMode(syscall.Stdout, &mode)
+ if err != nil {
+ return err
+ }
+
+ if enable {
+ mode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING
+ } else {
+ mode &^= ENABLE_VIRTUAL_TERMINAL_PROCESSING
+ }
+
+ ret, _, err := setConsoleMode.Call(uintptr(unsafe.Pointer(stream)), uintptr(mode))
+ if ret == 0 {
+ return err
+ }
+
+ return nil
+}
diff --git a/vendor/github.com/konsorten/go-windows-terminal-sequences/sequences_dummy.go b/vendor/github.com/konsorten/go-windows-terminal-sequences/sequences_dummy.go
new file mode 100644
index 00000000000..df61a6f2f6f
--- /dev/null
+++ b/vendor/github.com/konsorten/go-windows-terminal-sequences/sequences_dummy.go
@@ -0,0 +1,11 @@
+// +build linux darwin
+
+package sequences
+
+import (
+ "fmt"
+)
+
+func EnableVirtualTerminalProcessing(stream uintptr, enable bool) error {
+ return fmt.Errorf("windows only package")
+}
diff --git a/vendor/github.com/Sirupsen/logrus/.gitignore b/vendor/github.com/sirupsen/logrus/.gitignore
similarity index 50%
rename from vendor/github.com/Sirupsen/logrus/.gitignore
rename to vendor/github.com/sirupsen/logrus/.gitignore
index 66be63a0057..6b7d7d1e8b9 100644
--- a/vendor/github.com/Sirupsen/logrus/.gitignore
+++ b/vendor/github.com/sirupsen/logrus/.gitignore
@@ -1 +1,2 @@
logrus
+vendor
diff --git a/vendor/github.com/sirupsen/logrus/.travis.yml b/vendor/github.com/sirupsen/logrus/.travis.yml
new file mode 100644
index 00000000000..848938a6d4e
--- /dev/null
+++ b/vendor/github.com/sirupsen/logrus/.travis.yml
@@ -0,0 +1,25 @@
+language: go
+go_import_path: github.com/sirupsen/logrus
+git:
+ depth: 1
+env:
+ - GO111MODULE=on
+ - GO111MODULE=off
+go: [ 1.11.x, 1.12.x ]
+os: [ linux, osx ]
+matrix:
+ exclude:
+ - go: 1.12.x
+ env: GO111MODULE=off
+ - go: 1.11.x
+ os: osx
+install:
+ - ./travis/install.sh
+ - if [[ "$GO111MODULE" == "on" ]]; then go mod download; fi
+ - if [[ "$GO111MODULE" == "off" ]]; then go get github.com/stretchr/testify/assert golang.org/x/sys/unix github.com/konsorten/go-windows-terminal-sequences; fi
+script:
+ - ./travis/cross_build.sh
+ - export GOMAXPROCS=4
+ - export GORACE=halt_on_error=1
+ - go test -race -v ./...
+ - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then go test -race -v -tags appengine ./... ; fi
diff --git a/vendor/github.com/sirupsen/logrus/CHANGELOG.md b/vendor/github.com/sirupsen/logrus/CHANGELOG.md
new file mode 100644
index 00000000000..51a7ab0cab9
--- /dev/null
+++ b/vendor/github.com/sirupsen/logrus/CHANGELOG.md
@@ -0,0 +1,200 @@
+# 1.4.2
+ * Fixes build break for plan9, nacl, solaris
+# 1.4.1
+This new release introduces:
+ * Enhance TextFormatter to not print caller information when they are empty (#944)
+ * Remove dependency on golang.org/x/crypto (#932, #943)
+
+Fixes:
+ * Fix Entry.WithContext method to return a copy of the initial entry (#941)
+
+# 1.4.0
+This new release introduces:
+ * Add `DeferExitHandler`, similar to `RegisterExitHandler` but prepending the handler to the list of handlers (semantically like `defer`) (#848).
+ * Add `CallerPrettyfier` to `JSONFormatter` and `TextFormatter (#909, #911)
+ * Add `Entry.WithContext()` and `Entry.Context`, to set a context on entries to be used e.g. in hooks (#919).
+
+Fixes:
+ * Fix wrong method calls `Logger.Print` and `Logger.Warningln` (#893).
+ * Update `Entry.Logf` to not do string formatting unless the log level is enabled (#903)
+ * Fix infinite recursion on unknown `Level.String()` (#907)
+ * Fix race condition in `getCaller` (#916).
+
+
+# 1.3.0
+This new release introduces:
+ * Log, Logf, Logln functions for Logger and Entry that take a Level
+
+Fixes:
+ * Building prometheus node_exporter on AIX (#840)
+ * Race condition in TextFormatter (#468)
+ * Travis CI import path (#868)
+ * Remove coloured output on Windows (#862)
+ * Pointer to func as field in JSONFormatter (#870)
+ * Properly marshal Levels (#873)
+
+# 1.2.0
+This new release introduces:
+ * A new method `SetReportCaller` in the `Logger` to enable the file, line and calling function from which the trace has been issued
+ * A new trace level named `Trace` whose level is below `Debug`
+ * A configurable exit function to be called upon a Fatal trace
+ * The `Level` object now implements `encoding.TextUnmarshaler` interface
+
+# 1.1.1
+This is a bug fix release.
+ * fix the build break on Solaris
+ * don't drop a whole trace in JSONFormatter when a field param is a function pointer which can not be serialized
+
+# 1.1.0
+This new release introduces:
+ * several fixes:
+ * a fix for a race condition on entry formatting
+ * proper cleanup of previously used entries before putting them back in the pool
+ * the extra new line at the end of message in text formatter has been removed
+ * a new global public API to check if a level is activated: IsLevelEnabled
+ * the following methods have been added to the Logger object
+ * IsLevelEnabled
+ * SetFormatter
+ * SetOutput
+ * ReplaceHooks
+ * introduction of go module
+ * an indent configuration for the json formatter
+ * output colour support for windows
+ * the field sort function is now configurable for text formatter
+ * the CLICOLOR and CLICOLOR\_FORCE environment variable support in text formater
+
+# 1.0.6
+
+This new release introduces:
+ * a new api WithTime which allows to easily force the time of the log entry
+ which is mostly useful for logger wrapper
+ * a fix reverting the immutability of the entry given as parameter to the hooks
+ a new configuration field of the json formatter in order to put all the fields
+ in a nested dictionnary
+ * a new SetOutput method in the Logger
+ * a new configuration of the textformatter to configure the name of the default keys
+ * a new configuration of the text formatter to disable the level truncation
+
+# 1.0.5
+
+* Fix hooks race (#707)
+* Fix panic deadlock (#695)
+
+# 1.0.4
+
+* Fix race when adding hooks (#612)
+* Fix terminal check in AppEngine (#635)
+
+# 1.0.3
+
+* Replace example files with testable examples
+
+# 1.0.2
+
+* bug: quote non-string values in text formatter (#583)
+* Make (*Logger) SetLevel a public method
+
+# 1.0.1
+
+* bug: fix escaping in text formatter (#575)
+
+# 1.0.0
+
+* Officially changed name to lower-case
+* bug: colors on Windows 10 (#541)
+* bug: fix race in accessing level (#512)
+
+# 0.11.5
+
+* feature: add writer and writerlevel to entry (#372)
+
+# 0.11.4
+
+* bug: fix undefined variable on solaris (#493)
+
+# 0.11.3
+
+* formatter: configure quoting of empty values (#484)
+* formatter: configure quoting character (default is `"`) (#484)
+* bug: fix not importing io correctly in non-linux environments (#481)
+
+# 0.11.2
+
+* bug: fix windows terminal detection (#476)
+
+# 0.11.1
+
+* bug: fix tty detection with custom out (#471)
+
+# 0.11.0
+
+* performance: Use bufferpool to allocate (#370)
+* terminal: terminal detection for app-engine (#343)
+* feature: exit handler (#375)
+
+# 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)
+* logrus/doc: small typo fixes and doc improvements
+
+
+# 0.8.6
+
+* hooks/raven: allow passing an initialized client
+
+# 0.8.5
+
+* logrus/core: revert #208
+
+# 0.8.4
+
+* formatter/text: fix data race (#218)
+
+# 0.8.3
+
+* logrus/core: fix entry log level (#208)
+* logrus/core: improve performance of text formatter by 40%
+* logrus/core: expose `LevelHooks` type
+* logrus/core: add support for DragonflyBSD and NetBSD
+* formatter/text: print structs more verbosely
+
+# 0.8.2
+
+* logrus: fix more Fatal family functions
+
+# 0.8.1
+
+* logrus: fix not exiting on `Fatalf` and `Fatalln`
+
+# 0.8.0
+
+* logrus: defaults to stderr instead of stdout
+* hooks/sentry: add special field for `*http.Request`
+* formatter/text: ignore Windows for colors
+
+# 0.7.3
+
+* formatter/\*: allow configuration of timestamp layout
+
+# 0.7.2
+
+* formatter/text: Add configuration option for time format (#158)
diff --git a/vendor/github.com/Sirupsen/logrus/LICENSE b/vendor/github.com/sirupsen/logrus/LICENSE
similarity index 100%
rename from vendor/github.com/Sirupsen/logrus/LICENSE
rename to vendor/github.com/sirupsen/logrus/LICENSE
diff --git a/vendor/github.com/Sirupsen/logrus/README.md b/vendor/github.com/sirupsen/logrus/README.md
similarity index 92%
rename from vendor/github.com/Sirupsen/logrus/README.md
rename to vendor/github.com/sirupsen/logrus/README.md
index 072e99be313..a4796eb07d4 100644
--- a/vendor/github.com/Sirupsen/logrus/README.md
+++ b/vendor/github.com/sirupsen/logrus/README.md
@@ -56,8 +56,39 @@ time="2015-03-26T01:27:38-04:00" level=warning msg="The group's number increased
time="2015-03-26T01:27:38-04:00" level=debug msg="Temperature changes" temperature=-4
time="2015-03-26T01:27:38-04:00" level=panic msg="It's over 9000!" animal=orca size=9009
time="2015-03-26T01:27:38-04:00" level=fatal msg="The ice breaks!" err=&{0x2082280c0 map[animal:orca size:9009] 2015-03-26 01:27:38.441574009 -0400 EDT panic It's over 9000!} number=100 omg=true
-exit status 1
```
+To ensure this behaviour even if a TTY is attached, set your formatter as follows:
+
+```go
+ log.SetFormatter(&log.TextFormatter{
+ DisableColors: true,
+ FullTimestamp: true,
+ })
+```
+
+#### Logging Method Name
+
+If you wish to add the calling method as a field, instruct the logger via:
+```go
+log.SetReportCaller(true)
+```
+This adds the caller as 'method' like so:
+
+```json
+{"animal":"penguin","level":"fatal","method":"github.com/sirupsen/arcticcreatures.migrate","msg":"a penguin swims by",
+"time":"2014-03-10 19:57:38.562543129 -0400 EDT"}
+```
+
+```text
+time="2015-03-26T01:27:38-04:00" level=fatal method=github.com/sirupsen/arcticcreatures.migrate msg="a penguin swims by" animal=penguin
+```
+Note that this does add measurable overhead - the cost will depend on the version of Go, but is
+between 20 and 40% in recent tests with 1.6 and 1.7. You can validate this in your
+environment via benchmarks:
+```
+go test -bench=.*CallerTracing
+```
+
#### Case-sensitivity
@@ -246,9 +277,10 @@ A list of currently known of service hook can be found in this wiki [page](https
#### Level logging
-Logrus has six logging levels: Debug, Info, Warning, Error, Fatal and Panic.
+Logrus has seven logging levels: Trace, Debug, Info, Warning, Error, Fatal and Panic.
```go
+log.Trace("Something very low level.")
log.Debug("Useful debugging information.")
log.Info("Something noteworthy happened!")
log.Warn("You should probably take a look at this.")
@@ -329,9 +361,11 @@ The built-in logging formatters are:
Third party logging formatters:
* [`FluentdFormatter`](https://github.com/joonix/log). Formats entries that can be parsed by Kubernetes and Google Container Engine.
+* [`GELF`](https://github.com/fabienm/go-logrus-formatters). Formats entries so they comply to Graylog's [GELF 1.1 specification](http://docs.graylog.org/en/2.4/pages/gelf.html).
* [`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̰̥̅!̣͔̲̻͊̄ ̙̘̦̹̦.
+* [`nested-logrus-formatter`](https://github.com/antonfisher/nested-logrus-formatter). Converts logrus fields to a nested structure.
You can define your formatter by implementing the `Formatter` interface,
requiring a `Format` method. `Format` takes an `*Entry`. `entry.Data` is a
diff --git a/vendor/github.com/Sirupsen/logrus/alt_exit.go b/vendor/github.com/sirupsen/logrus/alt_exit.go
similarity index 74%
rename from vendor/github.com/Sirupsen/logrus/alt_exit.go
rename to vendor/github.com/sirupsen/logrus/alt_exit.go
index 8af90637a99..8fd189e1cca 100644
--- a/vendor/github.com/Sirupsen/logrus/alt_exit.go
+++ b/vendor/github.com/sirupsen/logrus/alt_exit.go
@@ -51,9 +51,9 @@ func Exit(code int) {
os.Exit(code)
}
-// RegisterExitHandler adds a Logrus Exit handler, call logrus.Exit to invoke
-// all handlers. The handlers will also be invoked when any Fatal log entry is
-// made.
+// RegisterExitHandler appends a Logrus Exit handler to the list of handlers,
+// call logrus.Exit to invoke all handlers. The handlers will also be invoked when
+// any Fatal log entry is made.
//
// This method is useful when a caller wishes to use logrus to log a fatal
// message but also needs to gracefully shutdown. An example usecase could be
@@ -62,3 +62,15 @@ func Exit(code int) {
func RegisterExitHandler(handler func()) {
handlers = append(handlers, handler)
}
+
+// DeferExitHandler prepends a Logrus Exit handler to the list of handlers,
+// call logrus.Exit to invoke all handlers. The handlers will also be invoked when
+// any Fatal log entry is made.
+//
+// This method is useful when a caller wishes to use logrus to log a fatal
+// message but also needs to gracefully shutdown. An example usecase could be
+// closing database connections, or sending a alert that the application is
+// closing.
+func DeferExitHandler(handler func()) {
+ handlers = append([]func(){handler}, handlers...)
+}
diff --git a/vendor/github.com/Sirupsen/logrus/appveyor.yml b/vendor/github.com/sirupsen/logrus/appveyor.yml
similarity index 100%
rename from vendor/github.com/Sirupsen/logrus/appveyor.yml
rename to vendor/github.com/sirupsen/logrus/appveyor.yml
diff --git a/vendor/github.com/Sirupsen/logrus/doc.go b/vendor/github.com/sirupsen/logrus/doc.go
similarity index 100%
rename from vendor/github.com/Sirupsen/logrus/doc.go
rename to vendor/github.com/sirupsen/logrus/doc.go
diff --git a/vendor/github.com/Sirupsen/logrus/entry.go b/vendor/github.com/sirupsen/logrus/entry.go
similarity index 51%
rename from vendor/github.com/Sirupsen/logrus/entry.go
rename to vendor/github.com/sirupsen/logrus/entry.go
index 473bd1a0d3b..63e25583cb0 100644
--- a/vendor/github.com/Sirupsen/logrus/entry.go
+++ b/vendor/github.com/sirupsen/logrus/entry.go
@@ -2,13 +2,33 @@ package logrus
import (
"bytes"
+ "context"
"fmt"
"os"
+ "reflect"
+ "runtime"
+ "strings"
"sync"
"time"
)
-var bufferPool *sync.Pool
+var (
+ bufferPool *sync.Pool
+
+ // qualified package name, cached at first use
+ logrusPackage string
+
+ // Positions in the call stack when tracing to report the calling method
+ minimumCallerDepth int
+
+ // Used for caller information initialisation
+ callerInitOnce sync.Once
+)
+
+const (
+ maximumCallerDepth int = 25
+ knownLogrusFrames int = 4
+)
func init() {
bufferPool = &sync.Pool{
@@ -16,15 +36,18 @@ func init() {
return new(bytes.Buffer)
},
}
+
+ // start at the bottom of the stack before the package-name cache is primed
+ minimumCallerDepth = 1
}
// Defines the key when adding errors using WithError.
var ErrorKey = "error"
// An entry is the final or intermediate Logrus logging entry. It contains all
-// the fields passed with WithField{,s}. It's finally logged when Debug, Info,
-// Warn, Error, Fatal or Panic is called on it. These objects can be reused and
-// passed around as much as you wish to avoid field duplication.
+// the fields passed with WithField{,s}. It's finally logged when Trace, Debug,
+// Info, Warn, Error, Fatal or Panic is called on it. These objects can be
+// reused and passed around as much as you wish to avoid field duplication.
type Entry struct {
Logger *Logger
@@ -34,22 +57,31 @@ type Entry struct {
// Time at which the log entry was created
Time time.Time
- // Level the log entry was logged at: Debug, Info, Warn, Error, Fatal or Panic
+ // Level the log entry was logged at: Trace, Debug, Info, Warn, Error, Fatal or Panic
// This field will be set on entry firing and the value will be equal to the one in Logger struct field.
Level Level
- // Message passed to Debug, Info, Warn, Error, Fatal or Panic
+ // Calling method, with package name
+ Caller *runtime.Frame
+
+ // Message passed to Trace, Debug, Info, Warn, Error, Fatal or Panic
Message string
- // When formatter is called in entry.log(), an Buffer may be set to entry
+ // When formatter is called in entry.log(), a Buffer may be set to entry
Buffer *bytes.Buffer
+
+ // Contains the context set by the user. Useful for hook processing etc.
+ Context context.Context
+
+ // err may contain a field formatting error
+ err string
}
func NewEntry(logger *Logger) *Entry {
return &Entry{
Logger: logger,
- // Default is five fields, give a little extra room
- Data: make(Fields, 5),
+ // Default is three fields, plus one optional. Give a little extra room.
+ Data: make(Fields, 6),
}
}
@@ -69,6 +101,11 @@ func (entry *Entry) WithError(err error) *Entry {
return entry.WithField(ErrorKey, err)
}
+// Add a context to the Entry.
+func (entry *Entry) WithContext(ctx context.Context) *Entry {
+ return &Entry{Logger: entry.Logger, Data: entry.Data, Time: entry.Time, err: entry.err, Context: ctx}
+}
+
// Add a single field to the Entry.
func (entry *Entry) WithField(key string, value interface{}) *Entry {
return entry.WithFields(Fields{key: value})
@@ -80,15 +117,88 @@ func (entry *Entry) WithFields(fields Fields) *Entry {
for k, v := range entry.Data {
data[k] = v
}
+ fieldErr := entry.err
for k, v := range fields {
- data[k] = v
+ isErrField := false
+ if t := reflect.TypeOf(v); t != nil {
+ switch t.Kind() {
+ case reflect.Func:
+ isErrField = true
+ case reflect.Ptr:
+ isErrField = t.Elem().Kind() == reflect.Func
+ }
+ }
+ if isErrField {
+ tmp := fmt.Sprintf("can not add field %q", k)
+ if fieldErr != "" {
+ fieldErr = entry.err + ", " + tmp
+ } else {
+ fieldErr = tmp
+ }
+ } else {
+ data[k] = v
+ }
}
- return &Entry{Logger: entry.Logger, Data: data, Time: entry.Time}
+ return &Entry{Logger: entry.Logger, Data: data, Time: entry.Time, err: fieldErr, Context: entry.Context}
}
// Overrides the time of the Entry.
func (entry *Entry) WithTime(t time.Time) *Entry {
- return &Entry{Logger: entry.Logger, Data: entry.Data, Time: t}
+ return &Entry{Logger: entry.Logger, Data: entry.Data, Time: t, err: entry.err, Context: entry.Context}
+}
+
+// getPackageName reduces a fully qualified function name to the package name
+// There really ought to be to be a better way...
+func getPackageName(f string) string {
+ for {
+ lastPeriod := strings.LastIndex(f, ".")
+ lastSlash := strings.LastIndex(f, "/")
+ if lastPeriod > lastSlash {
+ f = f[:lastPeriod]
+ } else {
+ break
+ }
+ }
+
+ return f
+}
+
+// getCaller retrieves the name of the first non-logrus calling function
+func getCaller() *runtime.Frame {
+
+ // cache this package's fully-qualified name
+ callerInitOnce.Do(func() {
+ pcs := make([]uintptr, 2)
+ _ = runtime.Callers(0, pcs)
+ logrusPackage = getPackageName(runtime.FuncForPC(pcs[1]).Name())
+
+ // now that we have the cache, we can skip a minimum count of known-logrus functions
+ // XXX this is dubious, the number of frames may vary
+ minimumCallerDepth = knownLogrusFrames
+ })
+
+ // Restrict the lookback frames to avoid runaway lookups
+ pcs := make([]uintptr, maximumCallerDepth)
+ depth := runtime.Callers(minimumCallerDepth, pcs)
+ frames := runtime.CallersFrames(pcs[:depth])
+
+ for f, again := frames.Next(); again; f, again = frames.Next() {
+ pkg := getPackageName(f.Function)
+
+ // If the caller isn't part of this package, we're done
+ if pkg != logrusPackage {
+ return &f
+ }
+ }
+
+ // if we got here, we failed to find the caller's context
+ return nil
+}
+
+func (entry Entry) HasCaller() (has bool) {
+ return entry.Logger != nil &&
+ entry.Logger.ReportCaller &&
+ entry.Caller != nil
}
// This function is not declared with a pointer value because otherwise
@@ -107,6 +217,9 @@ func (entry Entry) log(level Level, msg string) {
entry.Level = level
entry.Message = msg
+ if entry.Logger.ReportCaller {
+ entry.Caller = getCaller()
+ }
entry.fireHooks()
@@ -137,9 +250,9 @@ func (entry *Entry) fireHooks() {
}
func (entry *Entry) write() {
- serialized, err := entry.Logger.Formatter.Format(entry)
entry.Logger.mu.Lock()
defer entry.Logger.mu.Unlock()
+ serialized, err := entry.Logger.Formatter.Format(entry)
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to obtain reader, %v\n", err)
} else {
@@ -150,26 +263,30 @@ func (entry *Entry) write() {
}
}
-func (entry *Entry) Debug(args ...interface{}) {
- if entry.Logger.level() >= DebugLevel {
- entry.log(DebugLevel, fmt.Sprint(args...))
+func (entry *Entry) Log(level Level, args ...interface{}) {
+ if entry.Logger.IsLevelEnabled(level) {
+ entry.log(level, fmt.Sprint(args...))
}
}
+func (entry *Entry) Trace(args ...interface{}) {
+ entry.Log(TraceLevel, args...)
+}
+
+func (entry *Entry) Debug(args ...interface{}) {
+ entry.Log(DebugLevel, args...)
+}
+
func (entry *Entry) Print(args ...interface{}) {
entry.Info(args...)
}
func (entry *Entry) Info(args ...interface{}) {
- if entry.Logger.level() >= InfoLevel {
- entry.log(InfoLevel, fmt.Sprint(args...))
- }
+ entry.Log(InfoLevel, args...)
}
func (entry *Entry) Warn(args ...interface{}) {
- if entry.Logger.level() >= WarnLevel {
- entry.log(WarnLevel, fmt.Sprint(args...))
- }
+ entry.Log(WarnLevel, args...)
}
func (entry *Entry) Warning(args ...interface{}) {
@@ -177,37 +294,37 @@ func (entry *Entry) Warning(args ...interface{}) {
}
func (entry *Entry) Error(args ...interface{}) {
- if entry.Logger.level() >= ErrorLevel {
- entry.log(ErrorLevel, fmt.Sprint(args...))
- }
+ entry.Log(ErrorLevel, args...)
}
func (entry *Entry) Fatal(args ...interface{}) {
- if entry.Logger.level() >= FatalLevel {
- entry.log(FatalLevel, fmt.Sprint(args...))
- }
- Exit(1)
+ entry.Log(FatalLevel, args...)
+ entry.Logger.Exit(1)
}
func (entry *Entry) Panic(args ...interface{}) {
- if entry.Logger.level() >= PanicLevel {
- entry.log(PanicLevel, fmt.Sprint(args...))
- }
+ entry.Log(PanicLevel, args...)
panic(fmt.Sprint(args...))
}
// Entry Printf family functions
-func (entry *Entry) Debugf(format string, args ...interface{}) {
- if entry.Logger.level() >= DebugLevel {
- entry.Debug(fmt.Sprintf(format, args...))
+func (entry *Entry) Logf(level Level, format string, args ...interface{}) {
+ if entry.Logger.IsLevelEnabled(level) {
+ entry.Log(level, fmt.Sprintf(format, args...))
}
}
+func (entry *Entry) Tracef(format string, args ...interface{}) {
+ entry.Logf(TraceLevel, format, args...)
+}
+
+func (entry *Entry) Debugf(format string, args ...interface{}) {
+ entry.Logf(DebugLevel, format, args...)
+}
+
func (entry *Entry) Infof(format string, args ...interface{}) {
- if entry.Logger.level() >= InfoLevel {
- entry.Info(fmt.Sprintf(format, args...))
- }
+ entry.Logf(InfoLevel, format, args...)
}
func (entry *Entry) Printf(format string, args ...interface{}) {
@@ -215,9 +332,7 @@ func (entry *Entry) Printf(format string, args ...interface{}) {
}
func (entry *Entry) Warnf(format string, args ...interface{}) {
- if entry.Logger.level() >= WarnLevel {
- entry.Warn(fmt.Sprintf(format, args...))
- }
+ entry.Logf(WarnLevel, format, args...)
}
func (entry *Entry) Warningf(format string, args ...interface{}) {
@@ -225,36 +340,36 @@ func (entry *Entry) Warningf(format string, args ...interface{}) {
}
func (entry *Entry) Errorf(format string, args ...interface{}) {
- if entry.Logger.level() >= ErrorLevel {
- entry.Error(fmt.Sprintf(format, args...))
- }
+ entry.Logf(ErrorLevel, format, args...)
}
func (entry *Entry) Fatalf(format string, args ...interface{}) {
- if entry.Logger.level() >= FatalLevel {
- entry.Fatal(fmt.Sprintf(format, args...))
- }
- Exit(1)
+ entry.Logf(FatalLevel, format, args...)
+ entry.Logger.Exit(1)
}
func (entry *Entry) Panicf(format string, args ...interface{}) {
- if entry.Logger.level() >= PanicLevel {
- entry.Panic(fmt.Sprintf(format, args...))
- }
+ entry.Logf(PanicLevel, format, args...)
}
// Entry Println family functions
-func (entry *Entry) Debugln(args ...interface{}) {
- if entry.Logger.level() >= DebugLevel {
- entry.Debug(entry.sprintlnn(args...))
+func (entry *Entry) Logln(level Level, args ...interface{}) {
+ if entry.Logger.IsLevelEnabled(level) {
+ entry.Log(level, entry.sprintlnn(args...))
}
}
+func (entry *Entry) Traceln(args ...interface{}) {
+ entry.Logln(TraceLevel, args...)
+}
+
+func (entry *Entry) Debugln(args ...interface{}) {
+ entry.Logln(DebugLevel, args...)
+}
+
func (entry *Entry) Infoln(args ...interface{}) {
- if entry.Logger.level() >= InfoLevel {
- entry.Info(entry.sprintlnn(args...))
- }
+ entry.Logln(InfoLevel, args...)
}
func (entry *Entry) Println(args ...interface{}) {
@@ -262,9 +377,7 @@ func (entry *Entry) Println(args ...interface{}) {
}
func (entry *Entry) Warnln(args ...interface{}) {
- if entry.Logger.level() >= WarnLevel {
- entry.Warn(entry.sprintlnn(args...))
- }
+ entry.Logln(WarnLevel, args...)
}
func (entry *Entry) Warningln(args ...interface{}) {
@@ -272,22 +385,16 @@ func (entry *Entry) Warningln(args ...interface{}) {
}
func (entry *Entry) Errorln(args ...interface{}) {
- if entry.Logger.level() >= ErrorLevel {
- entry.Error(entry.sprintlnn(args...))
- }
+ entry.Logln(ErrorLevel, args...)
}
func (entry *Entry) Fatalln(args ...interface{}) {
- if entry.Logger.level() >= FatalLevel {
- entry.Fatal(entry.sprintlnn(args...))
- }
- Exit(1)
+ entry.Logln(FatalLevel, args...)
+ entry.Logger.Exit(1)
}
func (entry *Entry) Panicln(args ...interface{}) {
- if entry.Logger.level() >= PanicLevel {
- entry.Panic(entry.sprintlnn(args...))
- }
+ entry.Logln(PanicLevel, args...)
}
// Sprintlnn => Sprint no newline. This is to get the behavior of how
diff --git a/vendor/github.com/Sirupsen/logrus/exported.go b/vendor/github.com/sirupsen/logrus/exported.go
similarity index 83%
rename from vendor/github.com/Sirupsen/logrus/exported.go
rename to vendor/github.com/sirupsen/logrus/exported.go
index eb612a6f3e8..62fc2f2193c 100644
--- a/vendor/github.com/Sirupsen/logrus/exported.go
+++ b/vendor/github.com/sirupsen/logrus/exported.go
@@ -1,6 +1,7 @@
package logrus
import (
+ "context"
"io"
"time"
)
@@ -21,30 +22,33 @@ func SetOutput(out io.Writer) {
// SetFormatter sets the standard logger formatter.
func SetFormatter(formatter Formatter) {
- std.mu.Lock()
- defer std.mu.Unlock()
- std.Formatter = formatter
+ std.SetFormatter(formatter)
+}
+
+// SetReportCaller sets whether the standard logger will include the calling
+// method as a field.
+func SetReportCaller(include bool) {
+ std.SetReportCaller(include)
}
// SetLevel sets the standard logger level.
func SetLevel(level Level) {
- std.mu.Lock()
- defer std.mu.Unlock()
std.SetLevel(level)
}
// GetLevel returns the standard logger level.
func GetLevel() Level {
- std.mu.Lock()
- defer std.mu.Unlock()
- return std.level()
+ return std.GetLevel()
+}
+
+// IsLevelEnabled checks if the log level of the standard logger is greater than the level param
+func IsLevelEnabled(level Level) bool {
+ return std.IsLevelEnabled(level)
}
// AddHook adds a hook to the standard logger hooks.
func AddHook(hook Hook) {
- std.mu.Lock()
- defer std.mu.Unlock()
- std.Hooks.Add(hook)
+ std.AddHook(hook)
}
// WithError creates an entry from the standard logger and adds an error to it, using the value defined in ErrorKey as key.
@@ -52,6 +56,11 @@ func WithError(err error) *Entry {
return std.WithField(ErrorKey, err)
}
+// WithContext creates an entry from the standard logger and adds a context to it.
+func WithContext(ctx context.Context) *Entry {
+ return std.WithContext(ctx)
+}
+
// WithField creates an entry from the standard logger and adds a field to
// it. If you want multiple fields, use `WithFields`.
//
@@ -80,6 +89,11 @@ func WithTime(t time.Time) *Entry {
return std.WithTime(t)
}
+// Trace logs a message at level Trace on the standard logger.
+func Trace(args ...interface{}) {
+ std.Trace(args...)
+}
+
// Debug logs a message at level Debug on the standard logger.
func Debug(args ...interface{}) {
std.Debug(args...)
@@ -120,6 +134,11 @@ func Fatal(args ...interface{}) {
std.Fatal(args...)
}
+// Tracef logs a message at level Trace on the standard logger.
+func Tracef(format string, args ...interface{}) {
+ std.Tracef(format, args...)
+}
+
// Debugf logs a message at level Debug on the standard logger.
func Debugf(format string, args ...interface{}) {
std.Debugf(format, args...)
@@ -160,6 +179,11 @@ func Fatalf(format string, args ...interface{}) {
std.Fatalf(format, args...)
}
+// Traceln logs a message at level Trace on the standard logger.
+func Traceln(args ...interface{}) {
+ std.Traceln(args...)
+}
+
// Debugln logs a message at level Debug on the standard logger.
func Debugln(args ...interface{}) {
std.Debugln(args...)
diff --git a/vendor/github.com/Sirupsen/logrus/formatter.go b/vendor/github.com/sirupsen/logrus/formatter.go
similarity index 60%
rename from vendor/github.com/Sirupsen/logrus/formatter.go
rename to vendor/github.com/sirupsen/logrus/formatter.go
index 83c74947bea..408883773eb 100644
--- a/vendor/github.com/Sirupsen/logrus/formatter.go
+++ b/vendor/github.com/sirupsen/logrus/formatter.go
@@ -2,7 +2,16 @@ package logrus
import "time"
-const defaultTimestampFormat = time.RFC3339
+// Default key names for the default fields
+const (
+ defaultTimestampFormat = time.RFC3339
+ FieldKeyMsg = "msg"
+ FieldKeyLevel = "level"
+ FieldKeyTime = "time"
+ FieldKeyLogrusError = "logrus_error"
+ FieldKeyFunc = "func"
+ FieldKeyFile = "file"
+)
// The Formatter interface is used to implement a custom Formatter. It takes an
// `Entry`. It exposes all the fields, including the default ones:
@@ -18,7 +27,7 @@ type Formatter interface {
Format(*Entry) ([]byte, error)
}
-// This is to not silently overwrite `time`, `msg` and `level` fields when
+// This is to not silently overwrite `time`, `msg`, `func` and `level` fields when
// dumping it. If this code wasn't there doing:
//
// logrus.WithField("level", 1).Info("hello")
@@ -30,7 +39,7 @@ 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, fieldMap FieldMap) {
+func prefixFieldClashes(data Fields, fieldMap FieldMap, reportCaller bool) {
timeKey := fieldMap.resolve(FieldKeyTime)
if t, ok := data[timeKey]; ok {
data["fields."+timeKey] = t
@@ -48,4 +57,22 @@ func prefixFieldClashes(data Fields, fieldMap FieldMap) {
data["fields."+levelKey] = l
delete(data, levelKey)
}
+
+ logrusErrKey := fieldMap.resolve(FieldKeyLogrusError)
+ if l, ok := data[logrusErrKey]; ok {
+ data["fields."+logrusErrKey] = l
+ delete(data, logrusErrKey)
+ }
+
+ // If reportCaller is not set, 'func' will not conflict.
+ if reportCaller {
+ funcKey := fieldMap.resolve(FieldKeyFunc)
+ if l, ok := data[funcKey]; ok {
+ data["fields."+funcKey] = l
+ }
+ fileKey := fieldMap.resolve(FieldKeyFile)
+ if l, ok := data[fileKey]; ok {
+ data["fields."+fileKey] = l
+ }
+ }
}
diff --git a/vendor/github.com/sirupsen/logrus/go.mod b/vendor/github.com/sirupsen/logrus/go.mod
new file mode 100644
index 00000000000..12fdf989847
--- /dev/null
+++ b/vendor/github.com/sirupsen/logrus/go.mod
@@ -0,0 +1,10 @@
+module github.com/sirupsen/logrus
+
+require (
+ github.com/davecgh/go-spew v1.1.1 // indirect
+ github.com/konsorten/go-windows-terminal-sequences v1.0.1
+ github.com/pmezard/go-difflib v1.0.0 // indirect
+ github.com/stretchr/objx v0.1.1 // indirect
+ github.com/stretchr/testify v1.2.2
+ golang.org/x/sys v0.0.0-20190422165155-953cdadca894
+)
diff --git a/vendor/github.com/sirupsen/logrus/go.sum b/vendor/github.com/sirupsen/logrus/go.sum
new file mode 100644
index 00000000000..596c318b9f7
--- /dev/null
+++ b/vendor/github.com/sirupsen/logrus/go.sum
@@ -0,0 +1,16 @@
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/konsorten/go-windows-terminal-sequences v0.0.0-20180402223658-b729f2633dfe h1:CHRGQ8V7OlCYtwaKPJi3iA7J+YdNKdo8j7nG5IgDhjs=
+github.com/konsorten/go-windows-terminal-sequences v0.0.0-20180402223658-b729f2633dfe/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
+github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
+github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A=
+github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
+github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
+golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33 h1:I6FyU15t786LL7oL/hn43zqTuEGr4PN7F4XJ1p4E3Y8=
+golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190422165155-953cdadca894 h1:Cz4ceDQGXuKRnVBDTS23GTn/pU5OE2C0WrNTOYK1Uuc=
+golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
diff --git a/vendor/github.com/Sirupsen/logrus/hooks.go b/vendor/github.com/sirupsen/logrus/hooks.go
similarity index 100%
rename from vendor/github.com/Sirupsen/logrus/hooks.go
rename to vendor/github.com/sirupsen/logrus/hooks.go
diff --git a/vendor/github.com/Sirupsen/logrus/json_formatter.go b/vendor/github.com/sirupsen/logrus/json_formatter.go
similarity index 54%
rename from vendor/github.com/Sirupsen/logrus/json_formatter.go
rename to vendor/github.com/sirupsen/logrus/json_formatter.go
index dab17610f17..098a21a0679 100644
--- a/vendor/github.com/Sirupsen/logrus/json_formatter.go
+++ b/vendor/github.com/sirupsen/logrus/json_formatter.go
@@ -1,8 +1,10 @@
package logrus
import (
+ "bytes"
"encoding/json"
"fmt"
+ "runtime"
)
type fieldKey string
@@ -10,13 +12,6 @@ type fieldKey string
// FieldMap allows customization of the key names for default fields.
type FieldMap map[fieldKey]string
-// Default key names for the default fields
-const (
- FieldKeyMsg = "msg"
- FieldKeyLevel = "level"
- FieldKeyTime = "time"
-)
-
func (f FieldMap) resolve(key fieldKey) string {
if k, ok := f[key]; ok {
return k
@@ -40,17 +35,27 @@ type JSONFormatter struct {
// As an example:
// formatter := &JSONFormatter{
// FieldMap: FieldMap{
- // FieldKeyTime: "@timestamp",
+ // FieldKeyTime: "@timestamp",
// FieldKeyLevel: "@level",
- // FieldKeyMsg: "@message",
+ // FieldKeyMsg: "@message",
+ // FieldKeyFunc: "@caller",
// },
// }
FieldMap FieldMap
+
+ // CallerPrettyfier can be set by the user to modify the content
+ // of the function and file keys in the json data when ReportCaller is
+ // activated. If any of the returned value is the empty string the
+ // corresponding key will be removed from json fields.
+ CallerPrettyfier func(*runtime.Frame) (function string, file string)
+
+ // PrettyPrint will indent all json logs
+ PrettyPrint bool
}
// Format renders a single log entry
func (f *JSONFormatter) Format(entry *Entry) ([]byte, error) {
- data := make(Fields, len(entry.Data)+3)
+ data := make(Fields, len(entry.Data)+4)
for k, v := range entry.Data {
switch v := v.(type) {
case error:
@@ -68,22 +73,49 @@ func (f *JSONFormatter) Format(entry *Entry) ([]byte, error) {
data = newData
}
- prefixFieldClashes(data, f.FieldMap)
+ prefixFieldClashes(data, f.FieldMap, entry.HasCaller())
timestampFormat := f.TimestampFormat
if timestampFormat == "" {
timestampFormat = defaultTimestampFormat
}
+ if entry.err != "" {
+ data[f.FieldMap.resolve(FieldKeyLogrusError)] = entry.err
+ }
if !f.DisableTimestamp {
data[f.FieldMap.resolve(FieldKeyTime)] = entry.Time.Format(timestampFormat)
}
data[f.FieldMap.resolve(FieldKeyMsg)] = entry.Message
data[f.FieldMap.resolve(FieldKeyLevel)] = entry.Level.String()
+ if entry.HasCaller() {
+ funcVal := entry.Caller.Function
+ fileVal := fmt.Sprintf("%s:%d", entry.Caller.File, entry.Caller.Line)
+ if f.CallerPrettyfier != nil {
+ funcVal, fileVal = f.CallerPrettyfier(entry.Caller)
+ }
+ if funcVal != "" {
+ data[f.FieldMap.resolve(FieldKeyFunc)] = funcVal
+ }
+ if fileVal != "" {
+ data[f.FieldMap.resolve(FieldKeyFile)] = fileVal
+ }
+ }
+
+ var b *bytes.Buffer
+ if entry.Buffer != nil {
+ b = entry.Buffer
+ } else {
+ b = &bytes.Buffer{}
+ }
- serialized, err := json.Marshal(data)
- if err != nil {
- return nil, fmt.Errorf("Failed to marshal fields to JSON, %v", err)
+ encoder := json.NewEncoder(b)
+ if f.PrettyPrint {
+ encoder.SetIndent("", " ")
+ }
+ if err := encoder.Encode(data); err != nil {
+ return nil, fmt.Errorf("failed to marshal fields to JSON, %v", err)
}
- return append(serialized, '\n'), nil
+
+ return b.Bytes(), nil
}
diff --git a/vendor/github.com/Sirupsen/logrus/logger.go b/vendor/github.com/sirupsen/logrus/logger.go
similarity index 63%
rename from vendor/github.com/Sirupsen/logrus/logger.go
rename to vendor/github.com/sirupsen/logrus/logger.go
index 342f7977d85..c0c0b1e5590 100644
--- a/vendor/github.com/Sirupsen/logrus/logger.go
+++ b/vendor/github.com/sirupsen/logrus/logger.go
@@ -1,6 +1,7 @@
package logrus
import (
+ "context"
"io"
"os"
"sync"
@@ -11,7 +12,7 @@ import (
type Logger struct {
// The logs are `io.Copy`'d to this in a mutex. It's common to set this to a
// file, or leave it default which is `os.Stderr`. You can also set this to
- // something more adventorous, such as logging to Kafka.
+ // something more adventurous, such as logging to Kafka.
Out io.Writer
// Hooks for the logger instance. These allow firing events based on logging
// levels and log entries. For example, to send errors to an error tracking
@@ -24,6 +25,10 @@ type Logger struct {
// own that implements the `Formatter` interface, see the `README` or included
// formatters for examples.
Formatter Formatter
+
+ // Flag for whether to log caller info (off by default)
+ ReportCaller bool
+
// The logging level the logger should log at. This is typically (and defaults
// to) `logrus.Info`, which allows Info(), Warn(), Error() and Fatal() to be
// logged.
@@ -32,8 +37,12 @@ type Logger struct {
mu MutexWrap
// Reusable empty entry
entryPool sync.Pool
+ // Function to exit the application, defaults to `os.Exit()`
+ ExitFunc exitFunc
}
+type exitFunc func(int)
+
type MutexWrap struct {
lock sync.Mutex
disabled bool
@@ -69,10 +78,12 @@ func (mw *MutexWrap) Disable() {
// It's recommended to make this a global instance called `log`.
func New() *Logger {
return &Logger{
- Out: os.Stderr,
- Formatter: new(TextFormatter),
- Hooks: make(LevelHooks),
- Level: InfoLevel,
+ Out: os.Stderr,
+ Formatter: new(TextFormatter),
+ Hooks: make(LevelHooks),
+ Level: InfoLevel,
+ ExitFunc: os.Exit,
+ ReportCaller: false,
}
}
@@ -85,6 +96,7 @@ func (logger *Logger) newEntry() *Entry {
}
func (logger *Logger) releaseEntry(entry *Entry) {
+ entry.Data = map[string]interface{}{}
logger.entryPool.Put(entry)
}
@@ -113,6 +125,13 @@ func (logger *Logger) WithError(err error) *Entry {
return entry.WithError(err)
}
+// Add a context to the log entry.
+func (logger *Logger) WithContext(ctx context.Context) *Entry {
+ entry := logger.newEntry()
+ defer logger.releaseEntry(entry)
+ return entry.WithContext(ctx)
+}
+
// Overrides the time of the log entry.
func (logger *Logger) WithTime(t time.Time) *Entry {
entry := logger.newEntry()
@@ -120,20 +139,24 @@ func (logger *Logger) WithTime(t time.Time) *Entry {
return entry.WithTime(t)
}
-func (logger *Logger) Debugf(format string, args ...interface{}) {
- if logger.level() >= DebugLevel {
+func (logger *Logger) Logf(level Level, format string, args ...interface{}) {
+ if logger.IsLevelEnabled(level) {
entry := logger.newEntry()
- entry.Debugf(format, args...)
+ entry.Logf(level, format, args...)
logger.releaseEntry(entry)
}
}
+func (logger *Logger) Tracef(format string, args ...interface{}) {
+ logger.Logf(TraceLevel, format, args...)
+}
+
+func (logger *Logger) Debugf(format string, args ...interface{}) {
+ logger.Logf(DebugLevel, format, args...)
+}
+
func (logger *Logger) Infof(format string, args ...interface{}) {
- if logger.level() >= InfoLevel {
- entry := logger.newEntry()
- entry.Infof(format, args...)
- logger.releaseEntry(entry)
- }
+ logger.Logf(InfoLevel, format, args...)
}
func (logger *Logger) Printf(format string, args ...interface{}) {
@@ -143,123 +166,91 @@ func (logger *Logger) Printf(format string, args ...interface{}) {
}
func (logger *Logger) Warnf(format string, args ...interface{}) {
- if logger.level() >= WarnLevel {
- entry := logger.newEntry()
- entry.Warnf(format, args...)
- logger.releaseEntry(entry)
- }
+ logger.Logf(WarnLevel, format, args...)
}
func (logger *Logger) Warningf(format string, args ...interface{}) {
- if logger.level() >= WarnLevel {
- entry := logger.newEntry()
- entry.Warnf(format, args...)
- logger.releaseEntry(entry)
- }
+ logger.Warnf(format, args...)
}
func (logger *Logger) Errorf(format string, args ...interface{}) {
- if logger.level() >= ErrorLevel {
- entry := logger.newEntry()
- entry.Errorf(format, args...)
- logger.releaseEntry(entry)
- }
+ logger.Logf(ErrorLevel, format, args...)
}
func (logger *Logger) Fatalf(format string, args ...interface{}) {
- if logger.level() >= FatalLevel {
- entry := logger.newEntry()
- entry.Fatalf(format, args...)
- logger.releaseEntry(entry)
- }
- Exit(1)
+ logger.Logf(FatalLevel, format, args...)
+ logger.Exit(1)
}
func (logger *Logger) Panicf(format string, args ...interface{}) {
- if logger.level() >= PanicLevel {
+ logger.Logf(PanicLevel, format, args...)
+}
+
+func (logger *Logger) Log(level Level, args ...interface{}) {
+ if logger.IsLevelEnabled(level) {
entry := logger.newEntry()
- entry.Panicf(format, args...)
+ entry.Log(level, args...)
logger.releaseEntry(entry)
}
}
+func (logger *Logger) Trace(args ...interface{}) {
+ logger.Log(TraceLevel, args...)
+}
+
func (logger *Logger) Debug(args ...interface{}) {
- if logger.level() >= DebugLevel {
- entry := logger.newEntry()
- entry.Debug(args...)
- logger.releaseEntry(entry)
- }
+ logger.Log(DebugLevel, args...)
}
func (logger *Logger) Info(args ...interface{}) {
- if logger.level() >= InfoLevel {
- entry := logger.newEntry()
- entry.Info(args...)
- logger.releaseEntry(entry)
- }
+ logger.Log(InfoLevel, args...)
}
func (logger *Logger) Print(args ...interface{}) {
entry := logger.newEntry()
- entry.Info(args...)
+ entry.Print(args...)
logger.releaseEntry(entry)
}
func (logger *Logger) Warn(args ...interface{}) {
- if logger.level() >= WarnLevel {
- entry := logger.newEntry()
- entry.Warn(args...)
- logger.releaseEntry(entry)
- }
+ logger.Log(WarnLevel, args...)
}
func (logger *Logger) Warning(args ...interface{}) {
- if logger.level() >= WarnLevel {
- entry := logger.newEntry()
- entry.Warn(args...)
- logger.releaseEntry(entry)
- }
+ logger.Warn(args...)
}
func (logger *Logger) Error(args ...interface{}) {
- if logger.level() >= ErrorLevel {
- entry := logger.newEntry()
- entry.Error(args...)
- logger.releaseEntry(entry)
- }
+ logger.Log(ErrorLevel, args...)
}
func (logger *Logger) Fatal(args ...interface{}) {
- if logger.level() >= FatalLevel {
- entry := logger.newEntry()
- entry.Fatal(args...)
- logger.releaseEntry(entry)
- }
- Exit(1)
+ logger.Log(FatalLevel, args...)
+ logger.Exit(1)
}
func (logger *Logger) Panic(args ...interface{}) {
- if logger.level() >= PanicLevel {
+ logger.Log(PanicLevel, args...)
+}
+
+func (logger *Logger) Logln(level Level, args ...interface{}) {
+ if logger.IsLevelEnabled(level) {
entry := logger.newEntry()
- entry.Panic(args...)
+ entry.Logln(level, args...)
logger.releaseEntry(entry)
}
}
+func (logger *Logger) Traceln(args ...interface{}) {
+ logger.Logln(TraceLevel, args...)
+}
+
func (logger *Logger) Debugln(args ...interface{}) {
- if logger.level() >= DebugLevel {
- entry := logger.newEntry()
- entry.Debugln(args...)
- logger.releaseEntry(entry)
- }
+ logger.Logln(DebugLevel, args...)
}
func (logger *Logger) Infoln(args ...interface{}) {
- if logger.level() >= InfoLevel {
- entry := logger.newEntry()
- entry.Infoln(args...)
- logger.releaseEntry(entry)
- }
+ logger.Logln(InfoLevel, args...)
}
func (logger *Logger) Println(args ...interface{}) {
@@ -269,44 +260,32 @@ func (logger *Logger) Println(args ...interface{}) {
}
func (logger *Logger) Warnln(args ...interface{}) {
- if logger.level() >= WarnLevel {
- entry := logger.newEntry()
- entry.Warnln(args...)
- logger.releaseEntry(entry)
- }
+ logger.Logln(WarnLevel, args...)
}
func (logger *Logger) Warningln(args ...interface{}) {
- if logger.level() >= WarnLevel {
- entry := logger.newEntry()
- entry.Warnln(args...)
- logger.releaseEntry(entry)
- }
+ logger.Warnln(args...)
}
func (logger *Logger) Errorln(args ...interface{}) {
- if logger.level() >= ErrorLevel {
- entry := logger.newEntry()
- entry.Errorln(args...)
- logger.releaseEntry(entry)
- }
+ logger.Logln(ErrorLevel, args...)
}
func (logger *Logger) Fatalln(args ...interface{}) {
- if logger.level() >= FatalLevel {
- entry := logger.newEntry()
- entry.Fatalln(args...)
- logger.releaseEntry(entry)
- }
- Exit(1)
+ logger.Logln(FatalLevel, args...)
+ logger.Exit(1)
}
func (logger *Logger) Panicln(args ...interface{}) {
- if logger.level() >= PanicLevel {
- entry := logger.newEntry()
- entry.Panicln(args...)
- logger.releaseEntry(entry)
+ logger.Logln(PanicLevel, args...)
+}
+
+func (logger *Logger) Exit(code int) {
+ runHandlers()
+ if logger.ExitFunc == nil {
+ logger.ExitFunc = os.Exit
}
+ logger.ExitFunc(code)
}
//When file is opened with appending mode, it's safe to
@@ -320,18 +299,53 @@ func (logger *Logger) level() Level {
return Level(atomic.LoadUint32((*uint32)(&logger.Level)))
}
+// SetLevel sets the logger level.
func (logger *Logger) SetLevel(level Level) {
atomic.StoreUint32((*uint32)(&logger.Level), uint32(level))
}
-func (logger *Logger) SetOutput(out io.Writer) {
- logger.mu.Lock()
- defer logger.mu.Unlock()
- logger.Out = out
+// GetLevel returns the logger level.
+func (logger *Logger) GetLevel() Level {
+ return logger.level()
}
+// AddHook adds a hook to the logger hooks.
func (logger *Logger) AddHook(hook Hook) {
logger.mu.Lock()
defer logger.mu.Unlock()
logger.Hooks.Add(hook)
}
+
+// IsLevelEnabled checks if the log level of the logger is greater than the level param
+func (logger *Logger) IsLevelEnabled(level Level) bool {
+ return logger.level() >= level
+}
+
+// SetFormatter sets the logger formatter.
+func (logger *Logger) SetFormatter(formatter Formatter) {
+ logger.mu.Lock()
+ defer logger.mu.Unlock()
+ logger.Formatter = formatter
+}
+
+// SetOutput sets the logger output.
+func (logger *Logger) SetOutput(output io.Writer) {
+ logger.mu.Lock()
+ defer logger.mu.Unlock()
+ logger.Out = output
+}
+
+func (logger *Logger) SetReportCaller(reportCaller bool) {
+ logger.mu.Lock()
+ defer logger.mu.Unlock()
+ logger.ReportCaller = reportCaller
+}
+
+// ReplaceHooks replaces the logger hooks and returns the old ones
+func (logger *Logger) ReplaceHooks(hooks LevelHooks) LevelHooks {
+ logger.mu.Lock()
+ oldHooks := logger.Hooks
+ logger.Hooks = hooks
+ logger.mu.Unlock()
+ return oldHooks
+}
diff --git a/vendor/github.com/Sirupsen/logrus/logrus.go b/vendor/github.com/sirupsen/logrus/logrus.go
similarity index 72%
rename from vendor/github.com/Sirupsen/logrus/logrus.go
rename to vendor/github.com/sirupsen/logrus/logrus.go
index dd38999741e..8644761f73c 100644
--- a/vendor/github.com/Sirupsen/logrus/logrus.go
+++ b/vendor/github.com/sirupsen/logrus/logrus.go
@@ -14,22 +14,11 @@ type Level uint32
// Convert the Level to a string. E.g. PanicLevel becomes "panic".
func (level Level) String() string {
- switch level {
- case DebugLevel:
- return "debug"
- case InfoLevel:
- return "info"
- case WarnLevel:
- return "warning"
- case ErrorLevel:
- return "error"
- case FatalLevel:
- return "fatal"
- case PanicLevel:
- return "panic"
+ if b, err := level.MarshalText(); err == nil {
+ return string(b)
+ } else {
+ return "unknown"
}
-
- return "unknown"
}
// ParseLevel takes a string level and returns the Logrus log level constant.
@@ -47,12 +36,47 @@ func ParseLevel(lvl string) (Level, error) {
return InfoLevel, nil
case "debug":
return DebugLevel, nil
+ case "trace":
+ return TraceLevel, nil
}
var l Level
return l, fmt.Errorf("not a valid logrus Level: %q", lvl)
}
+// UnmarshalText implements encoding.TextUnmarshaler.
+func (level *Level) UnmarshalText(text []byte) error {
+ l, err := ParseLevel(string(text))
+ if err != nil {
+ return err
+ }
+
+ *level = Level(l)
+
+ return nil
+}
+
+func (level Level) MarshalText() ([]byte, error) {
+ switch level {
+ case TraceLevel:
+ return []byte("trace"), nil
+ case DebugLevel:
+ return []byte("debug"), nil
+ case InfoLevel:
+ return []byte("info"), nil
+ case WarnLevel:
+ return []byte("warning"), nil
+ case ErrorLevel:
+ return []byte("error"), nil
+ case FatalLevel:
+ return []byte("fatal"), nil
+ case PanicLevel:
+ return []byte("panic"), nil
+ }
+
+ return nil, fmt.Errorf("not a valid logrus level %d", level)
+}
+
// A constant exposing all logging levels
var AllLevels = []Level{
PanicLevel,
@@ -61,6 +85,7 @@ var AllLevels = []Level{
WarnLevel,
InfoLevel,
DebugLevel,
+ TraceLevel,
}
// These are the different logging levels. You can set the logging level to log
@@ -69,7 +94,7 @@ const (
// PanicLevel level, highest level of severity. Logs and then calls panic with the
// message passed to Debug, Info, ...
PanicLevel Level = iota
- // FatalLevel level. Logs and then calls `os.Exit(1)`. It will exit even if the
+ // FatalLevel level. Logs and then calls `logger.Exit(1)`. It will exit even if the
// logging level is set to Panic.
FatalLevel
// ErrorLevel level. Logs. Used for errors that should definitely be noted.
@@ -82,6 +107,8 @@ const (
InfoLevel
// DebugLevel level. Usually only enabled when debugging. Very verbose logging.
DebugLevel
+ // TraceLevel level. Designates finer-grained informational events than the Debug.
+ TraceLevel
)
// Won't compile if StdLogger can't be realized by a log.Logger
@@ -140,4 +167,20 @@ type FieldLogger interface {
Errorln(args ...interface{})
Fatalln(args ...interface{})
Panicln(args ...interface{})
+
+ // IsDebugEnabled() bool
+ // IsInfoEnabled() bool
+ // IsWarnEnabled() bool
+ // IsErrorEnabled() bool
+ // IsFatalEnabled() bool
+ // IsPanicEnabled() bool
+}
+
+// Ext1FieldLogger (the first extension to FieldLogger) is superfluous, it is
+// here for consistancy. Do not use. Use Logger or Entry instead.
+type Ext1FieldLogger interface {
+ FieldLogger
+ Tracef(format string, args ...interface{})
+ Trace(args ...interface{})
+ Traceln(args ...interface{})
}
diff --git a/vendor/github.com/Sirupsen/logrus/terminal_check_appengine.go b/vendor/github.com/sirupsen/logrus/terminal_check_appengine.go
similarity index 75%
rename from vendor/github.com/Sirupsen/logrus/terminal_check_appengine.go
rename to vendor/github.com/sirupsen/logrus/terminal_check_appengine.go
index 3de08e802fd..2403de98192 100644
--- a/vendor/github.com/Sirupsen/logrus/terminal_check_appengine.go
+++ b/vendor/github.com/sirupsen/logrus/terminal_check_appengine.go
@@ -1,4 +1,4 @@
-// +build appengine gopherjs
+// +build appengine
package logrus
diff --git a/vendor/github.com/sirupsen/logrus/terminal_check_bsd.go b/vendor/github.com/sirupsen/logrus/terminal_check_bsd.go
new file mode 100644
index 00000000000..3c4f43f91cd
--- /dev/null
+++ b/vendor/github.com/sirupsen/logrus/terminal_check_bsd.go
@@ -0,0 +1,13 @@
+// +build darwin dragonfly freebsd netbsd openbsd
+
+package logrus
+
+import "golang.org/x/sys/unix"
+
+const ioctlReadTermios = unix.TIOCGETA
+
+func isTerminal(fd int) bool {
+ _, err := unix.IoctlGetTermios(fd, ioctlReadTermios)
+ return err == nil
+}
+
diff --git a/vendor/github.com/sirupsen/logrus/terminal_check_no_terminal.go b/vendor/github.com/sirupsen/logrus/terminal_check_no_terminal.go
new file mode 100644
index 00000000000..97af92c68ea
--- /dev/null
+++ b/vendor/github.com/sirupsen/logrus/terminal_check_no_terminal.go
@@ -0,0 +1,11 @@
+// +build js nacl plan9
+
+package logrus
+
+import (
+ "io"
+)
+
+func checkIfTerminal(w io.Writer) bool {
+ return false
+}
diff --git a/vendor/github.com/Sirupsen/logrus/terminal_check_notappengine.go b/vendor/github.com/sirupsen/logrus/terminal_check_notappengine.go
similarity index 58%
rename from vendor/github.com/Sirupsen/logrus/terminal_check_notappengine.go
rename to vendor/github.com/sirupsen/logrus/terminal_check_notappengine.go
index 067047a1233..3293fb3caad 100644
--- a/vendor/github.com/Sirupsen/logrus/terminal_check_notappengine.go
+++ b/vendor/github.com/sirupsen/logrus/terminal_check_notappengine.go
@@ -1,18 +1,16 @@
-// +build !appengine,!gopherjs
+// +build !appengine,!js,!windows,!nacl,!plan9
package logrus
import (
"io"
"os"
-
- "golang.org/x/crypto/ssh/terminal"
)
func checkIfTerminal(w io.Writer) bool {
switch v := w.(type) {
case *os.File:
- return terminal.IsTerminal(int(v.Fd()))
+ return isTerminal(int(v.Fd()))
default:
return false
}
diff --git a/vendor/github.com/sirupsen/logrus/terminal_check_solaris.go b/vendor/github.com/sirupsen/logrus/terminal_check_solaris.go
new file mode 100644
index 00000000000..f6710b3bd0b
--- /dev/null
+++ b/vendor/github.com/sirupsen/logrus/terminal_check_solaris.go
@@ -0,0 +1,11 @@
+package logrus
+
+import (
+ "golang.org/x/sys/unix"
+)
+
+// IsTerminal returns true if the given file descriptor is a terminal.
+func isTerminal(fd int) bool {
+ _, err := unix.IoctlGetTermio(fd, unix.TCGETA)
+ return err == nil
+}
diff --git a/vendor/github.com/sirupsen/logrus/terminal_check_unix.go b/vendor/github.com/sirupsen/logrus/terminal_check_unix.go
new file mode 100644
index 00000000000..355dc966f00
--- /dev/null
+++ b/vendor/github.com/sirupsen/logrus/terminal_check_unix.go
@@ -0,0 +1,13 @@
+// +build linux aix
+
+package logrus
+
+import "golang.org/x/sys/unix"
+
+const ioctlReadTermios = unix.TCGETS
+
+func isTerminal(fd int) bool {
+ _, err := unix.IoctlGetTermios(fd, ioctlReadTermios)
+ return err == nil
+}
+
diff --git a/vendor/github.com/sirupsen/logrus/terminal_check_windows.go b/vendor/github.com/sirupsen/logrus/terminal_check_windows.go
new file mode 100644
index 00000000000..572889db216
--- /dev/null
+++ b/vendor/github.com/sirupsen/logrus/terminal_check_windows.go
@@ -0,0 +1,34 @@
+// +build !appengine,!js,windows
+
+package logrus
+
+import (
+ "io"
+ "os"
+ "syscall"
+
+ sequences "github.com/konsorten/go-windows-terminal-sequences"
+)
+
+func initTerminal(w io.Writer) {
+ switch v := w.(type) {
+ case *os.File:
+ sequences.EnableVirtualTerminalProcessing(syscall.Handle(v.Fd()), true)
+ }
+}
+
+func checkIfTerminal(w io.Writer) bool {
+ var ret bool
+ switch v := w.(type) {
+ case *os.File:
+ var mode uint32
+ err := syscall.GetConsoleMode(syscall.Handle(v.Fd()), &mode)
+ ret = (err == nil)
+ default:
+ ret = false
+ }
+ if ret {
+ initTerminal(w)
+ }
+ return ret
+}
diff --git a/vendor/github.com/sirupsen/logrus/text_formatter.go b/vendor/github.com/sirupsen/logrus/text_formatter.go
new file mode 100644
index 00000000000..e01587c437d
--- /dev/null
+++ b/vendor/github.com/sirupsen/logrus/text_formatter.go
@@ -0,0 +1,295 @@
+package logrus
+
+import (
+ "bytes"
+ "fmt"
+ "os"
+ "runtime"
+ "sort"
+ "strings"
+ "sync"
+ "time"
+)
+
+const (
+ red = 31
+ yellow = 33
+ blue = 36
+ gray = 37
+)
+
+var baseTimestamp time.Time
+
+func init() {
+ baseTimestamp = time.Now()
+}
+
+// TextFormatter formats logs into text
+type TextFormatter struct {
+ // Set to true to bypass checking for a TTY before outputting colors.
+ ForceColors bool
+
+ // Force disabling colors.
+ DisableColors bool
+
+ // Override coloring based on CLICOLOR and CLICOLOR_FORCE. - https://bixense.com/clicolors/
+ EnvironmentOverrideColors bool
+
+ // Disable timestamp logging. useful when output is redirected to logging
+ // system that already adds timestamps.
+ DisableTimestamp bool
+
+ // Enable logging the full timestamp when a TTY is attached instead of just
+ // the time passed since beginning of execution.
+ FullTimestamp bool
+
+ // TimestampFormat to use for display when a full timestamp is printed
+ TimestampFormat string
+
+ // The fields are sorted by default for a consistent output. For applications
+ // that log extremely frequently and don't use the JSON formatter this may not
+ // be desired.
+ DisableSorting bool
+
+ // The keys sorting function, when uninitialized it uses sort.Strings.
+ SortingFunc func([]string)
+
+ // Disables the truncation of the level text to 4 characters.
+ DisableLevelTruncation bool
+
+ // QuoteEmptyFields will wrap empty fields in quotes if true
+ QuoteEmptyFields bool
+
+ // Whether the logger's out is to a terminal
+ isTerminal bool
+
+ // FieldMap allows users to customize the names of keys for default fields.
+ // As an example:
+ // formatter := &TextFormatter{
+ // FieldMap: FieldMap{
+ // FieldKeyTime: "@timestamp",
+ // FieldKeyLevel: "@level",
+ // FieldKeyMsg: "@message"}}
+ FieldMap FieldMap
+
+ // CallerPrettyfier can be set by the user to modify the content
+ // of the function and file keys in the data when ReportCaller is
+ // activated. If any of the returned value is the empty string the
+ // corresponding key will be removed from fields.
+ CallerPrettyfier func(*runtime.Frame) (function string, file string)
+
+ terminalInitOnce sync.Once
+}
+
+func (f *TextFormatter) init(entry *Entry) {
+ if entry.Logger != nil {
+ f.isTerminal = checkIfTerminal(entry.Logger.Out)
+ }
+}
+
+func (f *TextFormatter) isColored() bool {
+ isColored := f.ForceColors || (f.isTerminal && (runtime.GOOS != "windows"))
+
+ if f.EnvironmentOverrideColors {
+ if force, ok := os.LookupEnv("CLICOLOR_FORCE"); ok && force != "0" {
+ isColored = true
+ } else if ok && force == "0" {
+ isColored = false
+ } else if os.Getenv("CLICOLOR") == "0" {
+ isColored = false
+ }
+ }
+
+ return isColored && !f.DisableColors
+}
+
+// Format renders a single log entry
+func (f *TextFormatter) Format(entry *Entry) ([]byte, error) {
+ data := make(Fields)
+ for k, v := range entry.Data {
+ data[k] = v
+ }
+ prefixFieldClashes(data, f.FieldMap, entry.HasCaller())
+ keys := make([]string, 0, len(data))
+ for k := range data {
+ keys = append(keys, k)
+ }
+
+ var funcVal, fileVal string
+
+ fixedKeys := make([]string, 0, 4+len(data))
+ if !f.DisableTimestamp {
+ fixedKeys = append(fixedKeys, f.FieldMap.resolve(FieldKeyTime))
+ }
+ fixedKeys = append(fixedKeys, f.FieldMap.resolve(FieldKeyLevel))
+ if entry.Message != "" {
+ fixedKeys = append(fixedKeys, f.FieldMap.resolve(FieldKeyMsg))
+ }
+ if entry.err != "" {
+ fixedKeys = append(fixedKeys, f.FieldMap.resolve(FieldKeyLogrusError))
+ }
+ if entry.HasCaller() {
+ if f.CallerPrettyfier != nil {
+ funcVal, fileVal = f.CallerPrettyfier(entry.Caller)
+ } else {
+ funcVal = entry.Caller.Function
+ fileVal = fmt.Sprintf("%s:%d", entry.Caller.File, entry.Caller.Line)
+ }
+
+ if funcVal != "" {
+ fixedKeys = append(fixedKeys, f.FieldMap.resolve(FieldKeyFunc))
+ }
+ if fileVal != "" {
+ fixedKeys = append(fixedKeys, f.FieldMap.resolve(FieldKeyFile))
+ }
+ }
+
+ if !f.DisableSorting {
+ if f.SortingFunc == nil {
+ sort.Strings(keys)
+ fixedKeys = append(fixedKeys, keys...)
+ } else {
+ if !f.isColored() {
+ fixedKeys = append(fixedKeys, keys...)
+ f.SortingFunc(fixedKeys)
+ } else {
+ f.SortingFunc(keys)
+ }
+ }
+ } else {
+ fixedKeys = append(fixedKeys, keys...)
+ }
+
+ var b *bytes.Buffer
+ if entry.Buffer != nil {
+ b = entry.Buffer
+ } else {
+ b = &bytes.Buffer{}
+ }
+
+ f.terminalInitOnce.Do(func() { f.init(entry) })
+
+ timestampFormat := f.TimestampFormat
+ if timestampFormat == "" {
+ timestampFormat = defaultTimestampFormat
+ }
+ if f.isColored() {
+ f.printColored(b, entry, keys, data, timestampFormat)
+ } else {
+
+ for _, key := range fixedKeys {
+ var value interface{}
+ switch {
+ case key == f.FieldMap.resolve(FieldKeyTime):
+ value = entry.Time.Format(timestampFormat)
+ case key == f.FieldMap.resolve(FieldKeyLevel):
+ value = entry.Level.String()
+ case key == f.FieldMap.resolve(FieldKeyMsg):
+ value = entry.Message
+ case key == f.FieldMap.resolve(FieldKeyLogrusError):
+ value = entry.err
+ case key == f.FieldMap.resolve(FieldKeyFunc) && entry.HasCaller():
+ value = funcVal
+ case key == f.FieldMap.resolve(FieldKeyFile) && entry.HasCaller():
+ value = fileVal
+ default:
+ value = data[key]
+ }
+ f.appendKeyValue(b, key, value)
+ }
+ }
+
+ b.WriteByte('\n')
+ return b.Bytes(), nil
+}
+
+func (f *TextFormatter) printColored(b *bytes.Buffer, entry *Entry, keys []string, data Fields, timestampFormat string) {
+ var levelColor int
+ switch entry.Level {
+ case DebugLevel, TraceLevel:
+ levelColor = gray
+ case WarnLevel:
+ levelColor = yellow
+ case ErrorLevel, FatalLevel, PanicLevel:
+ levelColor = red
+ default:
+ levelColor = blue
+ }
+
+ levelText := strings.ToUpper(entry.Level.String())
+ if !f.DisableLevelTruncation {
+ levelText = levelText[0:4]
+ }
+
+ // Remove a single newline if it already exists in the message to keep
+ // the behavior of logrus text_formatter the same as the stdlib log package
+ entry.Message = strings.TrimSuffix(entry.Message, "\n")
+
+ caller := ""
+ if entry.HasCaller() {
+ funcVal := fmt.Sprintf("%s()", entry.Caller.Function)
+ fileVal := fmt.Sprintf("%s:%d", entry.Caller.File, entry.Caller.Line)
+
+ if f.CallerPrettyfier != nil {
+ funcVal, fileVal = f.CallerPrettyfier(entry.Caller)
+ }
+
+ if fileVal == "" {
+ caller = funcVal
+ } else if funcVal == "" {
+ caller = fileVal
+ } else {
+ caller = fileVal + " " + funcVal
+ }
+ }
+
+ if f.DisableTimestamp {
+ fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m%s %-44s ", levelColor, levelText, caller, entry.Message)
+ } else if !f.FullTimestamp {
+ fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%04d]%s %-44s ", levelColor, levelText, int(entry.Time.Sub(baseTimestamp)/time.Second), caller, entry.Message)
+ } else {
+ fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%s]%s %-44s ", levelColor, levelText, entry.Time.Format(timestampFormat), caller, entry.Message)
+ }
+ for _, k := range keys {
+ v := data[k]
+ fmt.Fprintf(b, " \x1b[%dm%s\x1b[0m=", levelColor, k)
+ f.appendValue(b, v)
+ }
+}
+
+func (f *TextFormatter) needsQuoting(text string) bool {
+ if f.QuoteEmptyFields && len(text) == 0 {
+ return true
+ }
+ for _, ch := range text {
+ if !((ch >= 'a' && ch <= 'z') ||
+ (ch >= 'A' && ch <= 'Z') ||
+ (ch >= '0' && ch <= '9') ||
+ ch == '-' || ch == '.' || ch == '_' || ch == '/' || ch == '@' || ch == '^' || ch == '+') {
+ return true
+ }
+ }
+ return false
+}
+
+func (f *TextFormatter) appendKeyValue(b *bytes.Buffer, key string, value interface{}) {
+ if b.Len() > 0 {
+ b.WriteByte(' ')
+ }
+ b.WriteString(key)
+ b.WriteByte('=')
+ f.appendValue(b, value)
+}
+
+func (f *TextFormatter) appendValue(b *bytes.Buffer, value interface{}) {
+ stringVal, ok := value.(string)
+ if !ok {
+ stringVal = fmt.Sprint(value)
+ }
+
+ if !f.needsQuoting(stringVal) {
+ b.WriteString(stringVal)
+ } else {
+ b.WriteString(fmt.Sprintf("%q", stringVal))
+ }
+}
diff --git a/vendor/github.com/Sirupsen/logrus/writer.go b/vendor/github.com/sirupsen/logrus/writer.go
similarity index 96%
rename from vendor/github.com/Sirupsen/logrus/writer.go
rename to vendor/github.com/sirupsen/logrus/writer.go
index 7bdebedc60b..9e1f7513597 100644
--- a/vendor/github.com/Sirupsen/logrus/writer.go
+++ b/vendor/github.com/sirupsen/logrus/writer.go
@@ -24,6 +24,8 @@ func (entry *Entry) WriterLevel(level Level) *io.PipeWriter {
var printFunc func(args ...interface{})
switch level {
+ case TraceLevel:
+ printFunc = entry.Trace
case DebugLevel:
printFunc = entry.Debug
case InfoLevel:
diff --git a/vendor/github.com/valyala/fasthttp/.travis.yml b/vendor/github.com/valyala/fasthttp/.travis.yml
index 76cb8c17df8..b262c6941d3 100644
--- a/vendor/github.com/valyala/fasthttp/.travis.yml
+++ b/vendor/github.com/valyala/fasthttp/.travis.yml
@@ -1,37 +1,55 @@
language: go
+# Docker is required for fuzzit regression tests
+services:
+ - docker
+
+dist: bionic
+
+os:
+ - linux
+ - osx
go:
- tip
- - 1.12
+ - 1.13.x
+ - 1.12.x
- 1.11.x
- 1.10.x
- 1.9.x
-os:
- - linux
- - osx
-
matrix:
allow_failures:
- tip
fast_finish: true
+env:
+ global:
+ secure: "v/F0oI9zE9mcpEp4AVdHzSSHbe5ZFtH6B0i/BiUXKdQRQ10+JMPDOFRJQti7yxjMwltyd/QSFmR50Fl108sQYpo4xdlEXMHp2Y6OAN6crrp6PuHbLYgDWu3df/cH7/BqDyIq1uX8KZEeQssnygYN8hN4tpJCUg+NIb40Lm57Zsodt8DVjjyDWQQFDL7soNyAwGwQIqEyJsn+NUieXWEB1Qnt0xUtPIReuLlrwXR8wC1nLEjG9yz4ftDHHQdhVbO2b+xGWyaJ7QB5ixztaQP8Jnny6kSW9j6zEhJVuzdZ6d3xz23ibCbzSXBHdIUEI9u6ifQj8BYXr8fFS0FB3++IxgAYSs3ybZ+qEwuAxSBBm6YNW+3FrfDknVwTQscjKqnXPisjUqaRC9b31hke0tXzBq1488hE+wxMXeDM4LwWT5IMEO2gz0WGQXxmdVit72DIjCZxJkf1TvZZ0YH7Y//6wJTYYP9xulsy4gqu8CuFdWiF3fiGc3p5DTIS75nJ/Yy76Sa1pRPASKCujfLxtHE6Mt0XKvSolIXklYIzBkjN6vn80N6JIrqtqlimBGPW/Ec6+dwbmRe2AcOKRl4y7pZsGYhJhqdue1mucUYO/e2QeBZJGkqqG+zF5AW0v8x29BHvMwViAonc8o9eelkJ8khYzc/Qeq05pZnR/N/Pqfc+68k="
+
before_install:
- go get -t -v ./...
- # - go get -v golang.org/x/tools/cmd/goimports
-
-script:
- # TODO(@kirilldanshin)
- # - test -z "$(goimports -d $(find . -type f -name '*.go' -not -path "./vendor/*"))"
- # build test for supported platforms
- - GOOS=linux go build
- - GOOS=darwin go build
- - GOOS=freebsd go build
- - GOOS=windows go build
- - GOARCH=386 go build
-
- # run tests on a standard platform
- - go test -v ./...
-
- # run tests with the race detector as well
- - go test -race -v ./...
+
+jobs:
+ include:
+ - stage: test
+ script:
+ # build test for supported platforms
+ - GOOS=linux go build
+ - GOOS=darwin go build
+ - GOOS=freebsd go build
+ - GOOS=windows go build
+ - GOARCH=386 go build
+
+ # run tests on a standard platform
+ - go test -v ./...
+
+ # run tests with the race detector as well
+ - go test -race -v ./...
+ - stage: fuzzit.dev
+ os:
+ - linux
+ go:
+ - 1.13
+ script:
+ - if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then ./fuzzit.sh fuzzing; fi
+ - if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then ./fuzzit.sh local-regression; fi
diff --git a/vendor/github.com/valyala/fasthttp/README.md b/vendor/github.com/valyala/fasthttp/README.md
index 5fcb6398d05..7a128136956 100644
--- a/vendor/github.com/valyala/fasthttp/README.md
+++ b/vendor/github.com/valyala/fasthttp/README.md
@@ -1,15 +1,14 @@
-[![Build Status](https://travis-ci.org/valyala/fasthttp.svg)](https://travis-ci.org/valyala/fasthttp)
-[![GoDoc](https://godoc.org/github.com/valyala/fasthttp?status.svg)](http://godoc.org/github.com/valyala/fasthttp)
-[![Go Report](https://goreportcard.com/badge/github.com/valyala/fasthttp)](https://goreportcard.com/report/github.com/valyala/fasthttp)
+# fasthttp [![Build Status](https://travis-ci.org/valyala/fasthttp.svg)](https://travis-ci.org/valyala/fasthttp) [![GoDoc](https://godoc.org/github.com/valyala/fasthttp?status.svg)](http://godoc.org/github.com/valyala/fasthttp) [![fuzzit](https://app.fuzzit.dev/badge?org_id=fasthttp&branch=master)](https://fuzzit.dev) [![Go Report](https://goreportcard.com/badge/github.com/valyala/fasthttp)](https://goreportcard.com/report/github.com/valyala/fasthttp)
+
+![FastHTTP – Fastest and reliable HTTP implementation in Go](https://github.com/fasthttp/docs-assets/raw/master/banner@0.5.png)
-# fasthttp
Fast HTTP implementation for Go.
Currently fasthttp is successfully used by [VertaMedia](https://vertamedia.com/)
in a production serving up to 200K rps from more than 1.5M concurrent keep-alive
connections per physical server.
-[TechEmpower Benchmark round 12 results](https://www.techempower.com/benchmarks/#section=data-r12&hw=peak&test=plaintext)
+[TechEmpower Benchmark round 18 results](https://www.techempower.com/benchmarks/#section=data-r18&hw=ph&test=plaintext)
[Server Benchmarks](#http-server-performance-comparison-with-nethttp)
@@ -399,7 +398,7 @@ instead of [html/template](https://golang.org/pkg/html/template/).
* Pin each server instance to a separate CPU core using [taskset](http://linux.die.net/man/1/taskset).
* Ensure the interrupts of multiqueue network card are evenly distributed between CPU cores.
See [this article](https://blog.cloudflare.com/how-to-achieve-low-latency/) for details.
-* Use Go 1.6 as it provides some considerable performance improvements.
+* Use Go 1.13 as it provides some considerable performance improvements.
# Fasthttp best practices
@@ -492,8 +491,9 @@ uintBuf := fasthttp.AppendUint(nil, 1234)
* [websocket](https://github.com/fasthttp/websocket) - Gorilla-based
websocket implementation for fasthttp.
* [fasthttpsession](https://github.com/phachon/fasthttpsession) - a fast and powerful session package for fasthttp servers.
- * [atreugo](https://github.com/savsgio/atreugo) - Micro-framework to make simple the use of routing and middlewares.
+ * [atreugo](https://github.com/savsgio/atreugo) - High performance and extensible micro web framework with zero memory allocations in hot paths.
* [kratgo](https://github.com/savsgio/kratgo) - Simple, lightweight and ultra-fast HTTP Cache to speed up your websites.
+ * [kit-plugins](https://github.com/wencan/kit-plugins/tree/master/transport/fasthttp) - go-kit transport implementation for fasthttp.
# FAQ
diff --git a/vendor/github.com/valyala/fasthttp/bytesconv.go b/vendor/github.com/valyala/fasthttp/bytesconv.go
index 8c0e1545d18..2766794694e 100644
--- a/vendor/github.com/valyala/fasthttp/bytesconv.go
+++ b/vendor/github.com/valyala/fasthttp/bytesconv.go
@@ -1,3 +1,5 @@
+//go:generate go run bytesconv_table_gen.go
+
package fasthttp
import (
@@ -296,7 +298,7 @@ func writeHexInt(w *bufio.Writer, n int) error {
buf := v.([]byte)
i := len(buf) - 1
for {
- buf[i] = int2hexbyte(n & 0xf)
+ buf[i] = lowerhex[n&0xf]
n >>= 4
if n == 0 {
break
@@ -308,61 +310,10 @@ func writeHexInt(w *bufio.Writer, n int) error {
return err
}
-func int2hexbyte(n int) byte {
- if n < 10 {
- return '0' + byte(n)
- }
- return 'a' + byte(n) - 10
-}
-
-func hexCharUpper(c byte) byte {
- if c < 10 {
- return '0' + c
- }
- return c - 10 + 'A'
-}
-
-var hex2intTable = func() []byte {
- b := make([]byte, 256)
- for i := 0; i < 256; i++ {
- c := byte(16)
- if i >= '0' && i <= '9' {
- c = byte(i) - '0'
- } else if i >= 'a' && i <= 'f' {
- c = byte(i) - 'a' + 10
- } else if i >= 'A' && i <= 'F' {
- c = byte(i) - 'A' + 10
- }
- b[i] = c
- }
- return b
-}()
-
-const toLower = 'a' - 'A'
-
-var toLowerTable = func() [256]byte {
- var a [256]byte
- for i := 0; i < 256; i++ {
- c := byte(i)
- if c >= 'A' && c <= 'Z' {
- c += toLower
- }
- a[i] = c
- }
- return a
-}()
-
-var toUpperTable = func() [256]byte {
- var a [256]byte
- for i := 0; i < 256; i++ {
- c := byte(i)
- if c >= 'a' && c <= 'z' {
- c -= toLower
- }
- a[i] = c
- }
- return a
-}()
+const (
+ upperhex = "0123456789ABCDEF"
+ lowerhex = "0123456789abcdef"
+)
func lowercaseBytes(b []byte) {
for i := 0; i < len(b); i++ {
@@ -384,14 +335,13 @@ func b2s(b []byte) string {
//
// Note it may break if string and/or slice header will change
// in the future go versions.
-func s2b(s string) []byte {
- sh := (*reflect.StringHeader)(unsafe.Pointer(&s))
- bh := reflect.SliceHeader{
- Data: sh.Data,
- Len: sh.Len,
- Cap: sh.Len,
- }
- return *(*[]byte)(unsafe.Pointer(&bh))
+func s2b(s string) (b []byte) {
+ bh := (*reflect.SliceHeader)(unsafe.Pointer(&b))
+ sh := *(*reflect.StringHeader)(unsafe.Pointer(&s))
+ bh.Data = sh.Data
+ bh.Len = sh.Len
+ bh.Cap = sh.Len
+ return b
}
// AppendUnquotedArg appends url-decoded src to dst and returns appended dst.
@@ -404,33 +354,29 @@ func AppendUnquotedArg(dst, src []byte) []byte {
// AppendQuotedArg appends url-encoded src to dst and returns appended dst.
func AppendQuotedArg(dst, src []byte) []byte {
for _, c := range src {
- // See http://www.w3.org/TR/html5/forms.html#form-submission-algorithm
- if c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c >= '0' && c <= '9' ||
- c == '*' || c == '-' || c == '.' || c == '_' {
+ switch {
+ case c == ' ':
+ dst = append(dst, '+')
+ case quotedArgShouldEscapeTable[int(c)] != 0:
+ dst = append(dst, '%', upperhex[c>>4], upperhex[c&0xf])
+ default:
dst = append(dst, c)
- } else {
- dst = append(dst, '%', hexCharUpper(c>>4), hexCharUpper(c&15))
}
}
return dst
}
func appendQuotedPath(dst, src []byte) []byte {
+ // Fix issue in https://github.com/golang/go/issues/11202
+ if len(src) == 1 && src[0] == '*' {
+ return append(dst, '*')
+ }
+
for _, c := range src {
- // From the spec: http://tools.ietf.org/html/rfc3986#section-3.3
- // an path can contain zero or more of pchar that is defined as follows:
- // pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
- // pct-encoded = "%" HEXDIG HEXDIG
- // unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
- // sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
- // / "*" / "+" / "," / ";" / "="
- if c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c >= '0' && c <= '9' ||
- c == '-' || c == '.' || c == '_' || c == '~' || c == '!' || c == '$' ||
- c == '&' || c == '\'' || c == '(' || c == ')' || c == '*' || c == '+' ||
- c == ',' || c == ';' || c == '=' || c == ':' || c == '@' || c == '/' {
- dst = append(dst, c)
+ if quotedPathShouldEscapeTable[int(c)] != 0 {
+ dst = append(dst, '%', upperhex[c>>4], upperhex[c&15])
} else {
- dst = append(dst, '%', hexCharUpper(c>>4), hexCharUpper(c&15))
+ dst = append(dst, c)
}
}
return dst
diff --git a/vendor/github.com/valyala/fasthttp/bytesconv_table.go b/vendor/github.com/valyala/fasthttp/bytesconv_table.go
new file mode 100644
index 00000000000..78a12a30b1b
--- /dev/null
+++ b/vendor/github.com/valyala/fasthttp/bytesconv_table.go
@@ -0,0 +1,10 @@
+package fasthttp
+
+// Code generated by go run bytesconv_table_gen.go; DO NOT EDIT.
+// See bytesconv_table_gen.go for more information about these tables.
+
+const hex2intTable = "\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x00\x01\x02\x03\x04\x05\x06\a\b\t\x10\x10\x10\x10\x10\x10\x10\n\v\f\r\x0e\x0f\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\n\v\f\r\x0e\x0f\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10"
+const toLowerTable = "\x00\x01\x02\x03\x04\x05\x06\a\b\t\n\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@abcdefghijklmnopqrstuvwxyz[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\u007f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"
+const toUpperTable = "\x00\x01\x02\x03\x04\x05\x06\a\b\t\n\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`ABCDEFGHIJKLMNOPQRSTUVWXYZ{|}~\u007f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"
+const quotedArgShouldEscapeTable = "\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x01\x01\x01\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x01\x01\x01\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x01\x01\x00\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01"
+const quotedPathShouldEscapeTable = "\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x00\x01\x00\x01\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x01\x01\x01\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x01\x01\x00\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01"
diff --git a/vendor/github.com/valyala/fasthttp/client.go b/vendor/github.com/valyala/fasthttp/client.go
index cd55961f921..4bde3f0f75b 100644
--- a/vendor/github.com/valyala/fasthttp/client.go
+++ b/vendor/github.com/valyala/fasthttp/client.go
@@ -8,6 +8,7 @@ import (
"fmt"
"io"
"net"
+ "strconv"
"strings"
"sync"
"sync/atomic"
@@ -245,6 +246,15 @@ type Client struct {
// * cONTENT-lenGTH -> Content-Length
DisableHeaderNamesNormalizing bool
+ // Path values are sent as-is without normalization
+ //
+ // Disabled path normalization may be useful for proxying incoming requests
+ // to servers that are expecting paths to be forwarded as-is.
+ //
+ // By default path values are normalized, i.e.
+ // extra slashes are removed, special characters are encoded.
+ DisablePathNormalizing bool
+
mLock sync.Mutex
m map[string]*HostClient
ms map[string]*HostClient
@@ -422,6 +432,7 @@ func (c *Client) Do(req *Request, resp *Response) error {
WriteTimeout: c.WriteTimeout,
MaxResponseBodySize: c.MaxResponseBodySize,
DisableHeaderNamesNormalizing: c.DisableHeaderNamesNormalizing,
+ DisablePathNormalizing: c.DisablePathNormalizing,
}
m[string(host)] = hc
if len(m) == 1 {
@@ -613,6 +624,15 @@ type HostClient struct {
// * cONTENT-lenGTH -> Content-Length
DisableHeaderNamesNormalizing bool
+ // Path values are sent as-is without normalization
+ //
+ // Disabled path normalization may be useful for proxying incoming requests
+ // to servers that are expecting paths to be forwarded as-is.
+ //
+ // By default path values are normalized, i.e.
+ // extra slashes are removed, special characters are encoded.
+ DisablePathNormalizing bool
+
clientName atomic.Value
lastUseTime uint32
@@ -825,11 +845,7 @@ func doRequestFollowRedirects(req *Request, dst []byte, url string, c clientDoer
break
}
statusCode = resp.Header.StatusCode()
- if statusCode != StatusMovedPermanently &&
- statusCode != StatusFound &&
- statusCode != StatusSeeOther &&
- statusCode != StatusTemporaryRedirect &&
- statusCode != StatusPermanentRedirect {
+ if !StatusCodeIsRedirect(statusCode) {
break
}
@@ -863,6 +879,15 @@ func getRedirectURL(baseURL string, location []byte) string {
return redirectURL
}
+// StatusCodeIsRedirect returns true if the status code indicates a redirect.
+func StatusCodeIsRedirect(statusCode int) bool {
+ return statusCode == StatusMovedPermanently ||
+ statusCode == StatusFound ||
+ statusCode == StatusSeeOther ||
+ statusCode == StatusTemporaryRedirect ||
+ statusCode == StatusPermanentRedirect
+}
+
var (
requestPool sync.Pool
responsePool sync.Pool
@@ -1142,7 +1167,15 @@ func (c *HostClient) doNonNilReqResp(req *Request, resp *Response) (bool, error)
// Free up resources occupied by response before sending the request,
// so the GC may reclaim these resources (e.g. response body).
+
+ // backing up SkipBody in case it was set explicitly
+ customSkipBody := resp.SkipBody
resp.Reset()
+ resp.SkipBody = customSkipBody
+
+ if c.DisablePathNormalizing {
+ req.URI().DisablePathNormalizing = true
+ }
// If we detected a redirect to another schema
if req.schemaUpdate {
@@ -1209,7 +1242,7 @@ func (c *HostClient) doNonNilReqResp(req *Request, resp *Response) (bool, error)
}
}
- if !req.Header.IsGet() && req.Header.IsHead() {
+ if customSkipBody || !req.Header.IsGet() && req.Header.IsHead() {
resp.SkipBody = true
}
if c.DisableHeaderNamesNormalizing {
@@ -1537,7 +1570,7 @@ func (c *HostClient) dialHostHard() (conn net.Conn, err error) {
for n > 0 {
addr := c.nextAddr()
tlsConfig := c.cachedTLSConfig(addr)
- conn, err = dialAddr(addr, c.Dial, c.DialDualStack, c.IsTLS, tlsConfig)
+ conn, err = dialAddr(addr, c.Dial, c.DialDualStack, c.IsTLS, tlsConfig, c.WriteTimeout)
if err == nil {
return conn, nil
}
@@ -1568,7 +1601,43 @@ func (c *HostClient) cachedTLSConfig(addr string) *tls.Config {
return cfg
}
-func dialAddr(addr string, dial DialFunc, dialDualStack, isTLS bool, tlsConfig *tls.Config) (net.Conn, error) {
+var ErrTLSHandshakeTimeout = errors.New("tls handshake timed out")
+
+var timeoutErrorChPool sync.Pool
+
+func tlsClientHandshake(rawConn net.Conn, tlsConfig *tls.Config, timeout time.Duration) (net.Conn, error) {
+ tc := AcquireTimer(timeout)
+ defer ReleaseTimer(tc)
+
+ var ch chan error
+ chv := timeoutErrorChPool.Get()
+ if chv == nil {
+ chv = make(chan error)
+ }
+ ch = chv.(chan error)
+ defer timeoutErrorChPool.Put(chv)
+
+ conn := tls.Client(rawConn, tlsConfig)
+
+ go func() {
+ ch <- conn.Handshake()
+ }()
+
+ select {
+ case <-tc.C:
+ rawConn.Close()
+ <-ch
+ return nil, ErrTLSHandshakeTimeout
+ case err := <-ch:
+ if err != nil {
+ rawConn.Close()
+ return nil, err
+ }
+ return conn, nil
+ }
+}
+
+func dialAddr(addr string, dial DialFunc, dialDualStack, isTLS bool, tlsConfig *tls.Config, timeout time.Duration) (net.Conn, error) {
if dial == nil {
if dialDualStack {
dial = DialDualStack
@@ -1585,7 +1654,10 @@ func dialAddr(addr string, dial DialFunc, dialDualStack, isTLS bool, tlsConfig *
panic("BUG: DialFunc returned (nil, nil)")
}
if isTLS {
- conn = tls.Client(conn, tlsConfig)
+ if timeout == 0 {
+ return tls.Client(conn, tlsConfig), nil
+ }
+ return tlsClientHandshake(conn, tlsConfig, timeout)
}
return conn, nil
}
@@ -1614,7 +1686,7 @@ func addMissingPort(addr string, isTLS bool) string {
if isTLS {
port = 443
}
- return fmt.Sprintf("%s:%d", addr, port)
+ return net.JoinHostPort(addr, strconv.Itoa(port))
}
// PipelineClient pipelines requests over a limited set of concurrent
@@ -1992,7 +2064,7 @@ func (c *pipelineConnClient) init() {
func (c *pipelineConnClient) worker() error {
tlsConfig := c.cachedTLSConfig()
- conn, err := dialAddr(c.Addr, c.Dial, c.DialDualStack, c.IsTLS, tlsConfig)
+ conn, err := dialAddr(c.Addr, c.Dial, c.DialDualStack, c.IsTLS, tlsConfig, c.WriteTimeout)
if err != nil {
return err
}
diff --git a/vendor/github.com/valyala/fasthttp/fasthttputil/inmemory_listener.go b/vendor/github.com/valyala/fasthttp/fasthttputil/inmemory_listener.go
index 1b1a5f3666c..fd41fc8a099 100644
--- a/vendor/github.com/valyala/fasthttp/fasthttputil/inmemory_listener.go
+++ b/vendor/github.com/valyala/fasthttp/fasthttputil/inmemory_listener.go
@@ -1,11 +1,13 @@
package fasthttputil
import (
- "fmt"
+ "errors"
"net"
"sync"
)
+var ErrInmemoryListenerClosed = errors.New("InmemoryListener is already closed: use of closed network connection")
+
// InmemoryListener provides in-memory dialer<->net.Listener implementation.
//
// It may be used either for fast in-process client<->server communications
@@ -36,7 +38,7 @@ func NewInmemoryListener() *InmemoryListener {
func (ln *InmemoryListener) Accept() (net.Conn, error) {
c, ok := <-ln.conns
if !ok {
- return nil, fmt.Errorf("InmemoryListener is already closed: use of closed network connection")
+ return nil, ErrInmemoryListenerClosed
}
close(c.accepted)
return c.conn, nil
@@ -51,7 +53,7 @@ func (ln *InmemoryListener) Close() error {
close(ln.conns)
ln.closed = true
} else {
- err = fmt.Errorf("InmemoryListener is already closed")
+ err = ErrInmemoryListenerClosed
}
ln.lock.Unlock()
return err
@@ -88,7 +90,7 @@ func (ln *InmemoryListener) Dial() (net.Conn, error) {
ln.lock.Unlock()
if cConn == nil {
- return nil, fmt.Errorf("InmemoryListener is already closed")
+ return nil, ErrInmemoryListenerClosed
}
return cConn, nil
}
diff --git a/vendor/github.com/valyala/fasthttp/fasthttputil/pipeconns.go b/vendor/github.com/valyala/fasthttp/fasthttputil/pipeconns.go
index aa92b6ff8dd..3e45c842fe8 100644
--- a/vendor/github.com/valyala/fasthttp/fasthttputil/pipeconns.go
+++ b/vendor/github.com/valyala/fasthttp/fasthttputil/pipeconns.go
@@ -9,6 +9,8 @@ import (
)
// NewPipeConns returns new bi-directional connection pipe.
+//
+// PipeConns is NOT safe for concurrent use by multiple goroutines!
func NewPipeConns() *PipeConns {
ch1 := make(chan *byteBuffer, 4)
ch2 := make(chan *byteBuffer, 4)
@@ -38,6 +40,7 @@ func NewPipeConns() *PipeConns {
// calling Read in order to unblock each Write call.
// * It supports read and write deadlines.
//
+// PipeConns is NOT safe for concurrent use by multiple goroutines!
type PipeConns struct {
c1 pipeConn
c2 pipeConn
@@ -87,6 +90,8 @@ type pipeConn struct {
readDeadlineCh <-chan time.Time
writeDeadlineCh <-chan time.Time
+
+ readDeadlineChLock sync.Mutex
}
func (c *pipeConn) Write(p []byte) (int, error) {
@@ -158,10 +163,15 @@ func (c *pipeConn) readNextByteBuffer(mayBlock bool) error {
if !mayBlock {
return errWouldBlock
}
+ c.readDeadlineChLock.Lock()
+ readDeadlineCh := c.readDeadlineCh
+ c.readDeadlineChLock.Unlock()
select {
case c.b = <-c.rCh:
- case <-c.readDeadlineCh:
+ case <-readDeadlineCh:
+ c.readDeadlineChLock.Lock()
c.readDeadlineCh = closedDeadlineCh
+ c.readDeadlineChLock.Unlock()
// rCh may contain data when deadline is reached.
// Read the data before returning ErrTimeout.
select {
@@ -214,7 +224,10 @@ func (c *pipeConn) SetReadDeadline(deadline time.Time) error {
if c.readDeadlineTimer == nil {
c.readDeadlineTimer = time.NewTimer(time.Hour)
}
- c.readDeadlineCh = updateTimer(c.readDeadlineTimer, deadline)
+ readDeadlineCh := updateTimer(c.readDeadlineTimer, deadline)
+ c.readDeadlineChLock.Lock()
+ c.readDeadlineCh = readDeadlineCh
+ c.readDeadlineChLock.Unlock()
return nil
}
diff --git a/vendor/github.com/valyala/fasthttp/fuzzit.sh b/vendor/github.com/valyala/fasthttp/fuzzit.sh
new file mode 100644
index 00000000000..37f83db686d
--- /dev/null
+++ b/vendor/github.com/valyala/fasthttp/fuzzit.sh
@@ -0,0 +1,22 @@
+#!/bin/bash
+
+set -xe
+
+## go-fuzz doesn't support modules for now, so ensure we do everything
+## in the old style GOPATH way
+export GO111MODULE="off"
+
+# We need to download these dependencies again after we set GO111MODULE="off"
+go get -t -v ./...
+
+go get github.com/dvyukov/go-fuzz/go-fuzz github.com/dvyukov/go-fuzz/go-fuzz-build
+
+wget -q -O fuzzitbin https://github.com/fuzzitdev/fuzzit/releases/download/v2.4.52/fuzzit_Linux_x86_64
+chmod a+x fuzzitbin
+
+for w in request response cookie url; do
+ go-fuzz-build -libfuzzer -o fasthttp_$w.a ./fuzzit/$w/
+ clang -fsanitize=fuzzer fasthttp_$w.a -o fasthttp_$w
+
+ ./fuzzitbin create job --type $1 fasthttp/$w fasthttp_$w
+done
diff --git a/vendor/github.com/valyala/fasthttp/go.mod b/vendor/github.com/valyala/fasthttp/go.mod
index 8434ca1ec85..3e1c929b58f 100644
--- a/vendor/github.com/valyala/fasthttp/go.mod
+++ b/vendor/github.com/valyala/fasthttp/go.mod
@@ -1,9 +1,11 @@
module github.com/valyala/fasthttp
+go 1.11
+
require (
- github.com/klauspost/compress v1.4.0
- github.com/klauspost/cpuid v0.0.0-20180405133222-e7e905edc00e // indirect
+ github.com/klauspost/compress v1.8.2
+ github.com/klauspost/cpuid v1.2.1 // indirect
github.com/valyala/bytebufferpool v1.0.0
github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a
- golang.org/x/net v0.0.0-20180911220305-26e67e76b6c3
+ golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297
)
diff --git a/vendor/github.com/valyala/fasthttp/go.sum b/vendor/github.com/valyala/fasthttp/go.sum
index 93f38fcf2ea..52407f3f41f 100644
--- a/vendor/github.com/valyala/fasthttp/go.sum
+++ b/vendor/github.com/valyala/fasthttp/go.sum
@@ -1,10 +1,13 @@
-github.com/klauspost/compress v1.4.0 h1:8nsMz3tWa9SWWPL60G1V6CUsf4lLjWLTNEtibhe8gh8=
-github.com/klauspost/compress v1.4.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
-github.com/klauspost/cpuid v0.0.0-20180405133222-e7e905edc00e h1:+lIPJOWl+jSiJOc70QXJ07+2eg2Jy2EC7Mi11BWujeM=
-github.com/klauspost/cpuid v0.0.0-20180405133222-e7e905edc00e/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
+github.com/klauspost/compress v1.8.2 h1:Bx0qjetmNjdFXASH02NSAREKpiaDwkO1DRZ3dV2KCcs=
+github.com/klauspost/compress v1.8.2/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
+github.com/klauspost/cpuid v1.2.1 h1:vJi+O/nMdFt0vqm8NZBI6wzALWdA2X+egi0ogNyrC/w=
+github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a h1:0R4NLDRDZX6JcmhJgXi5E4b8Wg84ihbmUKp/GvSPEzc=
github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio=
-golang.org/x/net v0.0.0-20180911220305-26e67e76b6c3 h1:czFLhve3vsQetD6JOJ8NZZvGQIXlnN3/yXxbT6/awxI=
-golang.org/x/net v0.0.0-20180911220305-26e67e76b6c3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297 h1:k7pJ2yAPLPgbskkFdhRCsA77k2fySZ1zf2zCjvQCiIM=
+golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
diff --git a/vendor/github.com/valyala/fasthttp/header.go b/vendor/github.com/valyala/fasthttp/header.go
index 9f9c012c12f..399b486ffad 100644
--- a/vendor/github.com/valyala/fasthttp/header.go
+++ b/vendor/github.com/valyala/fasthttp/header.go
@@ -1395,9 +1395,10 @@ func (h *RequestHeader) tryRead(r *bufio.Reader, n int) error {
}
}
+ // n == 1 on the first read for the request.
if n == 1 {
// We didn't read a single byte.
- return errNothingRead
+ return errNothingRead{err}
}
return fmt.Errorf("error when reading request headers: %s", err)
@@ -1498,7 +1499,10 @@ func (h *ResponseHeader) AppendBytes(dst []byte) []byte {
// or if it is explicitly set.
// See https://github.com/valyala/fasthttp/issues/28 .
if h.ContentLength() != 0 || len(h.contentType) > 0 {
- dst = appendHeaderLine(dst, strContentType, h.ContentType())
+ contentType := h.ContentType()
+ if len(contentType) > 0 {
+ dst = appendHeaderLine(dst, strContentType, contentType)
+ }
}
if len(h.contentLengthBytes) > 0 {
@@ -1889,6 +1893,13 @@ func (h *RequestHeader) parseHeaders(buf []byte) (int, error) {
var err error
for s.next() {
if len(s.key) > 0 {
+ // Spaces between the header key and colon are not allowed.
+ // See RFC 7230, Section 3.2.4.
+ if bytes.IndexByte(s.key, ' ') != -1 || bytes.IndexByte(s.key, '\t') != -1 {
+ err = fmt.Errorf("invalid header key %q", s.key)
+ continue
+ }
+
switch s.key[0] | 0x20 {
case 'h':
if caseInsensitiveCompare(s.key, strHost) {
@@ -1907,7 +1918,11 @@ func (h *RequestHeader) parseHeaders(buf []byte) (int, error) {
}
if caseInsensitiveCompare(s.key, strContentLength) {
if h.contentLength != -1 {
- if h.contentLength, err = parseContentLength(s.value); err != nil {
+ var nerr error
+ if h.contentLength, nerr = parseContentLength(s.value); nerr != nil {
+ if err == nil {
+ err = nerr
+ }
h.contentLength = -2
} else {
h.contentLengthBytes = append(h.contentLengthBytes[:0], s.value...)
@@ -1936,9 +1951,12 @@ func (h *RequestHeader) parseHeaders(buf []byte) (int, error) {
}
h.h = appendArgBytes(h.h, s.key, s.value, argsHasValue)
}
- if s.err != nil {
+ if s.err != nil && err == nil {
+ err = s.err
+ }
+ if err != nil {
h.connectionClose = true
- return 0, s.err
+ return 0, err
}
if h.contentLength < 0 {
@@ -2172,9 +2190,12 @@ func AppendNormalizedHeaderKeyBytes(dst, key []byte) []byte {
var (
errNeedMore = errors.New("need more data: cannot find trailing lf")
errSmallBuffer = errors.New("small read buffer. Increase ReadBufferSize")
- errNothingRead = errors.New("read timeout with nothing read")
)
+type errNothingRead struct {
+ error
+}
+
// ErrSmallBuffer is returned when the provided buffer size is too small
// for reading request and/or response headers.
//
diff --git a/vendor/github.com/valyala/fasthttp/http.go b/vendor/github.com/valyala/fasthttp/http.go
index ce30f8c977f..9a55805ed99 100644
--- a/vendor/github.com/valyala/fasthttp/http.go
+++ b/vendor/github.com/valyala/fasthttp/http.go
@@ -3,6 +3,7 @@ package fasthttp
import (
"bufio"
"bytes"
+ "encoding/base64"
"errors"
"fmt"
"io"
@@ -703,7 +704,7 @@ func (req *Request) parseURI() {
}
req.parsedURI = true
- req.uri.parseQuick(req.Header.RequestURI(), &req.Header, req.isTLS)
+ req.uri.parse(req.Header.Host(), req.Header.RequestURI(), req.isTLS)
}
// PostArgs returns POST arguments.
@@ -829,7 +830,7 @@ func readMultipartForm(r io.Reader, boundary string, size, maxInMemoryFileSize i
// in multipart/form-data requests.
if size <= 0 {
- panic(fmt.Sprintf("BUG: form size must be greater than 0. Given %d", size))
+ return nil, fmt.Errorf("form size must be greater than 0. Given %d", size)
}
lr := io.LimitReader(r, int64(size))
mr := multipart.NewReader(lr, boundary)
@@ -926,6 +927,10 @@ var ErrGetOnly = errors.New("non-GET request received")
// io.EOF is returned if r is closed before reading the first header byte.
func (req *Request) ReadLimitBody(r *bufio.Reader, maxBodySize int) error {
req.resetSkipHeader()
+ if err := req.Header.Read(r); err != nil {
+ return err
+ }
+
return req.readLimitBody(r, maxBodySize, false)
}
@@ -933,10 +938,6 @@ func (req *Request) readLimitBody(r *bufio.Reader, maxBodySize int, getOnly bool
// Do not reset the request here - the caller must reset it before
// calling this method.
- err := req.Header.Read(r)
- if err != nil {
- return err
- }
if getOnly && !req.Header.IsGet() {
return ErrGetOnly
}
@@ -1148,6 +1149,25 @@ func (req *Request) Write(w *bufio.Writer) error {
}
req.Header.SetHostBytes(host)
req.Header.SetRequestURIBytes(uri.RequestURI())
+
+ if len(uri.username) > 0 {
+ // RequestHeader.SetBytesKV only uses RequestHeader.bufKV.key
+ // So we are free to use RequestHeader.bufKV.value as a scratch pad for
+ // the base64 encoding.
+ nl := len(uri.username) + len(uri.password) + 1
+ nb := nl + len(strBasicSpace)
+ tl := nb + base64.StdEncoding.EncodedLen(nl)
+ if tl > cap(req.Header.bufKV.value) {
+ req.Header.bufKV.value = make([]byte, 0, tl)
+ }
+ buf := req.Header.bufKV.value[:0]
+ buf = append(buf, uri.username...)
+ buf = append(buf, strColon...)
+ buf = append(buf, uri.password...)
+ buf = append(buf, strBasicSpace...)
+ base64.StdEncoding.Encode(buf[nb:tl], buf[:nl])
+ req.Header.SetBytesKV(strAuthorization, buf[nl:tl])
+ }
}
if req.bodyStream != nil {
diff --git a/vendor/github.com/valyala/fasthttp/lbclient.go b/vendor/github.com/valyala/fasthttp/lbclient.go
index 12418b6b6fa..932ce977824 100644
--- a/vendor/github.com/valyala/fasthttp/lbclient.go
+++ b/vendor/github.com/valyala/fasthttp/lbclient.go
@@ -17,7 +17,7 @@ type BalancingClient interface {
//
// It has the following features:
//
-// - Balances load among available clients using 'least loaded' + 'round robin'
+// - Balances load among available clients using 'least loaded' + 'least total'
// hybrid technique.
// - Dynamically decreases load on unhealthy clients.
//
@@ -49,10 +49,6 @@ type LBClient struct {
cs []*lbClient
- // nextIdx is for spreading requests among equally loaded clients
- // in a round-robin fashion.
- nextIdx uint32
-
once sync.Once
}
@@ -93,42 +89,23 @@ func (cc *LBClient) init() {
healthCheck: cc.HealthCheck,
})
}
-
- // Randomize nextIdx in order to prevent initial servers'
- // hammering from a cluster of identical LBClients.
- cc.nextIdx = uint32(time.Now().UnixNano())
}
func (cc *LBClient) get() *lbClient {
cc.once.Do(cc.init)
cs := cc.cs
- idx := atomic.AddUint32(&cc.nextIdx, 1)
- idx %= uint32(len(cs))
- minC := cs[idx]
+ minC := cs[0]
minN := minC.PendingRequests()
- if minN == 0 {
- return minC
- }
- for _, c := range cs[idx+1:] {
+ minT := atomic.LoadUint64(&minC.total)
+ for _, c := range cs[1:] {
n := c.PendingRequests()
- if n == 0 {
- return c
- }
- if n < minN {
- minC = c
- minN = n
- }
- }
- for _, c := range cs[:idx] {
- n := c.PendingRequests()
- if n == 0 {
- return c
- }
- if n < minN {
+ t := atomic.LoadUint64(&c.total)
+ if n < minN || (n == minN && t < minT) {
minC = c
minN = n
+ minT = t
}
}
return minC
@@ -138,6 +115,9 @@ type lbClient struct {
c BalancingClient
healthCheck func(req *Request, resp *Response, err error) bool
penalty uint32
+
+ // total amount of requests handled.
+ total uint64
}
func (c *lbClient) DoDeadline(req *Request, resp *Response, deadline time.Time) error {
@@ -146,6 +126,8 @@ func (c *lbClient) DoDeadline(req *Request, resp *Response, deadline time.Time)
// Penalize the client returning error, so the next requests
// are routed to another clients.
time.AfterFunc(penaltyDuration, c.decPenalty)
+ } else {
+ atomic.AddUint64(&c.total, 1)
}
return err
}
diff --git a/vendor/github.com/valyala/fasthttp/server.go b/vendor/github.com/valyala/fasthttp/server.go
index 9d14599283c..b501431bf83 100644
--- a/vendor/github.com/valyala/fasthttp/server.go
+++ b/vendor/github.com/valyala/fasthttp/server.go
@@ -17,7 +17,7 @@ import (
"time"
)
-var errNoCertOrKeyProvided = errors.New("Cert or key has not provided")
+var errNoCertOrKeyProvided = errors.New("cert or key has not provided")
var (
// ErrAlreadyServing is returned when calling Serve on a Server
@@ -167,6 +167,11 @@ type Server struct {
// * ErrBrokenChunks
ErrorHandler func(ctx *RequestCtx, err error)
+ // HeaderReceived is called after receiving the header
+ //
+ // non zero RequestConfig field values will overwrite the default configs
+ HeaderReceived func(header *RequestHeader) RequestConfig
+
// Server name for sending in response headers.
//
// Default server name is used if left blank.
@@ -371,10 +376,10 @@ type Server struct {
// msg to the client if there are more than Server.Concurrency concurrent
// handlers h are running at the moment.
func TimeoutHandler(h RequestHandler, timeout time.Duration, msg string) RequestHandler {
- return TimeoutWithCodeHandler(h,timeout,msg, StatusRequestTimeout)
+ return TimeoutWithCodeHandler(h, timeout, msg, StatusRequestTimeout)
}
-// TimeoutWithCodeHandler creates RequestHandler, which returns an error with
+// TimeoutWithCodeHandler creates RequestHandler, which returns an error with
// the given msg and status code to the client if h didn't return during
// the given duration.
//
@@ -415,6 +420,21 @@ func TimeoutWithCodeHandler(h RequestHandler, timeout time.Duration, msg string,
}
}
+//RequestConfig configure the per request deadline and body limits
+type RequestConfig struct {
+ // ReadTimeout is the maximum duration for reading the entire
+ // request body.
+ // a zero value means that default values will be honored
+ ReadTimeout time.Duration
+ // WriteTimeout is the maximum duration before timing out
+ // writes of the response.
+ // a zero value means that default values will be honored
+ WriteTimeout time.Duration
+ // Maximum request body size.
+ // a zero value means that default values will be honored
+ MaxRequestBodySize int
+}
+
// CompressHandler returns RequestHandler that transparently compresses
// response body generated by h if the request contains 'gzip' or 'deflate'
// 'Accept-Encoding' header.
@@ -1834,6 +1854,7 @@ func (s *Server) serveConn(c net.Conn) error {
if maxRequestBodySize <= 0 {
maxRequestBodySize = DefaultMaxRequestBodySize
}
+ writeTimeout := s.WriteTimeout
ctx := s.acquireCtx(c)
ctx.connTime = connTime
@@ -1876,7 +1897,9 @@ func (s *Server) serveConn(c net.Conn) error {
if len(b) == 0 {
// If reading from a keep-alive connection returns nothing it means
// the connection was closed (either timeout or from the other side).
- err = errNothingRead
+ if err != io.EOF {
+ err = errNothingRead{err}
+ }
}
}
} else {
@@ -1894,17 +1917,35 @@ func (s *Server) serveConn(c net.Conn) error {
panic(fmt.Sprintf("BUG: error in SetReadDeadline(%s): %s", s.ReadTimeout, err))
}
}
-
if s.DisableHeaderNamesNormalizing {
ctx.Request.Header.DisableNormalizing()
ctx.Response.Header.DisableNormalizing()
}
- // reading Headers and Body
- err = ctx.Request.readLimitBody(br, maxRequestBodySize, s.GetOnly)
+ // reading Headers
+ if err = ctx.Request.Header.Read(br); err == nil {
+ if onHdrRecv := s.HeaderReceived; onHdrRecv != nil {
+ reqConf := onHdrRecv(&ctx.Request.Header)
+ if reqConf.ReadTimeout > 0 {
+ deadline := time.Now().Add(reqConf.ReadTimeout)
+ if err := c.SetReadDeadline(deadline); err != nil {
+ panic(fmt.Sprintf("BUG: error in SetReadDeadline(%s): %s", deadline, err))
+ }
+ }
+ if reqConf.MaxRequestBodySize > 0 {
+ maxRequestBodySize = reqConf.MaxRequestBodySize
+ }
+ if reqConf.WriteTimeout > 0 {
+ writeTimeout = reqConf.WriteTimeout
+ }
+ }
+ //read body
+ err = ctx.Request.readLimitBody(br, maxRequestBodySize, s.GetOnly)
+ }
if err == nil {
// If we read any bytes off the wire, we're active.
s.setState(c, StateActive)
}
+
if (s.ReduceMemoryUsage && br.Buffered() == 0) || err != nil {
releaseReader(s, br)
br = nil
@@ -1914,14 +1955,20 @@ func (s *Server) serveConn(c net.Conn) error {
if err != nil {
if err == io.EOF {
err = nil
- } else if connRequestNum > 1 && err == errNothingRead {
- // This is not the first request and we haven't read a single byte
- // of a new request yet. This means it's just a keep-alive connection
- // closing down either because the remote closed it or because
- // or a read timeout on our side. Either way just close the connection
- // and don't return any error response.
- err = nil
- } else {
+ } else if nr, ok := err.(errNothingRead); ok {
+ if connRequestNum > 1 {
+ // This is not the first request and we haven't read a single byte
+ // of a new request yet. This means it's just a keep-alive connection
+ // closing down either because the remote closed it or because
+ // or a read timeout on our side. Either way just close the connection
+ // and don't return any error response.
+ err = nil
+ } else {
+ err = nr.error
+ }
+ }
+
+ if err != nil {
bw = s.writeErrorResponse(bw, ctx, serverName, err)
}
break
@@ -1995,8 +2042,8 @@ func (s *Server) serveConn(c net.Conn) error {
ctx.SetConnectionClose()
}
- if s.WriteTimeout > 0 {
- if err := c.SetWriteDeadline(time.Now().Add(s.WriteTimeout)); err != nil {
+ if writeTimeout > 0 {
+ if err := c.SetWriteDeadline(time.Now().Add(writeTimeout)); err != nil {
panic(fmt.Sprintf("BUG: error in SetWriteDeadline(%s): %s", s.WriteTimeout, err))
}
}
diff --git a/vendor/github.com/valyala/fasthttp/strings.go b/vendor/github.com/valyala/fasthttp/strings.go
index f654f958a0c..12f1926308d 100644
--- a/vendor/github.com/valyala/fasthttp/strings.go
+++ b/vendor/github.com/valyala/fasthttp/strings.go
@@ -16,9 +16,11 @@ var (
strHTTP = []byte("http")
strHTTPS = []byte("https")
strHTTP11 = []byte("HTTP/1.1")
+ strColon = []byte(":")
strColonSlashSlash = []byte("://")
strColonSpace = []byte(": ")
strGMT = []byte("GMT")
+ strAt = []byte("@")
strResponseContinue = []byte("HTTP/1.1 100 Continue\r\n\r\n")
@@ -52,6 +54,7 @@ var (
strAcceptRanges = []byte(HeaderAcceptRanges)
strRange = []byte(HeaderRange)
strContentRange = []byte(HeaderContentRange)
+ strAuthorization = []byte(HeaderAuthorization)
strCookieExpires = []byte("expires")
strCookieDomain = []byte("domain")
@@ -78,4 +81,5 @@ var (
strBytes = []byte("bytes")
strTextSlash = []byte("text/")
strApplicationSlash = []byte("application/")
+ strBasicSpace = []byte("Basic ")
)
diff --git a/vendor/github.com/valyala/fasthttp/uri.go b/vendor/github.com/valyala/fasthttp/uri.go
index d536f5934b1..1b784164884 100644
--- a/vendor/github.com/valyala/fasthttp/uri.go
+++ b/vendor/github.com/valyala/fasthttp/uri.go
@@ -48,10 +48,20 @@ type URI struct {
queryArgs Args
parsedQueryArgs bool
+ // Path values are sent as-is without normalization
+ //
+ // Disabled path normalization may be useful for proxying incoming requests
+ // to servers that are expecting paths to be forwarded as-is.
+ //
+ // By default path values are normalized, i.e.
+ // extra slashes are removed, special characters are encoded.
+ DisablePathNormalizing bool
+
fullURI []byte
requestURI []byte
- h *RequestHeader
+ username []byte
+ password []byte
}
// CopyTo copies uri contents to dst.
@@ -63,13 +73,15 @@ func (u *URI) CopyTo(dst *URI) {
dst.queryString = append(dst.queryString[:0], u.queryString...)
dst.hash = append(dst.hash[:0], u.hash...)
dst.host = append(dst.host[:0], u.host...)
+ dst.username = append(dst.username[:0], u.username...)
+ dst.password = append(dst.password[:0], u.password...)
u.queryArgs.CopyTo(&dst.queryArgs)
dst.parsedQueryArgs = u.parsedQueryArgs
+ dst.DisablePathNormalizing = u.DisablePathNormalizing
// fullURI and requestURI shouldn't be copied, since they are created
// from scratch on each FullURI() and RequestURI() call.
- dst.h = u.h
}
// Hash returns URI hash, i.e. qwe of http://aaa.com/foo/bar?baz=123#qwe .
@@ -89,6 +101,36 @@ func (u *URI) SetHashBytes(hash []byte) {
u.hash = append(u.hash[:0], hash...)
}
+// Username returns URI username
+func (u *URI) Username() []byte {
+ return u.username
+}
+
+// SetUsername sets URI username.
+func (u *URI) SetUsername(username string) {
+ u.username = append(u.username[:0], username...)
+}
+
+// SetUsernameBytes sets URI username.
+func (u *URI) SetUsernameBytes(username []byte) {
+ u.username = append(u.username[:0], username...)
+}
+
+// Password returns URI password
+func (u *URI) Password() []byte {
+ return u.password
+}
+
+// SetPassword sets URI password.
+func (u *URI) SetPassword(password string) {
+ u.password = append(u.password[:0], password...)
+}
+
+// SetPasswordBytes sets URI password.
+func (u *URI) SetPasswordBytes(password []byte) {
+ u.password = append(u.password[:0], password...)
+}
+
// QueryString returns URI query string,
// i.e. baz=123 of http://aaa.com/foo/bar?baz=123#qwe .
//
@@ -174,29 +216,25 @@ func (u *URI) Reset() {
u.path = u.path[:0]
u.queryString = u.queryString[:0]
u.hash = u.hash[:0]
+ u.username = u.username[:0]
+ u.password = u.password[:0]
u.host = u.host[:0]
u.queryArgs.Reset()
u.parsedQueryArgs = false
+ u.DisablePathNormalizing = false
// There is no need in u.fullURI = u.fullURI[:0], since full uri
// is calculated on each call to FullURI().
// There is no need in u.requestURI = u.requestURI[:0], since requestURI
// is calculated on each call to RequestURI().
-
- u.h = nil
}
// Host returns host part, i.e. aaa.com of http://aaa.com/foo/bar?baz=123#qwe .
//
// Host is always lowercased.
func (u *URI) Host() []byte {
- if len(u.host) == 0 && u.h != nil {
- u.host = append(u.host[:0], u.h.Host()...)
- lowercaseBytes(u.host)
- u.h = nil
- }
return u.host
}
@@ -219,23 +257,32 @@ func (u *URI) SetHostBytes(host []byte) {
//
// uri may contain e.g. RequestURI without scheme and host if host is non-empty.
func (u *URI) Parse(host, uri []byte) {
- u.parse(host, uri, nil)
+ u.parse(host, uri, false)
}
-func (u *URI) parseQuick(uri []byte, h *RequestHeader, isTLS bool) {
- u.parse(nil, uri, h)
- if isTLS {
- u.scheme = append(u.scheme[:0], strHTTPS...)
- }
-}
-
-func (u *URI) parse(host, uri []byte, h *RequestHeader) {
+func (u *URI) parse(host, uri []byte, isTLS bool) {
u.Reset()
- u.h = h
scheme, host, uri := splitHostURI(host, uri)
u.scheme = append(u.scheme, scheme...)
lowercaseBytes(u.scheme)
+ if isTLS {
+ u.scheme = append(u.scheme[:0], strHTTPS...)
+ }
+
+ if n := bytes.Index(host, strAt); n >= 0 {
+ auth := host[:n]
+ host = host[n+1:]
+
+ if n := bytes.Index(auth, strColon); n >= 0 {
+ u.username = auth[:n]
+ u.password = auth[n+1:]
+ } else {
+ u.username = auth
+ u.password = auth[:0] // Make sure it's not nil
+ }
+ }
+
u.host = append(u.host, host...)
lowercaseBytes(u.host)
@@ -336,7 +383,12 @@ func normalizePath(dst, src []byte) []byte {
// RequestURI returns RequestURI - i.e. URI without Scheme and Host.
func (u *URI) RequestURI() []byte {
- dst := appendQuotedPath(u.requestURI[:0], u.Path())
+ var dst []byte
+ if u.DisablePathNormalizing {
+ dst = append(u.requestURI[:0], u.PathOriginal()...)
+ } else {
+ dst = appendQuotedPath(u.requestURI[:0], u.Path())
+ }
if u.queryArgs.Len() > 0 {
dst = append(dst, '?')
dst = u.queryArgs.AppendBytes(dst)
diff --git a/vendor/github.com/valyala/fasthttp/workerpool.go b/vendor/github.com/valyala/fasthttp/workerpool.go
index bfd297c31eb..9b1987e8ddf 100644
--- a/vendor/github.com/valyala/fasthttp/workerpool.go
+++ b/vendor/github.com/valyala/fasthttp/workerpool.go
@@ -50,6 +50,11 @@ func (wp *workerPool) Start() {
}
wp.stopCh = make(chan struct{})
stopCh := wp.stopCh
+ wp.workerChanPool.New = func() interface{} {
+ return &workerChan{
+ ch: make(chan net.Conn, workerChanCap),
+ }
+ }
go func() {
var scratch []*workerChan
for {
@@ -76,8 +81,8 @@ func (wp *workerPool) Stop() {
// serving the connection and noticing wp.mustStop = true.
wp.lock.Lock()
ready := wp.ready
- for i, ch := range ready {
- ch.ch <- nil
+ for i := range ready {
+ ready[i].ch <- nil
ready[i] = nil
}
wp.ready = ready[:0]
@@ -97,23 +102,34 @@ func (wp *workerPool) clean(scratch *[]*workerChan) {
// Clean least recently used workers if they didn't serve connections
// for more than maxIdleWorkerDuration.
- currentTime := time.Now()
+ criticalTime := time.Now().Add(-maxIdleWorkerDuration)
wp.lock.Lock()
ready := wp.ready
n := len(ready)
- i := 0
- for i < n && currentTime.Sub(ready[i].lastUseTime) > maxIdleWorkerDuration {
- i++
- }
- *scratch = append((*scratch)[:0], ready[:i]...)
- if i > 0 {
- m := copy(ready, ready[i:])
- for i = m; i < n; i++ {
- ready[i] = nil
+
+ // Use binary-search algorithm to find out the index of the least recently worker which can be cleaned up.
+ l, r, mid := 0, n-1, 0
+ for l <= r {
+ mid = (l + r) / 2
+ if criticalTime.After(wp.ready[mid].lastUseTime) {
+ l = mid + 1
+ } else {
+ r = mid - 1
}
- wp.ready = ready[:m]
}
+ i := r
+ if i == -1 {
+ wp.lock.Unlock()
+ return
+ }
+
+ *scratch = append((*scratch)[:0], ready[:i+1]...)
+ m := copy(ready, ready[i+1:])
+ for i = m; i < n; i++ {
+ ready[i] = nil
+ }
+ wp.ready = ready[:m]
wp.lock.Unlock()
// Notify obsolete workers to stop.
@@ -121,8 +137,8 @@ func (wp *workerPool) clean(scratch *[]*workerChan) {
// may be blocking and may consume a lot of time if many workers
// are located on non-local CPUs.
tmp := *scratch
- for i, ch := range tmp {
- ch.ch <- nil
+ for i := range tmp {
+ tmp[i].ch <- nil
tmp[i] = nil
}
}
@@ -174,11 +190,6 @@ func (wp *workerPool) getCh() *workerChan {
return nil
}
vch := wp.workerChanPool.Get()
- if vch == nil {
- vch = &workerChan{
- ch: make(chan net.Conn, workerChanCap),
- }
- }
ch = vch.(*workerChan)
go func() {
wp.workerFunc(ch)
@@ -214,6 +225,7 @@ func (wp *workerPool) workerFunc(ch *workerChan) {
if wp.LogAllErrors || !(strings.Contains(errStr, "broken pipe") ||
strings.Contains(errStr, "reset by peer") ||
strings.Contains(errStr, "request headers: small read buffer") ||
+ strings.Contains(errStr, "unexpected EOF") ||
strings.Contains(errStr, "i/o timeout")) {
wp.Logger.Printf("error when serving connection %q<->%q: %s", c.LocalAddr(), c.RemoteAddr(), err)
}
@@ -221,7 +233,7 @@ func (wp *workerPool) workerFunc(ch *workerChan) {
if err == errHijacked {
wp.connState(c, StateHijacked)
} else {
- c.Close()
+ _ = c.Close()
wp.connState(c, StateClosed)
}
c = nil
diff --git a/vendor/modules.txt b/vendor/modules.txt
index 29a42f28686..92f04c882f0 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -89,8 +89,6 @@ github.com/PuerkitoBio/purell
github.com/PuerkitoBio/urlesc
# github.com/Shopify/sarama v1.23.1
github.com/Shopify/sarama
-# github.com/Sirupsen/logrus v1.0.6
-github.com/Sirupsen/logrus
# github.com/a8m/documentdb v1.2.0
github.com/a8m/documentdb
# github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da
@@ -171,7 +169,7 @@ github.com/coreos/etcd/raft/raftpb
github.com/coreos/go-systemd/journal
# github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f
github.com/coreos/pkg/capnslog
-# github.com/dapr/components-contrib v0.0.0-20191128051247-c4bd2a47eae0
+# github.com/dapr/components-contrib v0.0.0-20191217174314-701f12e52994
github.com/dapr/components-contrib/bindings
github.com/dapr/components-contrib/bindings/aws/dynamodb
github.com/dapr/components-contrib/bindings/aws/s3
@@ -193,6 +191,8 @@ github.com/dapr/components-contrib/exporters
github.com/dapr/components-contrib/exporters/native
github.com/dapr/components-contrib/exporters/stringexporter
github.com/dapr/components-contrib/exporters/zipkin
+github.com/dapr/components-contrib/middleware
+github.com/dapr/components-contrib/middleware/http/oauth2
github.com/dapr/components-contrib/pubsub
github.com/dapr/components-contrib/pubsub/azure/servicebus
github.com/dapr/components-contrib/pubsub/nats
@@ -237,6 +237,8 @@ github.com/emicklei/go-restful
github.com/emicklei/go-restful/log
# github.com/evanphx/json-patch v4.2.0+incompatible
github.com/evanphx/json-patch
+# github.com/fasthttp-contrib/sessions v0.0.0-20160905201309-74f6ac73d5d5
+github.com/fasthttp-contrib/sessions
# github.com/ghodss/yaml v1.0.0
github.com/ghodss/yaml
# github.com/go-openapi/jsonpointer v0.19.3
@@ -361,12 +363,14 @@ github.com/jstemmer/go-junit-report/formatter
github.com/jstemmer/go-junit-report/parser
# github.com/kelseyhightower/envconfig v1.4.0
github.com/kelseyhightower/envconfig
-# github.com/klauspost/compress v1.5.0
+# github.com/klauspost/compress v1.8.2
github.com/klauspost/compress/flate
github.com/klauspost/compress/gzip
github.com/klauspost/compress/zlib
# github.com/klauspost/cpuid v1.2.1
github.com/klauspost/cpuid
+# github.com/konsorten/go-windows-terminal-sequences v1.0.2
+github.com/konsorten/go-windows-terminal-sequences
# github.com/kubernetes-client/go v0.0.0-20190625181339-cd8e39e789c7
github.com/kubernetes-client/go/kubernetes/client
github.com/kubernetes-client/go/kubernetes/config
@@ -421,6 +425,8 @@ github.com/rcrowley/go-metrics
github.com/samuel/go-zookeeper/zk
# github.com/satori/go.uuid v1.2.0
github.com/satori/go.uuid
+# github.com/sirupsen/logrus v1.4.2
+github.com/sirupsen/logrus
# github.com/spf13/pflag v1.0.3
github.com/spf13/pflag
# github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271
@@ -433,7 +439,7 @@ github.com/stretchr/testify/mock
github.com/stretchr/testify/require
# github.com/valyala/bytebufferpool v1.0.0
github.com/valyala/bytebufferpool
-# github.com/valyala/fasthttp v1.4.0
+# github.com/valyala/fasthttp v1.6.0
github.com/valyala/fasthttp
github.com/valyala/fasthttp/fasthttpadaptor
github.com/valyala/fasthttp/fasthttputil