├── .drone.yml ├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── cmd └── relayd │ └── relayd.go ├── go.mod ├── go.sum ├── pkg ├── client │ ├── client.go │ └── ws_client.go ├── cond │ ├── cond.go │ └── cond_test.go ├── forward │ ├── forward.go │ └── forward_test.go ├── gopool │ └── go_pool.go ├── logger │ └── logger.go ├── retryablehttp │ ├── client.go │ └── client_test.go └── types │ ├── request_log.go │ ├── request_log_easyjson.go │ ├── requeststatus_jsonenums.go │ ├── version_info.go │ ├── ws_types.go │ └── ws_types_easyjson.go ├── tests └── forward │ ├── forward_test.go │ ├── helper.go │ └── receiver.go ├── vendor ├── github.com │ ├── alecthomas │ │ ├── template │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ ├── doc.go │ │ │ ├── exec.go │ │ │ ├── funcs.go │ │ │ ├── helper.go │ │ │ ├── parse │ │ │ │ ├── lex.go │ │ │ │ ├── node.go │ │ │ │ └── parse.go │ │ │ └── template.go │ │ └── units │ │ │ ├── COPYING │ │ │ ├── README.md │ │ │ ├── bytes.go │ │ │ ├── doc.go │ │ │ ├── si.go │ │ │ └── util.go │ ├── davecgh │ │ └── go-spew │ │ │ ├── LICENSE │ │ │ └── spew │ │ │ ├── bypass.go │ │ │ ├── bypasssafe.go │ │ │ ├── common.go │ │ │ ├── config.go │ │ │ ├── doc.go │ │ │ ├── dump.go │ │ │ ├── format.go │ │ │ └── spew.go │ ├── gorilla │ │ └── websocket │ │ │ ├── .gitignore │ │ │ ├── .travis.yml │ │ │ ├── AUTHORS │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ ├── client.go │ │ │ ├── client_clone.go │ │ │ ├── client_clone_legacy.go │ │ │ ├── compression.go │ │ │ ├── conn.go │ │ │ ├── conn_write.go │ │ │ ├── conn_write_legacy.go │ │ │ ├── doc.go │ │ │ ├── json.go │ │ │ ├── mask.go │ │ │ ├── mask_safe.go │ │ │ ├── prepared.go │ │ │ ├── proxy.go │ │ │ ├── server.go │ │ │ ├── trace.go │ │ │ ├── trace_17.go │ │ │ ├── util.go │ │ │ └── x_net_proxy.go │ ├── hashicorp │ │ └── go-cleanhttp │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ ├── cleanhttp.go │ │ │ ├── doc.go │ │ │ ├── go.mod │ │ │ └── handlers.go │ ├── heptio │ │ └── workgroup │ │ │ ├── .gitignore │ │ │ ├── .travis.yml │ │ │ ├── CODE_OF_CONDUCT.md │ │ │ ├── CONTRIBUTING.md │ │ │ ├── LICENSE │ │ │ ├── Makefile │ │ │ ├── README.md │ │ │ └── group.go │ ├── mailru │ │ └── easyjson │ │ │ ├── .gitignore │ │ │ ├── .travis.yml │ │ │ ├── LICENSE │ │ │ ├── Makefile │ │ │ ├── README.md │ │ │ ├── buffer │ │ │ └── pool.go │ │ │ ├── helpers.go │ │ │ ├── jlexer │ │ │ ├── bytestostr.go │ │ │ ├── bytestostr_nounsafe.go │ │ │ ├── error.go │ │ │ └── lexer.go │ │ │ ├── jwriter │ │ │ └── writer.go │ │ │ └── raw.go │ ├── pmezard │ │ └── go-difflib │ │ │ ├── LICENSE │ │ │ └── difflib │ │ │ └── difflib.go │ ├── stretchr │ │ └── testify │ │ │ ├── LICENSE │ │ │ └── assert │ │ │ ├── assertion_format.go │ │ │ ├── assertion_format.go.tmpl │ │ │ ├── assertion_forward.go │ │ │ ├── assertion_forward.go.tmpl │ │ │ ├── assertion_order.go │ │ │ ├── assertions.go │ │ │ ├── doc.go │ │ │ ├── errors.go │ │ │ ├── forward_assertions.go │ │ │ └── http_assertions.go │ └── urfave │ │ └── negroni │ │ ├── .gitignore │ │ ├── .travis.yml │ │ ├── CHANGELOG.md │ │ ├── LICENSE │ │ ├── README.md │ │ ├── doc.go │ │ ├── logger.go │ │ ├── negroni.go │ │ ├── recovery.go │ │ ├── response_writer.go │ │ ├── response_writer_pusher.go │ │ └── static.go ├── go.uber.org │ ├── atomic │ │ ├── .gitignore │ │ ├── .travis.yml │ │ ├── LICENSE.txt │ │ ├── Makefile │ │ ├── README.md │ │ ├── atomic.go │ │ ├── glide.lock │ │ ├── glide.yaml │ │ └── string.go │ ├── multierr │ │ ├── .codecov.yml │ │ ├── .gitignore │ │ ├── .travis.yml │ │ ├── CHANGELOG.md │ │ ├── LICENSE.txt │ │ ├── Makefile │ │ ├── README.md │ │ ├── error.go │ │ ├── glide.lock │ │ └── glide.yaml │ └── zap │ │ ├── .codecov.yml │ │ ├── .gitignore │ │ ├── .readme.tmpl │ │ ├── .travis.yml │ │ ├── CHANGELOG.md │ │ ├── CODE_OF_CONDUCT.md │ │ ├── CONTRIBUTING.md │ │ ├── FAQ.md │ │ ├── LICENSE.txt │ │ ├── Makefile │ │ ├── README.md │ │ ├── array.go │ │ ├── buffer │ │ ├── buffer.go │ │ └── pool.go │ │ ├── check_license.sh │ │ ├── config.go │ │ ├── doc.go │ │ ├── encoder.go │ │ ├── error.go │ │ ├── field.go │ │ ├── flag.go │ │ ├── glide.lock │ │ ├── glide.yaml │ │ ├── global.go │ │ ├── http_handler.go │ │ ├── internal │ │ ├── bufferpool │ │ │ └── bufferpool.go │ │ ├── color │ │ │ └── color.go │ │ └── exit │ │ │ └── exit.go │ │ ├── level.go │ │ ├── logger.go │ │ ├── options.go │ │ ├── sink.go │ │ ├── stacktrace.go │ │ ├── sugar.go │ │ ├── time.go │ │ ├── writer.go │ │ └── zapcore │ │ ├── console_encoder.go │ │ ├── core.go │ │ ├── doc.go │ │ ├── encoder.go │ │ ├── entry.go │ │ ├── error.go │ │ ├── field.go │ │ ├── hook.go │ │ ├── json_encoder.go │ │ ├── level.go │ │ ├── level_strings.go │ │ ├── marshaler.go │ │ ├── memory_encoder.go │ │ ├── sampler.go │ │ ├── tee.go │ │ └── write_syncer.go ├── gopkg.in │ ├── alecthomas │ │ └── kingpin.v2 │ │ │ ├── .travis.yml │ │ │ ├── COPYING │ │ │ ├── README.md │ │ │ ├── actions.go │ │ │ ├── app.go │ │ │ ├── args.go │ │ │ ├── cmd.go │ │ │ ├── completions.go │ │ │ ├── doc.go │ │ │ ├── envar.go │ │ │ ├── flags.go │ │ │ ├── global.go │ │ │ ├── guesswidth.go │ │ │ ├── guesswidth_unix.go │ │ │ ├── model.go │ │ │ ├── parser.go │ │ │ ├── parsers.go │ │ │ ├── templates.go │ │ │ ├── usage.go │ │ │ ├── values.go │ │ │ ├── values.json │ │ │ └── values_generated.go │ └── yaml.v2 │ │ ├── .travis.yml │ │ ├── LICENSE │ │ ├── LICENSE.libyaml │ │ ├── NOTICE │ │ ├── README.md │ │ ├── apic.go │ │ ├── decode.go │ │ ├── emitterc.go │ │ ├── encode.go │ │ ├── go.mod │ │ ├── parserc.go │ │ ├── readerc.go │ │ ├── resolve.go │ │ ├── scannerc.go │ │ ├── sorter.go │ │ ├── writerc.go │ │ ├── yaml.go │ │ ├── yamlh.go │ │ └── yamlprivateh.go └── modules.txt └── version └── version.go /.drone.yml: -------------------------------------------------------------------------------- 1 | kind: pipeline 2 | name: default 3 | 4 | workspace: 5 | base: /go 6 | path: src/github.com/webhookrelay/relay-go 7 | 8 | steps: 9 | - name: build 10 | image: golang:1.14 11 | environment: 12 | GO111MODULE: off 13 | commands: 14 | - make install 15 | 16 | - name: test 17 | image: golang:1.14 18 | environment: 19 | GO111MODULE: off 20 | commands: 21 | - make test-pretty 22 | 23 | - name: e2e-test 24 | image: golang:1.14 25 | environment: 26 | GO111MODULE: off 27 | BUCKETS: 28 | from_secret: buckets 29 | INPUT_URL: 30 | from_secret: input_url 31 | RELAY_KEY: 32 | from_secret: relay_key 33 | RELAY_SECRET: 34 | from_secret: relay_secret 35 | commands: 36 | - make install 37 | - make e2e 38 | 39 | - name: slack 40 | image: plugins/slack 41 | settings: 42 | webhook: 43 | from_secret: slack_url 44 | channel: general 45 | username: drone 46 | icon_url: https://i.pinimg.com/originals/51/29/a4/5129a48ddad9e8408d2757dd10eb836f.jpg 47 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | creds.sh 2 | cmd/relayd/release -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | JOBDATE ?= $(shell date -u +%Y-%m-%dT%H%M%SZ) 2 | GIT_REVISION = $(shell git rev-parse --short HEAD) 3 | VERSION ?= $(shell git describe --tags --abbrev=0) 4 | 5 | LDFLAGS += -s -w 6 | LDFLAGS += -X github.com/webhookrelay/relay-go/version.Version=$(VERSION) 7 | LDFLAGS += -X github.com/webhookrelay/relay-go/version.Revision=$(GIT_REVISION) 8 | LDFLAGS += -X github.com/webhookrelay/relay-go/version.BuildDate=$(JOBDATE) 9 | 10 | install: 11 | cd cmd/relayd && go install -ldflags "$(LDFLAGS)" 12 | 13 | release: 14 | cd cmd/relayd && env GOARCH=amd64 GOOS=linux go build -ldflags "$(LDFLAGS)" -o release/relayd 15 | cd cmd/relayd && env GOARCH=amd64 GOOS=windows go build -ldflags "$(LDFLAGS)" -o release/relayd.exe 16 | 17 | test: 18 | go test -v -failfast `go list ./... | egrep -v /tests/` 19 | 20 | e2e: 21 | go get github.com/mfridman/tparse 22 | cd tests/forward && go test 23 | 24 | test-pretty: 25 | go get github.com/mfridman/tparse 26 | go test -json -v `go list ./... | egrep -v /tests/` -cover | tparse -all -smallscreen 27 | 28 | gen-json-types: 29 | go get -u github.com/mailru/easyjson/... 30 | easyjson -all pkg/types/ws_types.go 31 | easyjson -all pkg/types/request_log.go 32 | 33 | run: install 34 | relayd forward -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Go Relay 2 | 3 | [![Build Status](https://drone-kr.webrelay.io/api/badges/webhookrelay/relay-go/status.svg)](https://drone-kr.webrelay.io/webhookrelay/relay-go) 4 | 5 | Lightweight and Open Source Webhook Relay forwarding client. 6 | 7 | 8 | ## Installation 9 | 10 | This client requires Go 1.12 (earlier versions might work as well) to be installed ([install instructions](https://golang.org/doc/install)) on your system. 11 | 12 | 1. After the installation, find out the GOPATH using `go env`, and then setup a source folder there 13 | 14 | ```bash 15 | mkdir $GOPATH/src 16 | ``` 17 | 18 | 2. Clone relay-go project into your Go source directory: 19 | 20 | ```bash 21 | cd $GOPATH/src 22 | mkdir -p github.com/webhookrelay/ 23 | cd github.com/webhookrelay/ 24 | git clone https://github.com/webhookrelay/relay-go 25 | ``` 26 | 27 | 3. Finally, to install client application, run: 28 | 29 | ```bash 30 | cd relay-go 31 | make install 32 | ``` 33 | 34 | ## Compiling binaries for Linux and Windows 35 | 36 | To compile your binaries for Linux (64-bit) and Windows (64-bit): 37 | 38 | ```bash 39 | make release 40 | ``` 41 | 42 | Binaries will be available in the `cmd/relayd/release` directory. 43 | 44 | ## Forwarding webhooks 45 | 46 | As opposed to the [Webhook Relay CLI](https://webhookrelay.com/v1/installation/cli), this client will not auto-create buckets, inputs and destinations when `forward` command is used. It will simply connect to Webhook Relay [WebSocket server](https://webhookrelay.com/v1/guide/socket-server) and subscribe to an already created buckets. 47 | 48 | To start forwarding bucket **foo** webhooks, first set several environment variables: 49 | 50 | ```bash 51 | export RELAY_KEY=your-token-key 52 | export RELAY_SECRET=your-token-secret 53 | export BUCKETS=foo 54 | ``` 55 | 56 | Then: 57 | 58 | ```bash 59 | relayd forward 60 | ``` 61 | 62 | Alternatively, you can set these variables through command line flags: 63 | 64 | ```bash 65 | relayd --key your-token-key --secret your-token-secret forward --bucket foo 66 | ``` 67 | 68 | ## Test 69 | 70 | To run all tests: 71 | 72 | ``` 73 | make test 74 | ``` 75 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/webhookrelay/relay-go 2 | 3 | go 1.14 4 | 5 | require ( 6 | github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc // indirect 7 | github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf // indirect 8 | github.com/gorilla/websocket v1.4.0 9 | github.com/hashicorp/go-cleanhttp v0.5.1 10 | github.com/heptio/workgroup v0.8.0-beta.1 11 | github.com/mailru/easyjson v0.0.0-20190403194419-1ea4449da983 12 | github.com/pkg/errors v0.9.1 // indirect 13 | github.com/stretchr/testify v1.5.1 14 | github.com/urfave/negroni v1.0.0 15 | go.uber.org/atomic v1.2.0 // indirect 16 | go.uber.org/multierr v1.1.0 // indirect 17 | go.uber.org/zap v1.9.1 18 | gopkg.in/alecthomas/kingpin.v2 v2.2.6 19 | ) 20 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc h1:cAKDfWh5VpdgMhJosfJnn5/FoN2SRZ4p7fJNX58YPaU= 2 | github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= 3 | github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf h1:qet1QNfXsQxTZqLG4oE62mJzwPIB8+Tee4RNCL9ulrY= 4 | github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= 5 | github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= 6 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 7 | github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q= 8 | github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= 9 | github.com/hashicorp/go-cleanhttp v0.5.1 h1:dH3aiDG9Jvb5r5+bYHsikaOUIpcM0xvgMXVoDkXMzJM= 10 | github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= 11 | github.com/heptio/workgroup v0.8.0-beta.1 h1:7o1B3CsesQFRHFxWRWB19a6E3PfhIj2CdXLYdFhN2Yg= 12 | github.com/heptio/workgroup v0.8.0-beta.1/go.mod h1:IuHqolPhhQFt9b9b/qu8XpcadoQD3QCr4WjqrOleypc= 13 | github.com/mailru/easyjson v0.0.0-20190403194419-1ea4449da983 h1:wL11wNW7dhKIcRCHSm4sHKPWz0tt4mwBsVodG7+Xyqg= 14 | github.com/mailru/easyjson v0.0.0-20190403194419-1ea4449da983/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= 15 | github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= 16 | github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 17 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 18 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 19 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 20 | github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= 21 | github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= 22 | github.com/urfave/negroni v1.0.0 h1:kIimOitoypq34K7TG7DUaJ9kq/N4Ofuwi1sjz0KipXc= 23 | github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4= 24 | go.uber.org/atomic v1.2.0 h1:yVVGhClJ8Xi1y4TxhJZE6QFPrz76BrzhWA01n47mSFk= 25 | go.uber.org/atomic v1.2.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= 26 | go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI= 27 | go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= 28 | go.uber.org/zap v1.9.1 h1:XCJQEf3W6eZaVwhRBof6ImoYGJSITeKWsyeh3HFu/5o= 29 | go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= 30 | gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc= 31 | gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= 32 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= 33 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 34 | gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= 35 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 36 | -------------------------------------------------------------------------------- /pkg/client/client.go: -------------------------------------------------------------------------------- 1 | package client 2 | 3 | import ( 4 | "context" 5 | "net/http" 6 | "sync" 7 | 8 | "github.com/gorilla/websocket" 9 | "go.uber.org/zap" 10 | 11 | "github.com/webhookrelay/relay-go/pkg/cond" 12 | "github.com/webhookrelay/relay-go/pkg/forward" 13 | "github.com/webhookrelay/relay-go/pkg/gopool" 14 | "github.com/webhookrelay/relay-go/pkg/logger" 15 | "github.com/webhookrelay/relay-go/pkg/types" 16 | ) 17 | 18 | type WebhookRelayClient interface { 19 | // start webhook relay 20 | StartRelay(ctx context.Context, filter *Filter) error 21 | RelayReady() <-chan bool 22 | } 23 | 24 | var _ WebhookRelayClient = &DefaultClient{} 25 | 26 | // Filter - optional filter that can be passed to the server 27 | type Filter struct { 28 | Bucket, Destination string 29 | Buckets []string // multiple bucket filtering based on name or ID 30 | } 31 | 32 | // concurrency options 33 | var ( 34 | workers = 256 35 | queue = 1 36 | ) 37 | 38 | // Opts - client configuration 39 | type Opts struct { 40 | HTTPClient *http.Client 41 | AccessKey, AccessSecret string 42 | // Optional way to turn off TLS certificate validation 43 | InsecureSkipVerify bool 44 | Forwarder forward.Forwarder 45 | Debug bool 46 | Logger *zap.SugaredLogger 47 | // Websocket server address, defaults to 48 | // wss://my.webhookrelay.com/ 49 | ServerAddress string 50 | } 51 | 52 | // DefaultClient - default client that connects to webhookrelay service via gRPC protocol 53 | type DefaultClient struct { 54 | httpClient *http.Client 55 | forwarder forward.Forwarder 56 | wsConn *websocket.Conn 57 | wsHealthPing chan *types.Event 58 | opts *Opts 59 | filter *Filter 60 | readyCond *cond.Cond 61 | goPool *gopool.Pool 62 | readyMu *sync.Mutex 63 | logger *zap.SugaredLogger 64 | } 65 | 66 | // NewDefaultClient - create new default client with given options 67 | func NewDefaultClient(opts *Opts) *DefaultClient { 68 | if opts.Logger == nil { 69 | opts.Logger = logger.GetLoggerInstance(logger.DefaultLogLevel).Sugar() 70 | } 71 | 72 | if opts.HTTPClient == nil { 73 | opts.HTTPClient = http.DefaultClient 74 | } 75 | 76 | return &DefaultClient{ 77 | opts: opts, 78 | httpClient: opts.HTTPClient, 79 | logger: opts.Logger, 80 | forwarder: opts.Forwarder, 81 | goPool: gopool.NewPool(workers, queue, 1), 82 | readyCond: &cond.Cond{}, 83 | readyMu: &sync.Mutex{}, 84 | wsHealthPing: make(chan *types.Event), 85 | } 86 | } 87 | 88 | // StartRelay - starts relay agent 89 | func (c *DefaultClient) StartRelay(ctx context.Context, filter *Filter) error { 90 | c.filter = filter 91 | return c.startWebSocketRelay(ctx) 92 | } 93 | 94 | // RelayReady - relay notification channel, closed when relay is ready 95 | func (c *DefaultClient) RelayReady() <-chan bool { 96 | 97 | rCh := make(chan bool) 98 | 99 | cCh := make(chan int, 1) 100 | 101 | c.readyCond.Register(cCh, 0) 102 | go func() { 103 | <-cCh 104 | close(rCh) 105 | }() 106 | 107 | return rCh 108 | } 109 | -------------------------------------------------------------------------------- /pkg/cond/cond.go: -------------------------------------------------------------------------------- 1 | package cond 2 | 3 | import "sync" 4 | 5 | // Cond implements a condition variable, a rendezvous point for goroutines 6 | // waiting for or announcing the occurrence of an event. 7 | // 8 | // Unlike sync.Cond, Cond communicates with waiters via channels registered by 9 | // the waiters. This permits goroutines to wait on Cond events using select. 10 | type Cond struct { 11 | mu sync.Mutex 12 | waiters []chan int 13 | last int 14 | } 15 | 16 | // Register registers ch to receive a value when Notify is called. 17 | // The value of last is the count of the times Notify has been called on this Cond. 18 | // It functions of a sequence counter, if the value of last supplied to Register 19 | // is less than the Conds internal counter, then the caller has missed at least 20 | // one notification and will fire immediately. 21 | // 22 | // Sends by the broadcaster to ch must not block, therefor ch must have a capacity 23 | // of at least 1. 24 | func (c *Cond) Register(ch chan int, last int) { 25 | c.mu.Lock() 26 | defer c.mu.Unlock() 27 | 28 | if last < c.last { 29 | // notify this channel immediately 30 | ch <- c.last 31 | return 32 | } 33 | c.waiters = append(c.waiters, ch) 34 | } 35 | 36 | // Notify notifies all registered waiters that an event has ocurred. 37 | func (c *Cond) Notify() { 38 | c.mu.Lock() 39 | defer c.mu.Unlock() 40 | c.last++ 41 | 42 | for _, ch := range c.waiters { 43 | ch <- c.last 44 | } 45 | c.waiters = c.waiters[:0] 46 | } 47 | -------------------------------------------------------------------------------- /pkg/cond/cond_test.go: -------------------------------------------------------------------------------- 1 | package cond 2 | 3 | import "testing" 4 | 5 | func TestCondRegisterBeforeNotifyShouldNotBroadcast(t *testing.T) { 6 | var c Cond 7 | ch := make(chan int, 1) 8 | c.Register(ch, 0) 9 | select { 10 | case <-ch: 11 | t.Fatal("ch was notified before broadcast") 12 | default: 13 | } 14 | } 15 | 16 | func TestCondRegisterAfterNotifyShouldBroadcast(t *testing.T) { 17 | var c Cond 18 | ch := make(chan int, 1) 19 | c.Notify() 20 | c.Register(ch, 0) 21 | select { 22 | case v := <-ch: 23 | if v != 1 { 24 | t.Fatal("ch was notified with the wrong sequence number", v) 25 | } 26 | default: 27 | t.Fatal("ch was not notified on registration") 28 | } 29 | } 30 | 31 | func TestCondRegisterAfterNotifyWithCorrectSequenceShouldNotBroadcast(t *testing.T) { 32 | var c Cond 33 | ch := make(chan int, 1) 34 | c.Notify() 35 | c.Register(ch, 0) 36 | seq := <-ch 37 | 38 | c.Register(ch, seq) 39 | select { 40 | case v := <-ch: 41 | t.Fatal("ch was notified immediately with seq", v) 42 | default: 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /pkg/forward/forward.go: -------------------------------------------------------------------------------- 1 | package forward 2 | 3 | import ( 4 | "bytes" 5 | "crypto/tls" 6 | "fmt" 7 | "io/ioutil" 8 | "net/http" 9 | 10 | "github.com/webhookrelay/relay-go/pkg/retryablehttp" 11 | "github.com/webhookrelay/relay-go/pkg/types" 12 | "go.uber.org/zap" 13 | ) 14 | 15 | // Forwarder is responsible for receiving and processing incoming webhook events 16 | type Forwarder interface { 17 | Forward(wh types.Event) (*types.LogUpdateRequest, error) 18 | } 19 | 20 | var _ Forwarder = &DefaultForwarder{} 21 | 22 | // DefaultForwarder - default 'last mile' webhook Forwarder 23 | type DefaultForwarder struct { 24 | hClient *http.Client 25 | rClient *retryablehttp.Client 26 | 27 | logger *zap.SugaredLogger 28 | } 29 | 30 | // Opts - configuration 31 | type Opts struct { 32 | Retries int 33 | Insecure bool 34 | Logger *zap.SugaredLogger 35 | } 36 | 37 | // NewDefaultForwarder - create an instance of default Forwarder 38 | func NewDefaultForwarder(opts *Opts) *DefaultForwarder { 39 | 40 | httpClient := &http.Client{} 41 | 42 | if opts.Logger == nil { 43 | cfg := zap.NewProductionConfig() 44 | cfg.DisableCaller = true 45 | cfg.DisableStacktrace = true 46 | cfg.Encoding = "console" 47 | 48 | l, err := cfg.Build() 49 | if err != nil { 50 | panic("failed to initialise logger") 51 | } 52 | opts.Logger = l.Sugar() 53 | } 54 | 55 | client := retryablehttp.NewClient(opts.Logger) 56 | 57 | if opts.Insecure { 58 | tr := &http.Transport{ 59 | TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, 60 | } 61 | insecureClient := &http.Client{Transport: tr} 62 | client.HTTPClient = insecureClient 63 | httpClient = insecureClient 64 | } 65 | 66 | client.RetryMax = opts.Retries 67 | 68 | return &DefaultForwarder{rClient: client, hClient: httpClient, logger: opts.Logger} 69 | } 70 | 71 | // Forward - relaying incoming webhook to original destination 72 | func (r *DefaultForwarder) Forward(wh types.Event) (*types.LogUpdateRequest, error) { 73 | if wh.RawQuery != "" { 74 | wh.Meta.OutputDestination = wh.Meta.OutputDestination + "?" + wh.RawQuery 75 | } 76 | req, err := retryablehttp.NewRequest(wh.Method, wh.Meta.OutputDestination, bytes.NewReader([]byte(wh.Body))) 77 | if err != nil { 78 | return nil, err 79 | } 80 | 81 | var retries int 82 | var statusCode int 83 | 84 | req.Header = wh.Headers 85 | 86 | resp, err := r.rClient.Do(req) 87 | if resp != nil { 88 | retries = retryablehttp.GetRetries(resp) 89 | statusCode = resp.StatusCode 90 | 91 | } 92 | if resp.Body != nil { 93 | defer resp.Body.Close() 94 | } 95 | 96 | if err != nil { 97 | return &types.LogUpdateRequest{ 98 | ID: wh.Meta.ID, 99 | StatusCode: statusCode, 100 | Status: types.RequestStatusFromCode(statusCode), 101 | ResponseBody: []byte(fmt.Sprintf("request failed, HTTP client error: %s", err)), 102 | Retries: retries, 103 | }, nil 104 | } 105 | 106 | body, err := ioutil.ReadAll(resp.Body) 107 | if err != nil { 108 | return &types.LogUpdateRequest{ 109 | ID: wh.Meta.ID, 110 | StatusCode: statusCode, 111 | Status: types.RequestStatusFromCode(statusCode), 112 | ResponseBody: []byte(fmt.Sprintf("failed to read response body, error: %s", err)), 113 | Retries: retries, 114 | ResponseHeaders: resp.Header, 115 | }, nil 116 | } 117 | 118 | r.logger.Infow("webhook forwarded", 119 | "status_code", resp.StatusCode, 120 | "destination", wh.Meta.OutputDestination, 121 | "method", wh.Method, 122 | ) 123 | 124 | return &types.LogUpdateRequest{ 125 | ID: wh.Meta.ID, 126 | StatusCode: resp.StatusCode, 127 | ResponseBody: body, 128 | Status: types.RequestStatusFromCode(statusCode), 129 | ResponseHeaders: resp.Header, 130 | Retries: retries, 131 | }, nil 132 | } 133 | -------------------------------------------------------------------------------- /pkg/gopool/go_pool.go: -------------------------------------------------------------------------------- 1 | // Package gopool contains tools for goroutine reuse. 2 | package gopool 3 | 4 | import ( 5 | "fmt" 6 | "time" 7 | ) 8 | 9 | // ErrScheduleTimeout returned by Pool to indicate that there no free 10 | // goroutines during some period of time. 11 | var ErrScheduleTimeout = fmt.Errorf("schedule error: timed out") 12 | 13 | // Pool contains logic of goroutine reuse. 14 | type Pool struct { 15 | sem chan struct{} 16 | work chan func() 17 | } 18 | 19 | // NewPool creates new goroutine pool with given size. It also creates a work 20 | // queue of given size. Finally, it spawns given amount of goroutines 21 | // immediately. 22 | func NewPool(size, queue, spawn int) *Pool { 23 | if spawn <= 0 && queue > 0 { 24 | panic("dead queue configuration detected") 25 | } 26 | if spawn > size { 27 | panic("spawn > workers") 28 | } 29 | p := &Pool{ 30 | sem: make(chan struct{}, size), 31 | work: make(chan func(), queue), 32 | } 33 | for i := 0; i < spawn; i++ { 34 | p.sem <- struct{}{} 35 | go p.worker(func() {}) 36 | } 37 | 38 | return p 39 | } 40 | 41 | // Schedule schedules task to be executed over pool's workers. 42 | func (p *Pool) Schedule(task func()) { 43 | p.schedule(task, nil) 44 | } 45 | 46 | // ScheduleTimeout schedules task to be executed over pool's workers. 47 | // It returns ErrScheduleTimeout when no free workers met during given timeout. 48 | func (p *Pool) ScheduleTimeout(timeout time.Duration, task func()) error { 49 | return p.schedule(task, time.After(timeout)) 50 | } 51 | 52 | func (p *Pool) schedule(task func(), timeout <-chan time.Time) error { 53 | select { 54 | case <-timeout: 55 | return ErrScheduleTimeout 56 | case p.work <- task: 57 | return nil 58 | case p.sem <- struct{}{}: 59 | go p.worker(task) 60 | return nil 61 | } 62 | } 63 | 64 | func (p *Pool) worker(task func()) { 65 | defer func() { <-p.sem }() 66 | 67 | task() 68 | 69 | for task := range p.work { 70 | task() 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /pkg/logger/logger.go: -------------------------------------------------------------------------------- 1 | package logger 2 | 3 | import ( 4 | "os" 5 | "time" 6 | 7 | "go.uber.org/zap" 8 | "go.uber.org/zap/zapcore" 9 | ) 10 | 11 | var DefaultLogLevel = zap.InfoLevel 12 | 13 | func getBaseLogConfig(level zapcore.Level) zapcore.EncoderConfig { 14 | 15 | switch level { 16 | case zap.DebugLevel: 17 | return zapcore.EncoderConfig{ 18 | // Keys can be anything except the empty string. 19 | TimeKey: "Time", 20 | LevelKey: "Level", 21 | NameKey: "Name", 22 | CallerKey: "Caller", 23 | MessageKey: "Message", 24 | StacktraceKey: "Stack", 25 | LineEnding: zapcore.DefaultLineEnding, 26 | EncodeLevel: zapcore.CapitalLevelEncoder, 27 | EncodeTime: timeEncoder, 28 | EncodeDuration: zapcore.StringDurationEncoder, 29 | EncodeCaller: zapcore.ShortCallerEncoder, 30 | } 31 | } 32 | 33 | return zapcore.EncoderConfig{ 34 | // Keys can be anything except the empty string. 35 | TimeKey: "Time", 36 | LevelKey: "Level", 37 | NameKey: "Name", 38 | // CallerKey: "Caller", 39 | MessageKey: "Message", 40 | // StacktraceKey: "Stack", 41 | LineEnding: zapcore.DefaultLineEnding, 42 | EncodeLevel: zapcore.CapitalLevelEncoder, 43 | EncodeTime: timeEncoder, 44 | EncodeDuration: zapcore.StringDurationEncoder, 45 | EncodeCaller: zapcore.ShortCallerEncoder, 46 | } 47 | } 48 | 49 | func timeEncoder(t time.Time, enc zapcore.PrimitiveArrayEncoder) { 50 | enc.AppendString(t.Format("2006-01-02 15:04:05.000")) 51 | } 52 | 53 | func GetLoggerInstance(level zapcore.Level) *zap.Logger { 54 | 55 | core := zapcore.NewCore( 56 | zapcore.NewConsoleEncoder(getBaseLogConfig(level)), 57 | zapcore.NewMultiWriteSyncer(zapcore.AddSync(os.Stdout)), 58 | level, 59 | ) 60 | return zap.New(core, zap.AddCaller()) 61 | 62 | } 63 | -------------------------------------------------------------------------------- /pkg/types/request_log.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import "net/http" 4 | 5 | // LogUpdateRequest - update log req 6 | type LogUpdateRequest struct { 7 | ID string `json:"-"` 8 | // BucketID string `json:"-"` 9 | StatusCode int `json:"status_code"` 10 | ResponseBody []byte `json:"response_body"` 11 | ResponseHeaders http.Header `json:"response_headers"` 12 | Status RequestStatus `json:"status"` 13 | Retries int `json:"retries"` 14 | } 15 | 16 | // RequestStatus - request status 17 | type RequestStatus int 18 | 19 | // default statuses 20 | const ( 21 | RequestStatusPreparing RequestStatus = iota 22 | RequestStatusSent 23 | RequestStatusFailed 24 | RequestStatusStalled // if request destination wasn't listening - incoming requests will be stalled 25 | RequestStatusReceived 26 | RequestStatusRejected 27 | ) 28 | 29 | func (s RequestStatus) String() string { 30 | switch s { 31 | case RequestStatusPreparing: 32 | return "preparing" 33 | case RequestStatusSent: 34 | return "sent" 35 | case RequestStatusFailed: 36 | return "failed" 37 | case RequestStatusStalled: 38 | return "stalled" 39 | case RequestStatusReceived: 40 | return "received" 41 | case RequestStatusRejected: 42 | return "rejected" 43 | default: 44 | return "unknown" 45 | } 46 | } 47 | 48 | // RequestStatusFromCode - gets request status from resp status code 49 | func RequestStatusFromCode(code int) RequestStatus { 50 | if code >= 200 && code <= 300 { 51 | return RequestStatusSent 52 | } 53 | 54 | return RequestStatusFailed 55 | } 56 | -------------------------------------------------------------------------------- /pkg/types/requeststatus_jsonenums.go: -------------------------------------------------------------------------------- 1 | // generated by jsonenums -type=RequestStatus; DO NOT EDIT 2 | 3 | package types 4 | 5 | import ( 6 | "encoding/json" 7 | "fmt" 8 | ) 9 | 10 | var ( 11 | _RequestStatusNameToValue = map[string]RequestStatus{ 12 | "RequestStatusPreparing": RequestStatusPreparing, 13 | "RequestStatusSent": RequestStatusSent, 14 | "RequestStatusFailed": RequestStatusFailed, 15 | "RequestStatusStalled": RequestStatusStalled, 16 | "RequestStatusReceived": RequestStatusReceived, 17 | "RequestStatusRejected": RequestStatusRejected, 18 | } 19 | 20 | _RequestStatusValueToName = map[RequestStatus]string{ 21 | RequestStatusPreparing: "RequestStatusPreparing", 22 | RequestStatusSent: "RequestStatusSent", 23 | RequestStatusFailed: "RequestStatusFailed", 24 | RequestStatusStalled: "RequestStatusStalled", 25 | RequestStatusReceived: "RequestStatusReceived", 26 | RequestStatusRejected: "RequestStatusRejected", 27 | } 28 | ) 29 | 30 | func init() { 31 | var v RequestStatus 32 | if _, ok := interface{}(v).(fmt.Stringer); ok { 33 | _RequestStatusNameToValue = map[string]RequestStatus{ 34 | interface{}(RequestStatusPreparing).(fmt.Stringer).String(): RequestStatusPreparing, 35 | interface{}(RequestStatusSent).(fmt.Stringer).String(): RequestStatusSent, 36 | interface{}(RequestStatusFailed).(fmt.Stringer).String(): RequestStatusFailed, 37 | interface{}(RequestStatusStalled).(fmt.Stringer).String(): RequestStatusStalled, 38 | interface{}(RequestStatusReceived).(fmt.Stringer).String(): RequestStatusReceived, 39 | interface{}(RequestStatusRejected).(fmt.Stringer).String(): RequestStatusRejected, 40 | } 41 | } 42 | } 43 | 44 | // MarshalJSON is generated so RequestStatus satisfies json.Marshaler. 45 | func (r RequestStatus) MarshalJSON() ([]byte, error) { 46 | if s, ok := interface{}(r).(fmt.Stringer); ok { 47 | return json.Marshal(s.String()) 48 | } 49 | s, ok := _RequestStatusValueToName[r] 50 | if !ok { 51 | return nil, fmt.Errorf("invalid RequestStatus: %d", r) 52 | } 53 | return json.Marshal(s) 54 | } 55 | 56 | // UnmarshalJSON is generated so RequestStatus satisfies json.Unmarshaler. 57 | func (r *RequestStatus) UnmarshalJSON(data []byte) error { 58 | var s string 59 | if err := json.Unmarshal(data, &s); err != nil { 60 | return fmt.Errorf("RequestStatus should be a string, got %s", data) 61 | } 62 | v, ok := _RequestStatusNameToValue[s] 63 | if !ok { 64 | return fmt.Errorf("invalid RequestStatus %q", s) 65 | } 66 | *r = v 67 | return nil 68 | } 69 | -------------------------------------------------------------------------------- /pkg/types/version_info.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | // VersionInfo describes version and runtime info. 4 | type VersionInfo struct { 5 | Name string `json:"name"` 6 | BuildDate string `json:"buildDate"` 7 | Revision string `json:"revision"` 8 | Version string `json:"version"` 9 | APIVersion string `json:"apiVersion"` 10 | GoVersion string `json:"goVersion"` 11 | OS string `json:"os"` 12 | Arch string `json:"arch"` 13 | KernelVersion string `json:"kernelVersion"` 14 | Experimental bool `json:"experimental"` 15 | } 16 | 17 | type VersionResponse struct { 18 | Client *VersionInfo 19 | Server *VersionInfo 20 | } 21 | 22 | // ServerOK returns true when the client could connect to the server 23 | // and parse the information received. It returns false otherwise. 24 | func (v VersionResponse) ServerOK() bool { 25 | return v.Server != nil 26 | } 27 | -------------------------------------------------------------------------------- /pkg/types/ws_types.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | type EventMeta struct { 4 | ID string `json:"id"` 5 | BucketID string `json:"bucked_id"` 6 | BucketName string `json:"bucket_name"` 7 | InputID string `json:"input_id"` 8 | InputName string `json:"input_name"` 9 | OutputName string `json:"output_name"` 10 | OutputDestination string `json:"output_destination"` 11 | } 12 | 13 | // Event is used by the socket server to stream new webhooks, example: 14 | // { 15 | // "type": "webhook", 16 | // "meta": { 17 | // "bucked_id": "1593fe5f-45f9-45cc-ba23-675fdc7c1638", 18 | // "bucket_name": "123", 19 | // "input_id": "b90f2fe9-621d-4290-9e74-edd5b61325dd", 20 | // "input_name": "Default public endpoint" 21 | // }, 22 | // "headers": { 23 | // "Accept": [ 24 | // "*/*" 25 | // ], 26 | // "Content-Length": [ 27 | // "15" 28 | // ], 29 | // "User-Agent": [ 30 | // "insomnia/6.2.0" 31 | // ], 32 | // "Cookie": [ 33 | // "JSESSIONID.9cbae22a=q3lczkhqmp3s15ssahn1hpsta" 34 | // ], 35 | // "Content-Type": [ 36 | // "application/json" 37 | // ] 38 | // }, 39 | // "query": "foo=bar", 40 | // "body": "{\"hi\": \"there\"}", 41 | // "method": "PUT" 42 | // } 43 | type Event struct { 44 | Type string `json:"type"` 45 | Meta EventMeta `json:"meta"` 46 | Headers map[string][]string `json:"headers"` 47 | RawQuery string `json:"query"` 48 | Body string `json:"body"` 49 | Method string `json:"method"` 50 | 51 | // combined fields from status 52 | Status string `json:"status"` 53 | Message string `json:"message"` 54 | } 55 | 56 | // SubscribeRequest contains bin ID 57 | // Example authentication: 58 | // SEND: 59 | // { 60 | // "action":"auth", 61 | // "key":"YOUR_KEY" 62 | // "secret":"YOUR_SECRET" 63 | // } 64 | // Example Subscribe: 65 | // SEND: 66 | // { 67 | // "action":"subscribe", 68 | // "buckets": ["bucket-x", "bucket-uuid-here"] 69 | // } 70 | type ActionRequest struct { 71 | // Action - auth/subscribe 72 | Action string `json:"action"` 73 | 74 | Key string `json:"key"` 75 | Secret string `json:"secret"` 76 | 77 | // if action == subscribe 78 | Buckets []string `json:"buckets"` 79 | } 80 | 81 | type EventStatus struct { 82 | ID string `json:"id"` 83 | StatusCode int `json:"status_code"` 84 | Retries int `json:"retries"` 85 | Message string `json:"message"` 86 | } 87 | -------------------------------------------------------------------------------- /tests/forward/forward_test.go: -------------------------------------------------------------------------------- 1 | package forward 2 | 3 | import ( 4 | "bytes" 5 | "context" 6 | "net" 7 | "net/http" 8 | "os" 9 | "strings" 10 | "testing" 11 | "time" 12 | ) 13 | 14 | func TestRelayFoward(t *testing.T) { 15 | 16 | if os.Getenv("RELAY_KEY") == "" || os.Getenv("RELAY_SECRET") == "" { 17 | t.Fatalf("RELAY_KEY or RELAY_SECRET not set") 18 | } 19 | relayCLITestBucketName := os.Getenv("BUCKETS") 20 | testBucketInputURL := os.Getenv("INPUT_URL") 21 | 22 | ctx, cancel := context.WithCancel(context.Background()) 23 | defer cancel() 24 | 25 | webhookReceiver := &WebhookServer{} 26 | go webhookReceiver.Start(":33003") 27 | time.Sleep(100 * time.Millisecond) 28 | defer webhookReceiver.Shutdown() 29 | 30 | relayCLI := NewRelayCmd(os.Getenv("RELAY_KEY"), os.Getenv("RELAY_SECRET")) 31 | go func() { 32 | // ensure that the bucket has output http://localhost:33003/webhook 33 | err := relayCLI.Forward(ctx, []string{"--buckets", relayCLITestBucketName}) 34 | if err != nil { 35 | t.Errorf("failed to start relay process: %s", err) 36 | } 37 | }() 38 | 39 | time.Sleep(1 * time.Second) 40 | 41 | var defaultTransport http.RoundTripper = &http.Transport{ 42 | Proxy: nil, 43 | DialContext: (&net.Dialer{ 44 | Timeout: 10 * time.Second, 45 | KeepAlive: 30 * time.Second, 46 | DualStack: true, 47 | }).DialContext, 48 | MaxIdleConns: 30, 49 | IdleConnTimeout: 90 * time.Second, 50 | TLSHandshakeTimeout: 15 * time.Second, 51 | ExpectContinueTimeout: 1 * time.Second, 52 | } 53 | 54 | httpClient := &http.Client{Transport: defaultTransport} 55 | 56 | t.Run("ForwardWebhook", func(t *testing.T) { 57 | 58 | // wiping server of any webhooks 59 | defer webhookReceiver.Cleanup() 60 | 61 | method := "POST" 62 | payload := "foo" 63 | 64 | headers := map[string]string{ 65 | "hdr-1": "foo", 66 | "hdr-2": "foo", 67 | "hdr-3": "foo", 68 | "hdr-4": "foo", 69 | "hdr-5": "foo", 70 | "hdr-6": "foo", 71 | } 72 | 73 | req, err := http.NewRequest(method, testBucketInputURL, bytes.NewBufferString(payload)) 74 | if err != nil { 75 | t.Fatalf("failed to create req: %s", err) 76 | } 77 | 78 | for k, v := range headers { 79 | req.Header.Set(k, v) 80 | } 81 | 82 | resp, err := httpClient.Do(req) 83 | if err != nil { 84 | t.Fatal(err) 85 | } 86 | 87 | if resp.StatusCode != 200 { 88 | t.Errorf("unexpected status code: %d", resp.StatusCode) 89 | } 90 | 91 | time.Sleep(1 * time.Second) 92 | 93 | // checking whether we got it 94 | if len(webhookReceiver.Received()) != 1 { 95 | t.Errorf("expected to receive 1 webhook, got %d", len(webhookReceiver.Received())) 96 | } else { 97 | 98 | webhook := webhookReceiver.Received()[0] 99 | 100 | if webhook.Payload != payload { 101 | t.Errorf("expected payload '%s', got: '%s'", payload, webhook.Payload) 102 | } 103 | if webhook.Method != method { 104 | t.Errorf("expected method '%s', got: '%s'", method, webhook.Method) 105 | } 106 | 107 | for k, v := range headers { 108 | if webhook.Headers[strings.Title(k)] != v { 109 | t.Errorf("expected %s=%s, got: %s=%s", k, v, k, webhook.Headers[k]) 110 | } 111 | } 112 | } 113 | }) 114 | } 115 | -------------------------------------------------------------------------------- /tests/forward/helper.go: -------------------------------------------------------------------------------- 1 | package forward 2 | 3 | import ( 4 | "context" 5 | "log" 6 | "os" 7 | "os/exec" 8 | "strings" 9 | ) 10 | 11 | type RelayCmd struct { 12 | cmd *exec.Cmd 13 | key string 14 | secret string 15 | } 16 | 17 | func NewRelayCmd(key string, secret string) *RelayCmd { 18 | return &RelayCmd{ 19 | key: key, 20 | secret: secret, 21 | } 22 | } 23 | 24 | func (rc *RelayCmd) Forward(ctx context.Context, args []string) error { 25 | 26 | cmd := "relayd" 27 | fullArgs := []string{"forward"} 28 | fullArgs = append(fullArgs, args...) 29 | c := exec.CommandContext(ctx, cmd, fullArgs...) 30 | c.Env = []string{ 31 | "DEBUG=true", 32 | "RELAY_KEY=" + rc.key, 33 | "RELAY_SECRET=" + rc.secret, 34 | "HTTP_PROXY=" + os.Getenv("HTTP_PROXY"), 35 | "HTTPS_PROXY=" + os.Getenv("HTTPS_PROXY"), 36 | "RELAY_INSECURE=" + os.Getenv("RELAY_INSECURE"), 37 | } 38 | c.Stdout = os.Stdout 39 | c.Stderr = os.Stderr 40 | 41 | rc.cmd = c 42 | 43 | err := c.Run() 44 | if err != nil { 45 | if strings.Contains(err.Error(), "killed") { 46 | return nil 47 | } 48 | } 49 | return err 50 | } 51 | 52 | func (rc *RelayCmd) Stop() error { 53 | defer log.Println("relayd stopped") 54 | return rc.cmd.Process.Kill() 55 | } 56 | -------------------------------------------------------------------------------- /tests/forward/receiver.go: -------------------------------------------------------------------------------- 1 | package forward 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "io/ioutil" 7 | "log" 8 | "net/http" 9 | "sync" 10 | "time" 11 | 12 | "github.com/urfave/negroni" 13 | ) 14 | 15 | // ReceivedWebhook - keeps info about received webhook 16 | type ReceivedWebhook struct { 17 | Payload string 18 | ReceivedAt time.Time 19 | Method string 20 | Headers map[string]string 21 | } 22 | 23 | type WebhookServer struct { 24 | received []*ReceivedWebhook 25 | srv *http.Server 26 | mw MWFunc 27 | } 28 | 29 | type MWFunc func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) 30 | 31 | func (s *WebhookServer) SetMiddleware(mw MWFunc) { 32 | s.mw = mw 33 | } 34 | 35 | func (s *WebhookServer) Received() []*ReceivedWebhook { 36 | return s.received 37 | } 38 | 39 | func (s *WebhookServer) Cleanup() { 40 | s.received = []*ReceivedWebhook{} 41 | } 42 | 43 | func (s *WebhookServer) Start(port string) { 44 | 45 | mux := http.NewServeMux() 46 | 47 | mu := &sync.RWMutex{} 48 | 49 | mux.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) { 50 | w.Header().Add("server", "webhook-server") 51 | w.WriteHeader(http.StatusOK) 52 | }) 53 | 54 | // Incoming webhook handler 55 | mux.HandleFunc("/webhook", func(w http.ResponseWriter, r *http.Request) { 56 | bd, err := ioutil.ReadAll(r.Body) 57 | if err != nil { 58 | w.WriteHeader(http.StatusInternalServerError) 59 | w.Write([]byte(err.Error())) 60 | return 61 | } 62 | defer r.Body.Close() 63 | 64 | // appending webhook to received list 65 | mu.Lock() 66 | 67 | headers := make(map[string]string) 68 | 69 | for k, vv := range r.Header { 70 | headers[k] = vv[0] 71 | } 72 | 73 | s.received = append(s.received, &ReceivedWebhook{ 74 | ReceivedAt: time.Now(), 75 | Payload: string(bd), 76 | Method: r.Method, 77 | Headers: headers, 78 | }) 79 | mu.Unlock() 80 | 81 | w.Header().Add("server", "webhook-demo") 82 | 83 | fmt.Printf("webhook received, payload: %s, method: %s \n", string(bd), r.Method) 84 | w.WriteHeader(http.StatusOK) 85 | }) 86 | 87 | n := negroni.New(negroni.NewRecovery()) 88 | 89 | if s.mw != nil { 90 | n.Use(negroni.HandlerFunc(s.mw)) 91 | } 92 | 93 | n.UseHandler(mux) 94 | 95 | s.srv = &http.Server{Addr: port, Handler: n} 96 | 97 | fmt.Printf("Receiving webhooks on http://localhost%s/webhook \n", port) 98 | // starting server 99 | if err := s.srv.ListenAndServe(); err != http.ErrServerClosed { 100 | log.Fatalf("listen: %s\n", err) 101 | } 102 | } 103 | 104 | func (s *WebhookServer) Shutdown() { 105 | if s.srv != nil { 106 | s.srv.Shutdown(context.Background()) 107 | } 108 | } 109 | 110 | type FailureMiddleware struct { 111 | toFail int 112 | statusCode int 113 | 114 | currentFails int 115 | mu *sync.Mutex 116 | } 117 | 118 | func NewFailureMiddleware(toFail, statusCode int) *FailureMiddleware { 119 | return &FailureMiddleware{ 120 | toFail: toFail, 121 | statusCode: statusCode, 122 | mu: &sync.Mutex{}, 123 | } 124 | } 125 | 126 | func (mw *FailureMiddleware) ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) { 127 | mw.mu.Lock() 128 | defer mw.mu.Unlock() 129 | 130 | if mw.toFail == 0 { 131 | next(rw, r) 132 | return 133 | } 134 | 135 | if mw.currentFails < mw.toFail { 136 | rw.WriteHeader(mw.statusCode) 137 | mw.currentFails++ 138 | return 139 | } 140 | 141 | next(rw, r) 142 | } 143 | -------------------------------------------------------------------------------- /vendor/github.com/alecthomas/template/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012 The Go Authors. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the 12 | distribution. 13 | * Neither the name of Google Inc. nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /vendor/github.com/alecthomas/template/README.md: -------------------------------------------------------------------------------- 1 | # Go's `text/template` package with newline elision 2 | 3 | This is a fork of Go 1.4's [text/template](http://golang.org/pkg/text/template/) package with one addition: a backslash immediately after a closing delimiter will delete all subsequent newlines until a non-newline. 4 | 5 | eg. 6 | 7 | ``` 8 | {{if true}}\ 9 | hello 10 | {{end}}\ 11 | ``` 12 | 13 | Will result in: 14 | 15 | ``` 16 | hello\n 17 | ``` 18 | 19 | Rather than: 20 | 21 | ``` 22 | \n 23 | hello\n 24 | \n 25 | ``` 26 | -------------------------------------------------------------------------------- /vendor/github.com/alecthomas/units/COPYING: -------------------------------------------------------------------------------- 1 | Copyright (C) 2014 Alec Thomas 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | this software and associated documentation files (the "Software"), to deal in 5 | the Software without restriction, including without limitation the rights to 6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 7 | of the Software, and to permit persons to whom the Software is furnished to do 8 | so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /vendor/github.com/alecthomas/units/README.md: -------------------------------------------------------------------------------- 1 | # Units - Helpful unit multipliers and functions for Go 2 | 3 | The goal of this package is to have functionality similar to the [time](http://golang.org/pkg/time/) package. 4 | 5 | It allows for code like this: 6 | 7 | ```go 8 | n, err := ParseBase2Bytes("1KB") 9 | // n == 1024 10 | n = units.Mebibyte * 512 11 | ``` 12 | -------------------------------------------------------------------------------- /vendor/github.com/alecthomas/units/bytes.go: -------------------------------------------------------------------------------- 1 | package units 2 | 3 | // Base2Bytes is the old non-SI power-of-2 byte scale (1024 bytes in a kilobyte, 4 | // etc.). 5 | type Base2Bytes int64 6 | 7 | // Base-2 byte units. 8 | const ( 9 | Kibibyte Base2Bytes = 1024 10 | KiB = Kibibyte 11 | Mebibyte = Kibibyte * 1024 12 | MiB = Mebibyte 13 | Gibibyte = Mebibyte * 1024 14 | GiB = Gibibyte 15 | Tebibyte = Gibibyte * 1024 16 | TiB = Tebibyte 17 | Pebibyte = Tebibyte * 1024 18 | PiB = Pebibyte 19 | Exbibyte = Pebibyte * 1024 20 | EiB = Exbibyte 21 | ) 22 | 23 | var ( 24 | bytesUnitMap = MakeUnitMap("iB", "B", 1024) 25 | oldBytesUnitMap = MakeUnitMap("B", "B", 1024) 26 | ) 27 | 28 | // ParseBase2Bytes supports both iB and B in base-2 multipliers. That is, KB 29 | // and KiB are both 1024. 30 | func ParseBase2Bytes(s string) (Base2Bytes, error) { 31 | n, err := ParseUnit(s, bytesUnitMap) 32 | if err != nil { 33 | n, err = ParseUnit(s, oldBytesUnitMap) 34 | } 35 | return Base2Bytes(n), err 36 | } 37 | 38 | func (b Base2Bytes) String() string { 39 | return ToString(int64(b), 1024, "iB", "B") 40 | } 41 | 42 | var ( 43 | metricBytesUnitMap = MakeUnitMap("B", "B", 1000) 44 | ) 45 | 46 | // MetricBytes are SI byte units (1000 bytes in a kilobyte). 47 | type MetricBytes SI 48 | 49 | // SI base-10 byte units. 50 | const ( 51 | Kilobyte MetricBytes = 1000 52 | KB = Kilobyte 53 | Megabyte = Kilobyte * 1000 54 | MB = Megabyte 55 | Gigabyte = Megabyte * 1000 56 | GB = Gigabyte 57 | Terabyte = Gigabyte * 1000 58 | TB = Terabyte 59 | Petabyte = Terabyte * 1000 60 | PB = Petabyte 61 | Exabyte = Petabyte * 1000 62 | EB = Exabyte 63 | ) 64 | 65 | // ParseMetricBytes parses base-10 metric byte units. That is, KB is 1000 bytes. 66 | func ParseMetricBytes(s string) (MetricBytes, error) { 67 | n, err := ParseUnit(s, metricBytesUnitMap) 68 | return MetricBytes(n), err 69 | } 70 | 71 | func (m MetricBytes) String() string { 72 | return ToString(int64(m), 1000, "B", "B") 73 | } 74 | 75 | // ParseStrictBytes supports both iB and B suffixes for base 2 and metric, 76 | // respectively. That is, KiB represents 1024 and KB represents 1000. 77 | func ParseStrictBytes(s string) (int64, error) { 78 | n, err := ParseUnit(s, bytesUnitMap) 79 | if err != nil { 80 | n, err = ParseUnit(s, metricBytesUnitMap) 81 | } 82 | return int64(n), err 83 | } 84 | -------------------------------------------------------------------------------- /vendor/github.com/alecthomas/units/doc.go: -------------------------------------------------------------------------------- 1 | // Package units provides helpful unit multipliers and functions for Go. 2 | // 3 | // The goal of this package is to have functionality similar to the time [1] package. 4 | // 5 | // 6 | // [1] http://golang.org/pkg/time/ 7 | // 8 | // It allows for code like this: 9 | // 10 | // n, err := ParseBase2Bytes("1KB") 11 | // // n == 1024 12 | // n = units.Mebibyte * 512 13 | package units 14 | -------------------------------------------------------------------------------- /vendor/github.com/alecthomas/units/si.go: -------------------------------------------------------------------------------- 1 | package units 2 | 3 | // SI units. 4 | type SI int64 5 | 6 | // SI unit multiples. 7 | const ( 8 | Kilo SI = 1000 9 | Mega = Kilo * 1000 10 | Giga = Mega * 1000 11 | Tera = Giga * 1000 12 | Peta = Tera * 1000 13 | Exa = Peta * 1000 14 | ) 15 | 16 | func MakeUnitMap(suffix, shortSuffix string, scale int64) map[string]float64 { 17 | return map[string]float64{ 18 | shortSuffix: 1, 19 | "K" + suffix: float64(scale), 20 | "M" + suffix: float64(scale * scale), 21 | "G" + suffix: float64(scale * scale * scale), 22 | "T" + suffix: float64(scale * scale * scale * scale), 23 | "P" + suffix: float64(scale * scale * scale * scale * scale), 24 | "E" + suffix: float64(scale * scale * scale * scale * scale * scale), 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /vendor/github.com/alecthomas/units/util.go: -------------------------------------------------------------------------------- 1 | package units 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "strings" 7 | ) 8 | 9 | var ( 10 | siUnits = []string{"", "K", "M", "G", "T", "P", "E"} 11 | ) 12 | 13 | func ToString(n int64, scale int64, suffix, baseSuffix string) string { 14 | mn := len(siUnits) 15 | out := make([]string, mn) 16 | for i, m := range siUnits { 17 | if n%scale != 0 || i == 0 && n == 0 { 18 | s := suffix 19 | if i == 0 { 20 | s = baseSuffix 21 | } 22 | out[mn-1-i] = fmt.Sprintf("%d%s%s", n%scale, m, s) 23 | } 24 | n /= scale 25 | if n == 0 { 26 | break 27 | } 28 | } 29 | return strings.Join(out, "") 30 | } 31 | 32 | // Below code ripped straight from http://golang.org/src/pkg/time/format.go?s=33392:33438#L1123 33 | var errLeadingInt = errors.New("units: bad [0-9]*") // never printed 34 | 35 | // leadingInt consumes the leading [0-9]* from s. 36 | func leadingInt(s string) (x int64, rem string, err error) { 37 | i := 0 38 | for ; i < len(s); i++ { 39 | c := s[i] 40 | if c < '0' || c > '9' { 41 | break 42 | } 43 | if x >= (1<<63-10)/10 { 44 | // overflow 45 | return 0, "", errLeadingInt 46 | } 47 | x = x*10 + int64(c) - '0' 48 | } 49 | return x, s[i:], nil 50 | } 51 | 52 | func ParseUnit(s string, unitMap map[string]float64) (int64, error) { 53 | // [-+]?([0-9]*(\.[0-9]*)?[a-z]+)+ 54 | orig := s 55 | f := float64(0) 56 | neg := false 57 | 58 | // Consume [-+]? 59 | if s != "" { 60 | c := s[0] 61 | if c == '-' || c == '+' { 62 | neg = c == '-' 63 | s = s[1:] 64 | } 65 | } 66 | // Special case: if all that is left is "0", this is zero. 67 | if s == "0" { 68 | return 0, nil 69 | } 70 | if s == "" { 71 | return 0, errors.New("units: invalid " + orig) 72 | } 73 | for s != "" { 74 | g := float64(0) // this element of the sequence 75 | 76 | var x int64 77 | var err error 78 | 79 | // The next character must be [0-9.] 80 | if !(s[0] == '.' || ('0' <= s[0] && s[0] <= '9')) { 81 | return 0, errors.New("units: invalid " + orig) 82 | } 83 | // Consume [0-9]* 84 | pl := len(s) 85 | x, s, err = leadingInt(s) 86 | if err != nil { 87 | return 0, errors.New("units: invalid " + orig) 88 | } 89 | g = float64(x) 90 | pre := pl != len(s) // whether we consumed anything before a period 91 | 92 | // Consume (\.[0-9]*)? 93 | post := false 94 | if s != "" && s[0] == '.' { 95 | s = s[1:] 96 | pl := len(s) 97 | x, s, err = leadingInt(s) 98 | if err != nil { 99 | return 0, errors.New("units: invalid " + orig) 100 | } 101 | scale := 1.0 102 | for n := pl - len(s); n > 0; n-- { 103 | scale *= 10 104 | } 105 | g += float64(x) / scale 106 | post = pl != len(s) 107 | } 108 | if !pre && !post { 109 | // no digits (e.g. ".s" or "-.s") 110 | return 0, errors.New("units: invalid " + orig) 111 | } 112 | 113 | // Consume unit. 114 | i := 0 115 | for ; i < len(s); i++ { 116 | c := s[i] 117 | if c == '.' || ('0' <= c && c <= '9') { 118 | break 119 | } 120 | } 121 | u := s[:i] 122 | s = s[i:] 123 | unit, ok := unitMap[u] 124 | if !ok { 125 | return 0, errors.New("units: unknown unit " + u + " in " + orig) 126 | } 127 | 128 | f += g * unit 129 | } 130 | 131 | if neg { 132 | f = -f 133 | } 134 | if f < float64(-1<<63) || f > float64(1<<63-1) { 135 | return 0, errors.New("units: overflow parsing unit") 136 | } 137 | return int64(f), nil 138 | } 139 | -------------------------------------------------------------------------------- /vendor/github.com/davecgh/go-spew/LICENSE: -------------------------------------------------------------------------------- 1 | ISC License 2 | 3 | Copyright (c) 2012-2016 Dave Collins 4 | 5 | Permission to use, copy, modify, and distribute this software for any 6 | purpose with or without fee is hereby granted, provided that the above 7 | copyright notice and this permission notice appear in all copies. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | -------------------------------------------------------------------------------- /vendor/github.com/davecgh/go-spew/spew/bypasssafe.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2016 Dave Collins 2 | // 3 | // Permission to use, copy, modify, and distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 13 | // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | // NOTE: Due to the following build constraints, this file will only be compiled 16 | // when the code is running on Google App Engine, compiled by GopherJS, or 17 | // "-tags safe" is added to the go build command line. The "disableunsafe" 18 | // tag is deprecated and thus should not be used. 19 | // +build js appengine safe disableunsafe 20 | 21 | package spew 22 | 23 | import "reflect" 24 | 25 | const ( 26 | // UnsafeDisabled is a build-time constant which specifies whether or 27 | // not access to the unsafe package is available. 28 | UnsafeDisabled = true 29 | ) 30 | 31 | // unsafeReflectValue typically converts the passed reflect.Value into a one 32 | // that bypasses the typical safety restrictions preventing access to 33 | // unaddressable and unexported data. However, doing this relies on access to 34 | // the unsafe package. This is a stub version which simply returns the passed 35 | // reflect.Value when the unsafe package is not available. 36 | func unsafeReflectValue(v reflect.Value) reflect.Value { 37 | return v 38 | } 39 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/websocket/.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 2 | *.o 3 | *.a 4 | *.so 5 | 6 | # Folders 7 | _obj 8 | _test 9 | 10 | # Architecture specific extensions/prefixes 11 | *.[568vq] 12 | [568vq].out 13 | 14 | *.cgo1.go 15 | *.cgo2.c 16 | _cgo_defun.c 17 | _cgo_gotypes.go 18 | _cgo_export.* 19 | 20 | _testmain.go 21 | 22 | *.exe 23 | 24 | .idea/ 25 | *.iml 26 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/websocket/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | sudo: false 3 | 4 | matrix: 5 | include: 6 | - go: 1.7.x 7 | - go: 1.8.x 8 | - go: 1.9.x 9 | - go: 1.10.x 10 | - go: 1.11.x 11 | - go: tip 12 | allow_failures: 13 | - go: tip 14 | 15 | script: 16 | - go get -t -v ./... 17 | - diff -u <(echo -n) <(gofmt -d .) 18 | - go vet $(go list ./... | grep -v /vendor/) 19 | - go test -v -race ./... 20 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/websocket/AUTHORS: -------------------------------------------------------------------------------- 1 | # This is the official list of Gorilla WebSocket authors for copyright 2 | # purposes. 3 | # 4 | # Please keep the list sorted. 5 | 6 | Gary Burd 7 | Google LLC (https://opensource.google.com/) 8 | Joachim Bauch 9 | 10 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/websocket/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013 The Gorilla WebSocket Authors. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are met: 5 | 6 | Redistributions of source code must retain the above copyright notice, this 7 | list of conditions and the following disclaimer. 8 | 9 | Redistributions in binary form must reproduce the above copyright notice, 10 | this list of conditions and the following disclaimer in the documentation 11 | and/or other materials provided with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 14 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 17 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 19 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 20 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 21 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 22 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/websocket/client_clone.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Gorilla WebSocket Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build go1.8 6 | 7 | package websocket 8 | 9 | import "crypto/tls" 10 | 11 | func cloneTLSConfig(cfg *tls.Config) *tls.Config { 12 | if cfg == nil { 13 | return &tls.Config{} 14 | } 15 | return cfg.Clone() 16 | } 17 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/websocket/client_clone_legacy.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Gorilla WebSocket Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build !go1.8 6 | 7 | package websocket 8 | 9 | import "crypto/tls" 10 | 11 | // cloneTLSConfig clones all public fields except the fields 12 | // SessionTicketsDisabled and SessionTicketKey. This avoids copying the 13 | // sync.Mutex in the sync.Once and makes it safe to call cloneTLSConfig on a 14 | // config in active use. 15 | func cloneTLSConfig(cfg *tls.Config) *tls.Config { 16 | if cfg == nil { 17 | return &tls.Config{} 18 | } 19 | return &tls.Config{ 20 | Rand: cfg.Rand, 21 | Time: cfg.Time, 22 | Certificates: cfg.Certificates, 23 | NameToCertificate: cfg.NameToCertificate, 24 | GetCertificate: cfg.GetCertificate, 25 | RootCAs: cfg.RootCAs, 26 | NextProtos: cfg.NextProtos, 27 | ServerName: cfg.ServerName, 28 | ClientAuth: cfg.ClientAuth, 29 | ClientCAs: cfg.ClientCAs, 30 | InsecureSkipVerify: cfg.InsecureSkipVerify, 31 | CipherSuites: cfg.CipherSuites, 32 | PreferServerCipherSuites: cfg.PreferServerCipherSuites, 33 | ClientSessionCache: cfg.ClientSessionCache, 34 | MinVersion: cfg.MinVersion, 35 | MaxVersion: cfg.MaxVersion, 36 | CurvePreferences: cfg.CurvePreferences, 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/websocket/compression.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Gorilla WebSocket Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package websocket 6 | 7 | import ( 8 | "compress/flate" 9 | "errors" 10 | "io" 11 | "strings" 12 | "sync" 13 | ) 14 | 15 | const ( 16 | minCompressionLevel = -2 // flate.HuffmanOnly not defined in Go < 1.6 17 | maxCompressionLevel = flate.BestCompression 18 | defaultCompressionLevel = 1 19 | ) 20 | 21 | var ( 22 | flateWriterPools [maxCompressionLevel - minCompressionLevel + 1]sync.Pool 23 | flateReaderPool = sync.Pool{New: func() interface{} { 24 | return flate.NewReader(nil) 25 | }} 26 | ) 27 | 28 | func decompressNoContextTakeover(r io.Reader) io.ReadCloser { 29 | const tail = 30 | // Add four bytes as specified in RFC 31 | "\x00\x00\xff\xff" + 32 | // Add final block to squelch unexpected EOF error from flate reader. 33 | "\x01\x00\x00\xff\xff" 34 | 35 | fr, _ := flateReaderPool.Get().(io.ReadCloser) 36 | fr.(flate.Resetter).Reset(io.MultiReader(r, strings.NewReader(tail)), nil) 37 | return &flateReadWrapper{fr} 38 | } 39 | 40 | func isValidCompressionLevel(level int) bool { 41 | return minCompressionLevel <= level && level <= maxCompressionLevel 42 | } 43 | 44 | func compressNoContextTakeover(w io.WriteCloser, level int) io.WriteCloser { 45 | p := &flateWriterPools[level-minCompressionLevel] 46 | tw := &truncWriter{w: w} 47 | fw, _ := p.Get().(*flate.Writer) 48 | if fw == nil { 49 | fw, _ = flate.NewWriter(tw, level) 50 | } else { 51 | fw.Reset(tw) 52 | } 53 | return &flateWriteWrapper{fw: fw, tw: tw, p: p} 54 | } 55 | 56 | // truncWriter is an io.Writer that writes all but the last four bytes of the 57 | // stream to another io.Writer. 58 | type truncWriter struct { 59 | w io.WriteCloser 60 | n int 61 | p [4]byte 62 | } 63 | 64 | func (w *truncWriter) Write(p []byte) (int, error) { 65 | n := 0 66 | 67 | // fill buffer first for simplicity. 68 | if w.n < len(w.p) { 69 | n = copy(w.p[w.n:], p) 70 | p = p[n:] 71 | w.n += n 72 | if len(p) == 0 { 73 | return n, nil 74 | } 75 | } 76 | 77 | m := len(p) 78 | if m > len(w.p) { 79 | m = len(w.p) 80 | } 81 | 82 | if nn, err := w.w.Write(w.p[:m]); err != nil { 83 | return n + nn, err 84 | } 85 | 86 | copy(w.p[:], w.p[m:]) 87 | copy(w.p[len(w.p)-m:], p[len(p)-m:]) 88 | nn, err := w.w.Write(p[:len(p)-m]) 89 | return n + nn, err 90 | } 91 | 92 | type flateWriteWrapper struct { 93 | fw *flate.Writer 94 | tw *truncWriter 95 | p *sync.Pool 96 | } 97 | 98 | func (w *flateWriteWrapper) Write(p []byte) (int, error) { 99 | if w.fw == nil { 100 | return 0, errWriteClosed 101 | } 102 | return w.fw.Write(p) 103 | } 104 | 105 | func (w *flateWriteWrapper) Close() error { 106 | if w.fw == nil { 107 | return errWriteClosed 108 | } 109 | err1 := w.fw.Flush() 110 | w.p.Put(w.fw) 111 | w.fw = nil 112 | if w.tw.p != [4]byte{0, 0, 0xff, 0xff} { 113 | return errors.New("websocket: internal error, unexpected bytes at end of flate stream") 114 | } 115 | err2 := w.tw.w.Close() 116 | if err1 != nil { 117 | return err1 118 | } 119 | return err2 120 | } 121 | 122 | type flateReadWrapper struct { 123 | fr io.ReadCloser 124 | } 125 | 126 | func (r *flateReadWrapper) Read(p []byte) (int, error) { 127 | if r.fr == nil { 128 | return 0, io.ErrClosedPipe 129 | } 130 | n, err := r.fr.Read(p) 131 | if err == io.EOF { 132 | // Preemptively place the reader back in the pool. This helps with 133 | // scenarios where the application does not call NextReader() soon after 134 | // this final read. 135 | r.Close() 136 | } 137 | return n, err 138 | } 139 | 140 | func (r *flateReadWrapper) Close() error { 141 | if r.fr == nil { 142 | return io.ErrClosedPipe 143 | } 144 | err := r.fr.Close() 145 | flateReaderPool.Put(r.fr) 146 | r.fr = nil 147 | return err 148 | } 149 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/websocket/conn_write.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Gorilla WebSocket Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build go1.8 6 | 7 | package websocket 8 | 9 | import "net" 10 | 11 | func (c *Conn) writeBufs(bufs ...[]byte) error { 12 | b := net.Buffers(bufs) 13 | _, err := b.WriteTo(c.conn) 14 | return err 15 | } 16 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/websocket/conn_write_legacy.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Gorilla WebSocket Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build !go1.8 6 | 7 | package websocket 8 | 9 | func (c *Conn) writeBufs(bufs ...[]byte) error { 10 | for _, buf := range bufs { 11 | if len(buf) > 0 { 12 | if _, err := c.conn.Write(buf); err != nil { 13 | return err 14 | } 15 | } 16 | } 17 | return nil 18 | } 19 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/websocket/json.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Gorilla WebSocket Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package websocket 6 | 7 | import ( 8 | "encoding/json" 9 | "io" 10 | ) 11 | 12 | // WriteJSON writes the JSON encoding of v as a message. 13 | // 14 | // Deprecated: Use c.WriteJSON instead. 15 | func WriteJSON(c *Conn, v interface{}) error { 16 | return c.WriteJSON(v) 17 | } 18 | 19 | // WriteJSON writes the JSON encoding of v as a message. 20 | // 21 | // See the documentation for encoding/json Marshal for details about the 22 | // conversion of Go values to JSON. 23 | func (c *Conn) WriteJSON(v interface{}) error { 24 | w, err := c.NextWriter(TextMessage) 25 | if err != nil { 26 | return err 27 | } 28 | err1 := json.NewEncoder(w).Encode(v) 29 | err2 := w.Close() 30 | if err1 != nil { 31 | return err1 32 | } 33 | return err2 34 | } 35 | 36 | // ReadJSON reads the next JSON-encoded message from the connection and stores 37 | // it in the value pointed to by v. 38 | // 39 | // Deprecated: Use c.ReadJSON instead. 40 | func ReadJSON(c *Conn, v interface{}) error { 41 | return c.ReadJSON(v) 42 | } 43 | 44 | // ReadJSON reads the next JSON-encoded message from the connection and stores 45 | // it in the value pointed to by v. 46 | // 47 | // See the documentation for the encoding/json Unmarshal function for details 48 | // about the conversion of JSON to a Go value. 49 | func (c *Conn) ReadJSON(v interface{}) error { 50 | _, r, err := c.NextReader() 51 | if err != nil { 52 | return err 53 | } 54 | err = json.NewDecoder(r).Decode(v) 55 | if err == io.EOF { 56 | // One value is expected in the message. 57 | err = io.ErrUnexpectedEOF 58 | } 59 | return err 60 | } 61 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/websocket/mask.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Gorilla WebSocket Authors. All rights reserved. Use of 2 | // this source code is governed by a BSD-style license that can be found in the 3 | // LICENSE file. 4 | 5 | // +build !appengine 6 | 7 | package websocket 8 | 9 | import "unsafe" 10 | 11 | const wordSize = int(unsafe.Sizeof(uintptr(0))) 12 | 13 | func maskBytes(key [4]byte, pos int, b []byte) int { 14 | // Mask one byte at a time for small buffers. 15 | if len(b) < 2*wordSize { 16 | for i := range b { 17 | b[i] ^= key[pos&3] 18 | pos++ 19 | } 20 | return pos & 3 21 | } 22 | 23 | // Mask one byte at a time to word boundary. 24 | if n := int(uintptr(unsafe.Pointer(&b[0]))) % wordSize; n != 0 { 25 | n = wordSize - n 26 | for i := range b[:n] { 27 | b[i] ^= key[pos&3] 28 | pos++ 29 | } 30 | b = b[n:] 31 | } 32 | 33 | // Create aligned word size key. 34 | var k [wordSize]byte 35 | for i := range k { 36 | k[i] = key[(pos+i)&3] 37 | } 38 | kw := *(*uintptr)(unsafe.Pointer(&k)) 39 | 40 | // Mask one word at a time. 41 | n := (len(b) / wordSize) * wordSize 42 | for i := 0; i < n; i += wordSize { 43 | *(*uintptr)(unsafe.Pointer(uintptr(unsafe.Pointer(&b[0])) + uintptr(i))) ^= kw 44 | } 45 | 46 | // Mask one byte at a time for remaining bytes. 47 | b = b[n:] 48 | for i := range b { 49 | b[i] ^= key[pos&3] 50 | pos++ 51 | } 52 | 53 | return pos & 3 54 | } 55 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/websocket/mask_safe.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Gorilla WebSocket Authors. All rights reserved. Use of 2 | // this source code is governed by a BSD-style license that can be found in the 3 | // LICENSE file. 4 | 5 | // +build appengine 6 | 7 | package websocket 8 | 9 | func maskBytes(key [4]byte, pos int, b []byte) int { 10 | for i := range b { 11 | b[i] ^= key[pos&3] 12 | pos++ 13 | } 14 | return pos & 3 15 | } 16 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/websocket/prepared.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Gorilla WebSocket Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package websocket 6 | 7 | import ( 8 | "bytes" 9 | "net" 10 | "sync" 11 | "time" 12 | ) 13 | 14 | // PreparedMessage caches on the wire representations of a message payload. 15 | // Use PreparedMessage to efficiently send a message payload to multiple 16 | // connections. PreparedMessage is especially useful when compression is used 17 | // because the CPU and memory expensive compression operation can be executed 18 | // once for a given set of compression options. 19 | type PreparedMessage struct { 20 | messageType int 21 | data []byte 22 | mu sync.Mutex 23 | frames map[prepareKey]*preparedFrame 24 | } 25 | 26 | // prepareKey defines a unique set of options to cache prepared frames in PreparedMessage. 27 | type prepareKey struct { 28 | isServer bool 29 | compress bool 30 | compressionLevel int 31 | } 32 | 33 | // preparedFrame contains data in wire representation. 34 | type preparedFrame struct { 35 | once sync.Once 36 | data []byte 37 | } 38 | 39 | // NewPreparedMessage returns an initialized PreparedMessage. You can then send 40 | // it to connection using WritePreparedMessage method. Valid wire 41 | // representation will be calculated lazily only once for a set of current 42 | // connection options. 43 | func NewPreparedMessage(messageType int, data []byte) (*PreparedMessage, error) { 44 | pm := &PreparedMessage{ 45 | messageType: messageType, 46 | frames: make(map[prepareKey]*preparedFrame), 47 | data: data, 48 | } 49 | 50 | // Prepare a plain server frame. 51 | _, frameData, err := pm.frame(prepareKey{isServer: true, compress: false}) 52 | if err != nil { 53 | return nil, err 54 | } 55 | 56 | // To protect against caller modifying the data argument, remember the data 57 | // copied to the plain server frame. 58 | pm.data = frameData[len(frameData)-len(data):] 59 | return pm, nil 60 | } 61 | 62 | func (pm *PreparedMessage) frame(key prepareKey) (int, []byte, error) { 63 | pm.mu.Lock() 64 | frame, ok := pm.frames[key] 65 | if !ok { 66 | frame = &preparedFrame{} 67 | pm.frames[key] = frame 68 | } 69 | pm.mu.Unlock() 70 | 71 | var err error 72 | frame.once.Do(func() { 73 | // Prepare a frame using a 'fake' connection. 74 | // TODO: Refactor code in conn.go to allow more direct construction of 75 | // the frame. 76 | mu := make(chan bool, 1) 77 | mu <- true 78 | var nc prepareConn 79 | c := &Conn{ 80 | conn: &nc, 81 | mu: mu, 82 | isServer: key.isServer, 83 | compressionLevel: key.compressionLevel, 84 | enableWriteCompression: true, 85 | writeBuf: make([]byte, defaultWriteBufferSize+maxFrameHeaderSize), 86 | } 87 | if key.compress { 88 | c.newCompressionWriter = compressNoContextTakeover 89 | } 90 | err = c.WriteMessage(pm.messageType, pm.data) 91 | frame.data = nc.buf.Bytes() 92 | }) 93 | return pm.messageType, frame.data, err 94 | } 95 | 96 | type prepareConn struct { 97 | buf bytes.Buffer 98 | net.Conn 99 | } 100 | 101 | func (pc *prepareConn) Write(p []byte) (int, error) { return pc.buf.Write(p) } 102 | func (pc *prepareConn) SetWriteDeadline(t time.Time) error { return nil } 103 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/websocket/proxy.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Gorilla WebSocket Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package websocket 6 | 7 | import ( 8 | "bufio" 9 | "encoding/base64" 10 | "errors" 11 | "net" 12 | "net/http" 13 | "net/url" 14 | "strings" 15 | ) 16 | 17 | type netDialerFunc func(network, addr string) (net.Conn, error) 18 | 19 | func (fn netDialerFunc) Dial(network, addr string) (net.Conn, error) { 20 | return fn(network, addr) 21 | } 22 | 23 | func init() { 24 | proxy_RegisterDialerType("http", func(proxyURL *url.URL, forwardDialer proxy_Dialer) (proxy_Dialer, error) { 25 | return &httpProxyDialer{proxyURL: proxyURL, fowardDial: forwardDialer.Dial}, nil 26 | }) 27 | } 28 | 29 | type httpProxyDialer struct { 30 | proxyURL *url.URL 31 | fowardDial func(network, addr string) (net.Conn, error) 32 | } 33 | 34 | func (hpd *httpProxyDialer) Dial(network string, addr string) (net.Conn, error) { 35 | hostPort, _ := hostPortNoPort(hpd.proxyURL) 36 | conn, err := hpd.fowardDial(network, hostPort) 37 | if err != nil { 38 | return nil, err 39 | } 40 | 41 | connectHeader := make(http.Header) 42 | if user := hpd.proxyURL.User; user != nil { 43 | proxyUser := user.Username() 44 | if proxyPassword, passwordSet := user.Password(); passwordSet { 45 | credential := base64.StdEncoding.EncodeToString([]byte(proxyUser + ":" + proxyPassword)) 46 | connectHeader.Set("Proxy-Authorization", "Basic "+credential) 47 | } 48 | } 49 | 50 | connectReq := &http.Request{ 51 | Method: "CONNECT", 52 | URL: &url.URL{Opaque: addr}, 53 | Host: addr, 54 | Header: connectHeader, 55 | } 56 | 57 | if err := connectReq.Write(conn); err != nil { 58 | conn.Close() 59 | return nil, err 60 | } 61 | 62 | // Read response. It's OK to use and discard buffered reader here becaue 63 | // the remote server does not speak until spoken to. 64 | br := bufio.NewReader(conn) 65 | resp, err := http.ReadResponse(br, connectReq) 66 | if err != nil { 67 | conn.Close() 68 | return nil, err 69 | } 70 | 71 | if resp.StatusCode != 200 { 72 | conn.Close() 73 | f := strings.SplitN(resp.Status, " ", 2) 74 | return nil, errors.New(f[1]) 75 | } 76 | return conn, nil 77 | } 78 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/websocket/trace.go: -------------------------------------------------------------------------------- 1 | // +build go1.8 2 | 3 | package websocket 4 | 5 | import ( 6 | "crypto/tls" 7 | "net/http/httptrace" 8 | ) 9 | 10 | func doHandshakeWithTrace(trace *httptrace.ClientTrace, tlsConn *tls.Conn, cfg *tls.Config) error { 11 | if trace.TLSHandshakeStart != nil { 12 | trace.TLSHandshakeStart() 13 | } 14 | err := doHandshake(tlsConn, cfg) 15 | if trace.TLSHandshakeDone != nil { 16 | trace.TLSHandshakeDone(tlsConn.ConnectionState(), err) 17 | } 18 | return err 19 | } 20 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/websocket/trace_17.go: -------------------------------------------------------------------------------- 1 | // +build !go1.8 2 | 3 | package websocket 4 | 5 | import ( 6 | "crypto/tls" 7 | "net/http/httptrace" 8 | ) 9 | 10 | func doHandshakeWithTrace(trace *httptrace.ClientTrace, tlsConn *tls.Conn, cfg *tls.Config) error { 11 | return doHandshake(tlsConn, cfg) 12 | } 13 | -------------------------------------------------------------------------------- /vendor/github.com/hashicorp/go-cleanhttp/README.md: -------------------------------------------------------------------------------- 1 | # cleanhttp 2 | 3 | Functions for accessing "clean" Go http.Client values 4 | 5 | ------------- 6 | 7 | The Go standard library contains a default `http.Client` called 8 | `http.DefaultClient`. It is a common idiom in Go code to start with 9 | `http.DefaultClient` and tweak it as necessary, and in fact, this is 10 | encouraged; from the `http` package documentation: 11 | 12 | > The Client's Transport typically has internal state (cached TCP connections), 13 | so Clients should be reused instead of created as needed. Clients are safe for 14 | concurrent use by multiple goroutines. 15 | 16 | Unfortunately, this is a shared value, and it is not uncommon for libraries to 17 | assume that they are free to modify it at will. With enough dependencies, it 18 | can be very easy to encounter strange problems and race conditions due to 19 | manipulation of this shared value across libraries and goroutines (clients are 20 | safe for concurrent use, but writing values to the client struct itself is not 21 | protected). 22 | 23 | Making things worse is the fact that a bare `http.Client` will use a default 24 | `http.Transport` called `http.DefaultTransport`, which is another global value 25 | that behaves the same way. So it is not simply enough to replace 26 | `http.DefaultClient` with `&http.Client{}`. 27 | 28 | This repository provides some simple functions to get a "clean" `http.Client` 29 | -- one that uses the same default values as the Go standard library, but 30 | returns a client that does not share any state with other clients. 31 | -------------------------------------------------------------------------------- /vendor/github.com/hashicorp/go-cleanhttp/cleanhttp.go: -------------------------------------------------------------------------------- 1 | package cleanhttp 2 | 3 | import ( 4 | "net" 5 | "net/http" 6 | "runtime" 7 | "time" 8 | ) 9 | 10 | // DefaultTransport returns a new http.Transport with similar default values to 11 | // http.DefaultTransport, but with idle connections and keepalives disabled. 12 | func DefaultTransport() *http.Transport { 13 | transport := DefaultPooledTransport() 14 | transport.DisableKeepAlives = true 15 | transport.MaxIdleConnsPerHost = -1 16 | return transport 17 | } 18 | 19 | // DefaultPooledTransport returns a new http.Transport with similar default 20 | // values to http.DefaultTransport. Do not use this for transient transports as 21 | // it can leak file descriptors over time. Only use this for transports that 22 | // will be re-used for the same host(s). 23 | func DefaultPooledTransport() *http.Transport { 24 | transport := &http.Transport{ 25 | Proxy: http.ProxyFromEnvironment, 26 | DialContext: (&net.Dialer{ 27 | Timeout: 30 * time.Second, 28 | KeepAlive: 30 * time.Second, 29 | DualStack: true, 30 | }).DialContext, 31 | MaxIdleConns: 100, 32 | IdleConnTimeout: 90 * time.Second, 33 | TLSHandshakeTimeout: 10 * time.Second, 34 | ExpectContinueTimeout: 1 * time.Second, 35 | MaxIdleConnsPerHost: runtime.GOMAXPROCS(0) + 1, 36 | } 37 | return transport 38 | } 39 | 40 | // DefaultClient returns a new http.Client with similar default values to 41 | // http.Client, but with a non-shared Transport, idle connections disabled, and 42 | // keepalives disabled. 43 | func DefaultClient() *http.Client { 44 | return &http.Client{ 45 | Transport: DefaultTransport(), 46 | } 47 | } 48 | 49 | // DefaultPooledClient returns a new http.Client with similar default values to 50 | // http.Client, but with a shared Transport. Do not use this function for 51 | // transient clients as it can leak file descriptors over time. Only use this 52 | // for clients that will be re-used for the same host(s). 53 | func DefaultPooledClient() *http.Client { 54 | return &http.Client{ 55 | Transport: DefaultPooledTransport(), 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /vendor/github.com/hashicorp/go-cleanhttp/doc.go: -------------------------------------------------------------------------------- 1 | // Package cleanhttp offers convenience utilities for acquiring "clean" 2 | // http.Transport and http.Client structs. 3 | // 4 | // Values set on http.DefaultClient and http.DefaultTransport affect all 5 | // callers. This can have detrimental effects, esepcially in TLS contexts, 6 | // where client or root certificates set to talk to multiple endpoints can end 7 | // up displacing each other, leading to hard-to-debug issues. This package 8 | // provides non-shared http.Client and http.Transport structs to ensure that 9 | // the configuration will not be overwritten by other parts of the application 10 | // or dependencies. 11 | // 12 | // The DefaultClient and DefaultTransport functions disable idle connections 13 | // and keepalives. Without ensuring that idle connections are closed before 14 | // garbage collection, short-term clients/transports can leak file descriptors, 15 | // eventually leading to "too many open files" errors. If you will be 16 | // connecting to the same hosts repeatedly from the same client, you can use 17 | // DefaultPooledClient to receive a client that has connection pooling 18 | // semantics similar to http.DefaultClient. 19 | // 20 | package cleanhttp 21 | -------------------------------------------------------------------------------- /vendor/github.com/hashicorp/go-cleanhttp/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/hashicorp/go-cleanhttp 2 | -------------------------------------------------------------------------------- /vendor/github.com/hashicorp/go-cleanhttp/handlers.go: -------------------------------------------------------------------------------- 1 | package cleanhttp 2 | 3 | import ( 4 | "net/http" 5 | "strings" 6 | "unicode" 7 | ) 8 | 9 | // HandlerInput provides input options to cleanhttp's handlers 10 | type HandlerInput struct { 11 | ErrStatus int 12 | } 13 | 14 | // PrintablePathCheckHandler is a middleware that ensures the request path 15 | // contains only printable runes. 16 | func PrintablePathCheckHandler(next http.Handler, input *HandlerInput) http.Handler { 17 | // Nil-check on input to make it optional 18 | if input == nil { 19 | input = &HandlerInput{ 20 | ErrStatus: http.StatusBadRequest, 21 | } 22 | } 23 | 24 | // Default to http.StatusBadRequest on error 25 | if input.ErrStatus == 0 { 26 | input.ErrStatus = http.StatusBadRequest 27 | } 28 | 29 | return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 30 | if r != nil { 31 | // Check URL path for non-printable characters 32 | idx := strings.IndexFunc(r.URL.Path, func(c rune) bool { 33 | return !unicode.IsPrint(c) 34 | }) 35 | 36 | if idx != -1 { 37 | w.WriteHeader(input.ErrStatus) 38 | return 39 | } 40 | 41 | if next != nil { 42 | next.ServeHTTP(w, r) 43 | } 44 | } 45 | 46 | return 47 | }) 48 | } 49 | -------------------------------------------------------------------------------- /vendor/github.com/heptio/workgroup/.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | *.swo 3 | vendor/ 4 | -------------------------------------------------------------------------------- /vendor/github.com/heptio/workgroup/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | go_import_path: github.com/heptio/workgroup 3 | go: 4 | - 1.10.x 5 | 6 | sudo: false 7 | 8 | script: 9 | - make check 10 | -------------------------------------------------------------------------------- /vendor/github.com/heptio/workgroup/CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Heptio Community Code of Conduct 2 | 3 | ## Contributor Code of Conduct 4 | 5 | As contributors and maintainers of this project, and in the interest of fostering 6 | an open and welcoming community, we pledge to respect all people who contribute 7 | through reporting issues, posting feature requests, updating documentation, 8 | submitting pull requests or patches, and other activities. 9 | 10 | We are committed to making participation in this project a harassment-free experience for 11 | everyone, regardless of level of experience, gender, gender identity and expression, 12 | sexual orientation, disability, personal appearance, body size, race, ethnicity, age, 13 | religion, or nationality. 14 | 15 | Examples of unacceptable behavior by participants include: 16 | 17 | * The use of sexualized language or imagery 18 | * Personal attacks 19 | * Trolling or insulting/derogatory comments 20 | * Public or private harassment 21 | * Publishing other's private information, such as physical or electronic addresses, without explicit permission 22 | * Other unethical or unprofessional conduct. 23 | 24 | Project maintainers have the right and responsibility to remove, edit, or reject 25 | comments, commits, code, wiki edits, issues, and other contributions that are not 26 | aligned to this Code of Conduct. By adopting this Code of Conduct, project maintainers 27 | commit themselves to fairly and consistently applying these principles to every aspect 28 | of managing this project. Project maintainers who do not follow or enforce the Code of 29 | Conduct may be permanently removed from the project team. 30 | 31 | This code of conduct applies both within project spaces and in public spaces 32 | when an individual is representing the project or its community. 33 | 34 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project maintainer(s). 35 | 36 | This Code of Conduct is adapted from the [CNCF Code of Conduct](https://github.com/cncf/foundation/blob/master/code-of-conduct.md) and [Contributor Covenant](http://contributor-covenant.org/version/1/2/0/), version 1.2.0. 37 | -------------------------------------------------------------------------------- /vendor/github.com/heptio/workgroup/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Thanks for taking the time to join our community and start contributing. 4 | These guidelines will help you get started with the Cruise project. 5 | Please note that we require [DCO sign off](#dco-sign-off). 6 | 7 | ## Contribution workflow 8 | 9 | This section describes the process for contributing a bug fix or new feature. 10 | 11 | ### Before you submit a pull request 12 | 13 | This project operates according to the _talk, then code_ rule. 14 | If you plan to submit a pull request for anything more than a typo or obvious bug fix, first you _should_ [raise an issue][6] to discuss your proposal, before submitting any code. 15 | 16 | ### Pre commit CI 17 | 18 | Before a change is submitted it should pass all the pre commit CI jobs. 19 | If there are unrelated test failures the change can be merged so long as a reference to an issue that tracks the test failures is provided. 20 | 21 | Once a change lands in master it will be built and available at this tag, `gcr.io/heptio-images/cruise:master`. 22 | 23 | ## DCO Sign off 24 | 25 | All authors to the project retain copyright to their work. However, to ensure 26 | that they are only submitting work that they have rights to, we are requiring 27 | everyone to acknowledge this by signing their work. 28 | 29 | Any copyright notices in this repository should specify the authors as "The 30 | project authors". 31 | 32 | To sign your work, just add a line like this at the end of your commit message: 33 | 34 | ``` 35 | Signed-off-by: Joe Beda 36 | ``` 37 | 38 | This can easily be done with the `--signoff` option to `git commit`. 39 | 40 | By doing this you state that you can certify the following (from https://developercertificate.org/): 41 | 42 | ``` 43 | Developer Certificate of Origin 44 | Version 1.1 45 | 46 | Copyright (C) 2004, 2006 The Linux Foundation and its contributors. 47 | 1 Letterman Drive 48 | Suite D4700 49 | San Francisco, CA, 94129 50 | 51 | Everyone is permitted to copy and distribute verbatim copies of this 52 | license document, but changing it is not allowed. 53 | 54 | 55 | Developer's Certificate of Origin 1.1 56 | 57 | By making a contribution to this project, I certify that: 58 | 59 | (a) The contribution was created in whole or in part by me and I 60 | have the right to submit it under the open source license 61 | indicated in the file; or 62 | 63 | (b) The contribution is based upon previous work that, to the best 64 | of my knowledge, is covered under an appropriate open source 65 | license and I have the right under that license to submit that 66 | work with modifications, whether created in whole or in part 67 | by me, under the same open source license (unless I am 68 | permitted to submit under a different license), as indicated 69 | in the file; or 70 | 71 | (c) The contribution was provided directly to me by some other 72 | person who certified (a), (b) or (c) and I have not modified 73 | it. 74 | 75 | (d) I understand and agree that this project and the contribution 76 | are public and that a record of the contribution (including all 77 | personal information I submit with it, including my sign-off) is 78 | maintained indefinitely and may be redistributed consistent with 79 | this project or the open source license(s) involved. 80 | ``` 81 | 82 | [1]: https://golang.org/dl/ 83 | [2]: https://github.com/golang/dep 84 | [3]: https://golang.org/doc/code.html 85 | [4]: https://golang.org/pkg/testing/ 86 | [5]: https://developercertificate.org/ 87 | [6]: https://github.com/heptio/workgroup/issues 88 | -------------------------------------------------------------------------------- /vendor/github.com/heptio/workgroup/Makefile: -------------------------------------------------------------------------------- 1 | PKGS := $(shell go list ./...) 2 | 3 | test: install 4 | go test ./... 5 | 6 | check: test vet staticcheck unused 7 | @echo Checking code is gofmted 8 | @bash -c 'if [ -n "$(gofmt -s -l .)" ]; then echo "Go code is not formatted:"; gofmt -s -d -e .; exit 1;fi' 9 | 10 | install: 11 | go install -v ./... 12 | 13 | vet: | test 14 | go vet ./... 15 | 16 | staticcheck: 17 | @go get honnef.co/go/tools/cmd/staticcheck 18 | staticcheck $(PKGS) 19 | 20 | unused: 21 | @go get honnef.co/go/tools/cmd/unused 22 | unused $(PKGS) 23 | -------------------------------------------------------------------------------- /vendor/github.com/heptio/workgroup/README.md: -------------------------------------------------------------------------------- 1 | # Heptio Workgroup 2 | 3 | **Maintainers:** [Heptio][0] 4 | 5 | [![Build Status][1]][2] 6 | 7 | [![godoc][3]][4] 8 | 9 | ## Overview 10 | Workgroup is a small utility to manage the lifetime of a set of related goroutines. 11 | 12 | ## Examples 13 | 14 | ### http.Serve 15 | 16 | ``` 17 | var g workgroup.Group 18 | 19 | g.Add(func(stop <-chan struct{}) error { 20 | l, err := net.Listen("tcp", ":80") // listen on port 80 21 | if err != nil { 22 | return err 23 | } 24 | 25 | go func() { 26 | <-stop // close listener on stop request 27 | l.Close() 28 | }() 29 | return http.Serve(l, mux) 30 | }) 31 | g.Run() 32 | ``` 33 | 34 | ## Related work 35 | 36 | `workgroup.Group` is heavily inspired by prior art including oklog's [`run.Group`][9] and Gustavo Niemeyer's [`tomb`][10] packages. 37 | 38 | ## Contributing 39 | 40 | Thanks for taking the time to join our community and start contributing! 41 | 42 | Bug reports are most welcome, but with the exception of #5, this project is closed. 43 | 44 | * Please familiarize yourself with the [Code of Conduct][8] before contributing. 45 | * See [CONTRIBUTING.md][5] for information about setting up your environment, the workflow that we expect, and instructions on the developer certificate of origin that we require. 46 | 47 | ## Changelog 48 | 49 | See [the list of releases][6] to find out about feature changes. 50 | 51 | [0]: https://github.com/heptio 52 | [1]: https://travis-ci.org/heptio/workgroup.svg?branch=master 53 | [2]: https://travis-ci.org/heptio/workgroup 54 | [3]: https://godoc.org/github.com/heptio/workgroup?status.svg 55 | [4]: https://godoc.org/github.com/heptio/workgroup 56 | [5]: /CONTRIBUTING.md 57 | [6]: https://github.com/heptio/contour/releases 58 | [8]: /CODE_OF_CONDUCT.md 59 | [9]: https://github.com/oklog/run 60 | [10]: https://godoc.org/gopkg.in/tomb.v2 61 | -------------------------------------------------------------------------------- /vendor/github.com/heptio/workgroup/group.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 Heptio 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | // workgroup provides a mechanism for controlling the lifetime 15 | // of a set of related goroutines. 16 | package workgroup 17 | 18 | import "sync" 19 | 20 | // A Group manages a set of goroutines with related lifetimes. 21 | // The zero value for a Group is fully usable without initalisation. 22 | type Group struct { 23 | fn []func(<-chan struct{}) error 24 | } 25 | 26 | // Add adds a function to the Group. 27 | // The function will be exectuted in its own goroutine when Run is called. 28 | // Add must be called before Run. 29 | func (g *Group) Add(fn func(<-chan struct{}) error) { 30 | g.fn = append(g.fn, fn) 31 | } 32 | 33 | // Run exectues each function registered via Add in its own goroutine. 34 | // Run blocks until all functions have returned. 35 | // The first function to return will trigger the closure of the channel 36 | // passed to each function, who should in turn, return. 37 | // The return value from the first function to exit will be returned to 38 | // the caller of Run. 39 | func (g *Group) Run() error { 40 | 41 | // if there are no registered functions, return immediately. 42 | if len(g.fn) < 1 { 43 | return nil 44 | } 45 | 46 | var wg sync.WaitGroup 47 | wg.Add(len(g.fn)) 48 | 49 | stop := make(chan struct{}) 50 | result := make(chan error, len(g.fn)) 51 | for _, fn := range g.fn { 52 | go func(fn func(<-chan struct{}) error) { 53 | defer wg.Done() 54 | result <- fn(stop) 55 | }(fn) 56 | } 57 | 58 | defer wg.Wait() 59 | defer close(stop) 60 | return <-result 61 | } 62 | -------------------------------------------------------------------------------- /vendor/github.com/mailru/easyjson/.gitignore: -------------------------------------------------------------------------------- 1 | .root 2 | *_easyjson.go 3 | *.iml 4 | .idea 5 | *.swp 6 | -------------------------------------------------------------------------------- /vendor/github.com/mailru/easyjson/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | 3 | go: 4 | - tip 5 | install: 6 | - go get github.com/ugorji/go/codec 7 | - go get github.com/pquerna/ffjson/fflib/v1 8 | - go get github.com/json-iterator/go 9 | - go get golang.org/x/lint/golint 10 | -------------------------------------------------------------------------------- /vendor/github.com/mailru/easyjson/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016 Mail.Ru Group 2 | 3 | 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: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | 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. 8 | -------------------------------------------------------------------------------- /vendor/github.com/mailru/easyjson/Makefile: -------------------------------------------------------------------------------- 1 | PKG=github.com/mailru/easyjson 2 | GOPATH:=$(PWD)/.root:$(GOPATH) 3 | export GOPATH 4 | 5 | all: test 6 | 7 | .root/src/$(PKG): 8 | mkdir -p $@ 9 | for i in $$PWD/* ; do ln -s $$i $@/`basename $$i` ; done 10 | 11 | root: .root/src/$(PKG) 12 | 13 | clean: 14 | rm -rf .root 15 | rm -rf tests/*_easyjson.go 16 | 17 | build: 18 | go build -i -o .root/bin/easyjson $(PKG)/easyjson 19 | 20 | generate: root build 21 | .root/bin/easyjson -stubs \ 22 | .root/src/$(PKG)/tests/snake.go \ 23 | .root/src/$(PKG)/tests/data.go \ 24 | .root/src/$(PKG)/tests/omitempty.go \ 25 | .root/src/$(PKG)/tests/nothing.go \ 26 | .root/src/$(PKG)/tests/named_type.go \ 27 | .root/src/$(PKG)/tests/custom_map_key_type.go \ 28 | .root/src/$(PKG)/tests/embedded_type.go \ 29 | .root/src/$(PKG)/tests/reference_to_pointer.go \ 30 | 31 | .root/bin/easyjson -all .root/src/$(PKG)/tests/data.go 32 | .root/bin/easyjson -all .root/src/$(PKG)/tests/nothing.go 33 | .root/bin/easyjson -all .root/src/$(PKG)/tests/errors.go 34 | .root/bin/easyjson -snake_case .root/src/$(PKG)/tests/snake.go 35 | .root/bin/easyjson -omit_empty .root/src/$(PKG)/tests/omitempty.go 36 | .root/bin/easyjson -build_tags=use_easyjson .root/src/$(PKG)/benchmark/data.go 37 | .root/bin/easyjson .root/src/$(PKG)/tests/nested_easy.go 38 | .root/bin/easyjson .root/src/$(PKG)/tests/named_type.go 39 | .root/bin/easyjson .root/src/$(PKG)/tests/custom_map_key_type.go 40 | .root/bin/easyjson .root/src/$(PKG)/tests/embedded_type.go 41 | .root/bin/easyjson .root/src/$(PKG)/tests/reference_to_pointer.go 42 | .root/bin/easyjson .root/src/$(PKG)/tests/key_marshaler_map.go 43 | .root/bin/easyjson -disallow_unknown_fields .root/src/$(PKG)/tests/disallow_unknown.go 44 | 45 | test: generate root 46 | go test \ 47 | $(PKG)/tests \ 48 | $(PKG)/jlexer \ 49 | $(PKG)/gen \ 50 | $(PKG)/buffer 51 | go test -benchmem -tags use_easyjson -bench . $(PKG)/benchmark 52 | golint -set_exit_status .root/src/$(PKG)/tests/*_easyjson.go 53 | 54 | bench-other: generate root 55 | @go test -benchmem -bench . $(PKG)/benchmark 56 | @go test -benchmem -tags use_ffjson -bench . $(PKG)/benchmark 57 | @go test -benchmem -tags use_jsoniter -bench . $(PKG)/benchmark 58 | @go test -benchmem -tags use_codec -bench . $(PKG)/benchmark 59 | 60 | bench-python: 61 | benchmark/ujson.sh 62 | 63 | 64 | .PHONY: root clean generate test build 65 | -------------------------------------------------------------------------------- /vendor/github.com/mailru/easyjson/helpers.go: -------------------------------------------------------------------------------- 1 | // Package easyjson contains marshaler/unmarshaler interfaces and helper functions. 2 | package easyjson 3 | 4 | import ( 5 | "io" 6 | "io/ioutil" 7 | "net/http" 8 | "strconv" 9 | 10 | "github.com/mailru/easyjson/jlexer" 11 | "github.com/mailru/easyjson/jwriter" 12 | ) 13 | 14 | // Marshaler is an easyjson-compatible marshaler interface. 15 | type Marshaler interface { 16 | MarshalEasyJSON(w *jwriter.Writer) 17 | } 18 | 19 | // Marshaler is an easyjson-compatible unmarshaler interface. 20 | type Unmarshaler interface { 21 | UnmarshalEasyJSON(w *jlexer.Lexer) 22 | } 23 | 24 | // Optional defines an undefined-test method for a type to integrate with 'omitempty' logic. 25 | type Optional interface { 26 | IsDefined() bool 27 | } 28 | 29 | // Marshal returns data as a single byte slice. Method is suboptimal as the data is likely to be copied 30 | // from a chain of smaller chunks. 31 | func Marshal(v Marshaler) ([]byte, error) { 32 | w := jwriter.Writer{} 33 | v.MarshalEasyJSON(&w) 34 | return w.BuildBytes() 35 | } 36 | 37 | // MarshalToWriter marshals the data to an io.Writer. 38 | func MarshalToWriter(v Marshaler, w io.Writer) (written int, err error) { 39 | jw := jwriter.Writer{} 40 | v.MarshalEasyJSON(&jw) 41 | return jw.DumpTo(w) 42 | } 43 | 44 | // MarshalToHTTPResponseWriter sets Content-Length and Content-Type headers for the 45 | // http.ResponseWriter, and send the data to the writer. started will be equal to 46 | // false if an error occurred before any http.ResponseWriter methods were actually 47 | // invoked (in this case a 500 reply is possible). 48 | func MarshalToHTTPResponseWriter(v Marshaler, w http.ResponseWriter) (started bool, written int, err error) { 49 | jw := jwriter.Writer{} 50 | v.MarshalEasyJSON(&jw) 51 | if jw.Error != nil { 52 | return false, 0, jw.Error 53 | } 54 | w.Header().Set("Content-Type", "application/json") 55 | w.Header().Set("Content-Length", strconv.Itoa(jw.Size())) 56 | 57 | started = true 58 | written, err = jw.DumpTo(w) 59 | return 60 | } 61 | 62 | // Unmarshal decodes the JSON in data into the object. 63 | func Unmarshal(data []byte, v Unmarshaler) error { 64 | l := jlexer.Lexer{Data: data} 65 | v.UnmarshalEasyJSON(&l) 66 | return l.Error() 67 | } 68 | 69 | // UnmarshalFromReader reads all the data in the reader and decodes as JSON into the object. 70 | func UnmarshalFromReader(r io.Reader, v Unmarshaler) error { 71 | data, err := ioutil.ReadAll(r) 72 | if err != nil { 73 | return err 74 | } 75 | l := jlexer.Lexer{Data: data} 76 | v.UnmarshalEasyJSON(&l) 77 | return l.Error() 78 | } 79 | -------------------------------------------------------------------------------- /vendor/github.com/mailru/easyjson/jlexer/bytestostr.go: -------------------------------------------------------------------------------- 1 | // This file will only be included to the build if neither 2 | // easyjson_nounsafe nor appengine build tag is set. See README notes 3 | // for more details. 4 | 5 | //+build !easyjson_nounsafe 6 | //+build !appengine 7 | 8 | package jlexer 9 | 10 | import ( 11 | "reflect" 12 | "unsafe" 13 | ) 14 | 15 | // bytesToStr creates a string pointing at the slice to avoid copying. 16 | // 17 | // Warning: the string returned by the function should be used with care, as the whole input data 18 | // chunk may be either blocked from being freed by GC because of a single string or the buffer.Data 19 | // may be garbage-collected even when the string exists. 20 | func bytesToStr(data []byte) string { 21 | h := (*reflect.SliceHeader)(unsafe.Pointer(&data)) 22 | shdr := reflect.StringHeader{Data: h.Data, Len: h.Len} 23 | return *(*string)(unsafe.Pointer(&shdr)) 24 | } 25 | -------------------------------------------------------------------------------- /vendor/github.com/mailru/easyjson/jlexer/bytestostr_nounsafe.go: -------------------------------------------------------------------------------- 1 | // This file is included to the build if any of the buildtags below 2 | // are defined. Refer to README notes for more details. 3 | 4 | //+build easyjson_nounsafe appengine 5 | 6 | package jlexer 7 | 8 | // bytesToStr creates a string normally from []byte 9 | // 10 | // Note that this method is roughly 1.5x slower than using the 'unsafe' method. 11 | func bytesToStr(data []byte) string { 12 | return string(data) 13 | } 14 | -------------------------------------------------------------------------------- /vendor/github.com/mailru/easyjson/jlexer/error.go: -------------------------------------------------------------------------------- 1 | package jlexer 2 | 3 | import "fmt" 4 | 5 | // LexerError implements the error interface and represents all possible errors that can be 6 | // generated during parsing the JSON data. 7 | type LexerError struct { 8 | Reason string 9 | Offset int 10 | Data string 11 | } 12 | 13 | func (l *LexerError) Error() string { 14 | return fmt.Sprintf("parse error: %s near offset %d of '%s'", l.Reason, l.Offset, l.Data) 15 | } 16 | -------------------------------------------------------------------------------- /vendor/github.com/mailru/easyjson/raw.go: -------------------------------------------------------------------------------- 1 | package easyjson 2 | 3 | import ( 4 | "github.com/mailru/easyjson/jlexer" 5 | "github.com/mailru/easyjson/jwriter" 6 | ) 7 | 8 | // RawMessage is a raw piece of JSON (number, string, bool, object, array or 9 | // null) that is extracted without parsing and output as is during marshaling. 10 | type RawMessage []byte 11 | 12 | // MarshalEasyJSON does JSON marshaling using easyjson interface. 13 | func (v *RawMessage) MarshalEasyJSON(w *jwriter.Writer) { 14 | if len(*v) == 0 { 15 | w.RawString("null") 16 | } else { 17 | w.Raw(*v, nil) 18 | } 19 | } 20 | 21 | // UnmarshalEasyJSON does JSON unmarshaling using easyjson interface. 22 | func (v *RawMessage) UnmarshalEasyJSON(l *jlexer.Lexer) { 23 | *v = RawMessage(l.Raw()) 24 | } 25 | 26 | // UnmarshalJSON implements encoding/json.Unmarshaler interface. 27 | func (v *RawMessage) UnmarshalJSON(data []byte) error { 28 | *v = data 29 | return nil 30 | } 31 | 32 | var nullBytes = []byte("null") 33 | 34 | // MarshalJSON implements encoding/json.Marshaler interface. 35 | func (v RawMessage) MarshalJSON() ([]byte, error) { 36 | if len(v) == 0 { 37 | return nullBytes, nil 38 | } 39 | return v, nil 40 | } 41 | 42 | // IsDefined is required for integration with omitempty easyjson logic. 43 | func (v *RawMessage) IsDefined() bool { 44 | return len(*v) > 0 45 | } 46 | -------------------------------------------------------------------------------- /vendor/github.com/pmezard/go-difflib/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013, Patrick Mezard 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are 6 | met: 7 | 8 | Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in the 12 | documentation and/or other materials provided with the distribution. 13 | The names of its contributors may not be used to endorse or promote 14 | products derived from this software without specific prior written 15 | permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 18 | IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 19 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 20 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 23 | TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 24 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 25 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 26 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /vendor/github.com/stretchr/testify/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2012-2018 Mat Ryer and Tyler Bunnell 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /vendor/github.com/stretchr/testify/assert/assertion_format.go.tmpl: -------------------------------------------------------------------------------- 1 | {{.CommentFormat}} 2 | func {{.DocInfo.Name}}f(t TestingT, {{.ParamsFormat}}) bool { 3 | if h, ok := t.(tHelper); ok { h.Helper() } 4 | return {{.DocInfo.Name}}(t, {{.ForwardedParamsFormat}}) 5 | } 6 | -------------------------------------------------------------------------------- /vendor/github.com/stretchr/testify/assert/assertion_forward.go.tmpl: -------------------------------------------------------------------------------- 1 | {{.CommentWithoutT "a"}} 2 | func (a *Assertions) {{.DocInfo.Name}}({{.Params}}) bool { 3 | if h, ok := a.t.(tHelper); ok { h.Helper() } 4 | return {{.DocInfo.Name}}(a.t, {{.ForwardedParams}}) 5 | } 6 | -------------------------------------------------------------------------------- /vendor/github.com/stretchr/testify/assert/doc.go: -------------------------------------------------------------------------------- 1 | // Package assert provides a set of comprehensive testing tools for use with the normal Go testing system. 2 | // 3 | // Example Usage 4 | // 5 | // The following is a complete example using assert in a standard test function: 6 | // import ( 7 | // "testing" 8 | // "github.com/stretchr/testify/assert" 9 | // ) 10 | // 11 | // func TestSomething(t *testing.T) { 12 | // 13 | // var a string = "Hello" 14 | // var b string = "Hello" 15 | // 16 | // assert.Equal(t, a, b, "The two words should be the same.") 17 | // 18 | // } 19 | // 20 | // if you assert many times, use the format below: 21 | // 22 | // import ( 23 | // "testing" 24 | // "github.com/stretchr/testify/assert" 25 | // ) 26 | // 27 | // func TestSomething(t *testing.T) { 28 | // assert := assert.New(t) 29 | // 30 | // var a string = "Hello" 31 | // var b string = "Hello" 32 | // 33 | // assert.Equal(a, b, "The two words should be the same.") 34 | // } 35 | // 36 | // Assertions 37 | // 38 | // Assertions allow you to easily write test code, and are global funcs in the `assert` package. 39 | // All assertion functions take, as the first argument, the `*testing.T` object provided by the 40 | // testing framework. This allows the assertion funcs to write the failings and other details to 41 | // the correct place. 42 | // 43 | // Every assertion function also takes an optional string message as the final argument, 44 | // allowing custom error messages to be appended to the message the assertion method outputs. 45 | package assert 46 | -------------------------------------------------------------------------------- /vendor/github.com/stretchr/testify/assert/errors.go: -------------------------------------------------------------------------------- 1 | package assert 2 | 3 | import ( 4 | "errors" 5 | ) 6 | 7 | // AnError is an error instance useful for testing. If the code does not care 8 | // about error specifics, and only needs to return the error for example, this 9 | // error should be used to make the test code more readable. 10 | var AnError = errors.New("assert.AnError general error for testing") 11 | -------------------------------------------------------------------------------- /vendor/github.com/stretchr/testify/assert/forward_assertions.go: -------------------------------------------------------------------------------- 1 | package assert 2 | 3 | // Assertions provides assertion methods around the 4 | // TestingT interface. 5 | type Assertions struct { 6 | t TestingT 7 | } 8 | 9 | // New makes a new Assertions object for the specified TestingT. 10 | func New(t TestingT) *Assertions { 11 | return &Assertions{ 12 | t: t, 13 | } 14 | } 15 | 16 | //go:generate sh -c "cd ../_codegen && go build && cd - && ../_codegen/_codegen -output-package=assert -template=assertion_forward.go.tmpl -include-format-funcs" 17 | -------------------------------------------------------------------------------- /vendor/github.com/urfave/negroni/.gitignore: -------------------------------------------------------------------------------- 1 | /coverage.txt 2 | -------------------------------------------------------------------------------- /vendor/github.com/urfave/negroni/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | 3 | sudo: false 4 | dist: trusty 5 | 6 | go: 7 | - 1.x 8 | - 1.2.x 9 | - 1.3.x 10 | - 1.4.x 11 | - 1.5.x 12 | - 1.6.x 13 | - 1.7.x 14 | - 1.8.x 15 | - master 16 | 17 | before_install: 18 | - find "${GOPATH%%:*}" -name '*.a' -delete 19 | - rm -rf "${GOPATH%%:*}/src/golang.org" 20 | - go get golang.org/x/tools/cover 21 | - go get golang.org/x/tools/cmd/cover 22 | 23 | script: 24 | - go test -race -coverprofile=coverage.txt -covermode=atomic 25 | 26 | after_success: 27 | - bash <(curl -s "https://codecov.io/bash") 28 | -------------------------------------------------------------------------------- /vendor/github.com/urfave/negroni/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | **ATTN**: This project uses [semantic versioning](http://semver.org/). 4 | 5 | ## [Unreleased] - 6 | 7 | ## [1.0.0] - 2018-09-01 8 | 9 | ### Fixed 10 | - `Logger` middleware now correctly handles paths containing a `%` instead of trying to treat it as a format specifier 11 | 12 | ## [0.3.0] - 2017-11-11 13 | ### Added 14 | - `With()` helper for building a new `Negroni` struct chaining handlers from 15 | existing `Negroni` structs 16 | - Format log output in `Logger` middleware via a configurable `text/template` 17 | string injectable via `.SetFormat`. Added `LoggerDefaultFormat` and 18 | `LoggerDefaultDateFormat` to configure the default template and date format 19 | used by the `Logger` middleware. 20 | - Support for HTTP/2 pusher support via `http.Pusher` interface for Go 1.8+. 21 | - `WrapFunc` to convert `http.HandlerFunc` into a `negroni.Handler` 22 | - `Formatter` field added to `Recovery` middleware to allow configuring how 23 | `panic`s are output. Default of `TextFormatter` (how it was output in 24 | `0.2.0`) used. `HTMLPanicFormatter` also added to allow easy outputing of 25 | `panic`s as HTML. 26 | 27 | ### Fixed 28 | - `Written()` correct returns `false` if no response header has been written 29 | - Only implement `http.CloseNotifier` with the `negroni.ResponseWriter` if the 30 | underlying `http.ResponseWriter` implements it (previously would always 31 | implement it and panic if the underlying `http.ResponseWriter` did not. 32 | 33 | ### Changed 34 | - Set default status to `0` in the case that no handler writes status -- was 35 | previously `200` (in 0.2.0, before that it was `0` so this reestablishes that 36 | behavior) 37 | - Catch `panic`s thrown by callbacks provided to the `Recovery` handler 38 | - Recovery middleware will set `text/plain` content-type if none is set 39 | - `ALogger` interface to allow custom logger outputs to be used with the 40 | `Logger` middleware. Changes embeded field in `negroni.Logger` from `Logger` 41 | to `ALogger`. 42 | - Default `Logger` middleware output changed to be more structure and verbose 43 | (also now configurable, see `Added`) 44 | - Automatically bind to port specified in `$PORT` in `.Run()` if an address is 45 | not passed in. Fall back to binding to `:8080` if no address specified 46 | (configuable via `DefaultAddress`). 47 | - `PanicHandlerFunc` added to `Recovery` middleware to enhance custom handling 48 | of `panic`s by providing additional information to the handler including the 49 | stack and the `http.Request`. `Recovery.ErrorHandlerFunc` was also added, but 50 | deprecated in favor of the new `PanicHandlerFunc`. 51 | 52 | ## [0.2.0] - 2016-05-10 53 | ### Added 54 | - Support for variadic handlers in `New()` 55 | - Added `Negroni.Handlers()` to fetch all of the handlers for a given chain 56 | - Allowed size in `Recovery` handler was bumped to 8k 57 | - `Negroni.UseFunc` to push another handler onto the chain 58 | 59 | ### Changed 60 | - Set the status before calling `beforeFuncs` so the information is available to them 61 | - Set default status to `200` in the case that no handler writes status -- was previously `0` 62 | - Panic if `nil` handler is given to `negroni.Use` 63 | 64 | ## 0.1.0 - 2013-07-22 65 | ### Added 66 | - Initial implementation. 67 | 68 | [Unreleased]: https://github.com/urfave/negroni/compare/v0.2.0...HEAD 69 | [0.2.0]: https://github.com/urfave/negroni/compare/v0.1.0...v0.2.0 70 | -------------------------------------------------------------------------------- /vendor/github.com/urfave/negroni/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Jeremy Saenz 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /vendor/github.com/urfave/negroni/doc.go: -------------------------------------------------------------------------------- 1 | // Package negroni is an idiomatic approach to web middleware in Go. It is tiny, non-intrusive, and encourages use of net/http Handlers. 2 | // 3 | // If you like the idea of Martini, but you think it contains too much magic, then Negroni is a great fit. 4 | // 5 | // For a full guide visit http://github.com/urfave/negroni 6 | // 7 | // package main 8 | // 9 | // import ( 10 | // "github.com/urfave/negroni" 11 | // "net/http" 12 | // "fmt" 13 | // ) 14 | // 15 | // func main() { 16 | // mux := http.NewServeMux() 17 | // mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) { 18 | // fmt.Fprintf(w, "Welcome to the home page!") 19 | // }) 20 | // 21 | // n := negroni.Classic() 22 | // n.UseHandler(mux) 23 | // n.Run(":3000") 24 | // } 25 | package negroni 26 | -------------------------------------------------------------------------------- /vendor/github.com/urfave/negroni/logger.go: -------------------------------------------------------------------------------- 1 | package negroni 2 | 3 | import ( 4 | "bytes" 5 | 6 | "log" 7 | "net/http" 8 | "os" 9 | "text/template" 10 | "time" 11 | ) 12 | 13 | // LoggerEntry is the structure passed to the template. 14 | type LoggerEntry struct { 15 | StartTime string 16 | Status int 17 | Duration time.Duration 18 | Hostname string 19 | Method string 20 | Path string 21 | Request *http.Request 22 | } 23 | 24 | // LoggerDefaultFormat is the format logged used by the default Logger instance. 25 | var LoggerDefaultFormat = "{{.StartTime}} | {{.Status}} | \t {{.Duration}} | {{.Hostname}} | {{.Method}} {{.Path}}" 26 | 27 | // LoggerDefaultDateFormat is the format used for date by the default Logger instance. 28 | var LoggerDefaultDateFormat = time.RFC3339 29 | 30 | // ALogger interface 31 | type ALogger interface { 32 | Println(v ...interface{}) 33 | Printf(format string, v ...interface{}) 34 | } 35 | 36 | // Logger is a middleware handler that logs the request as it goes in and the response as it goes out. 37 | type Logger struct { 38 | // ALogger implements just enough log.Logger interface to be compatible with other implementations 39 | ALogger 40 | dateFormat string 41 | template *template.Template 42 | } 43 | 44 | // NewLogger returns a new Logger instance 45 | func NewLogger() *Logger { 46 | logger := &Logger{ALogger: log.New(os.Stdout, "[negroni] ", 0), dateFormat: LoggerDefaultDateFormat} 47 | logger.SetFormat(LoggerDefaultFormat) 48 | return logger 49 | } 50 | 51 | func (l *Logger) SetFormat(format string) { 52 | l.template = template.Must(template.New("negroni_parser").Parse(format)) 53 | } 54 | 55 | func (l *Logger) SetDateFormat(format string) { 56 | l.dateFormat = format 57 | } 58 | 59 | func (l *Logger) ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) { 60 | start := time.Now() 61 | 62 | next(rw, r) 63 | 64 | res := rw.(ResponseWriter) 65 | log := LoggerEntry{ 66 | StartTime: start.Format(l.dateFormat), 67 | Status: res.Status(), 68 | Duration: time.Since(start), 69 | Hostname: r.Host, 70 | Method: r.Method, 71 | Path: r.URL.Path, 72 | Request: r, 73 | } 74 | 75 | buff := &bytes.Buffer{} 76 | l.template.Execute(buff, log) 77 | l.Println(buff.String()) 78 | } 79 | -------------------------------------------------------------------------------- /vendor/github.com/urfave/negroni/response_writer.go: -------------------------------------------------------------------------------- 1 | package negroni 2 | 3 | import ( 4 | "bufio" 5 | "fmt" 6 | "net" 7 | "net/http" 8 | ) 9 | 10 | // ResponseWriter is a wrapper around http.ResponseWriter that provides extra information about 11 | // the response. It is recommended that middleware handlers use this construct to wrap a responsewriter 12 | // if the functionality calls for it. 13 | type ResponseWriter interface { 14 | http.ResponseWriter 15 | http.Flusher 16 | // Status returns the status code of the response or 0 if the response has 17 | // not been written 18 | Status() int 19 | // Written returns whether or not the ResponseWriter has been written. 20 | Written() bool 21 | // Size returns the size of the response body. 22 | Size() int 23 | // Before allows for a function to be called before the ResponseWriter has been written to. This is 24 | // useful for setting headers or any other operations that must happen before a response has been written. 25 | Before(func(ResponseWriter)) 26 | } 27 | 28 | type beforeFunc func(ResponseWriter) 29 | 30 | // NewResponseWriter creates a ResponseWriter that wraps an http.ResponseWriter 31 | func NewResponseWriter(rw http.ResponseWriter) ResponseWriter { 32 | nrw := &responseWriter{ 33 | ResponseWriter: rw, 34 | } 35 | 36 | if _, ok := rw.(http.CloseNotifier); ok { 37 | return &responseWriterCloseNotifer{nrw} 38 | } 39 | 40 | return nrw 41 | } 42 | 43 | type responseWriter struct { 44 | http.ResponseWriter 45 | status int 46 | size int 47 | beforeFuncs []beforeFunc 48 | } 49 | 50 | func (rw *responseWriter) WriteHeader(s int) { 51 | rw.status = s 52 | rw.callBefore() 53 | rw.ResponseWriter.WriteHeader(s) 54 | } 55 | 56 | func (rw *responseWriter) Write(b []byte) (int, error) { 57 | if !rw.Written() { 58 | // The status will be StatusOK if WriteHeader has not been called yet 59 | rw.WriteHeader(http.StatusOK) 60 | } 61 | size, err := rw.ResponseWriter.Write(b) 62 | rw.size += size 63 | return size, err 64 | } 65 | 66 | func (rw *responseWriter) Status() int { 67 | return rw.status 68 | } 69 | 70 | func (rw *responseWriter) Size() int { 71 | return rw.size 72 | } 73 | 74 | func (rw *responseWriter) Written() bool { 75 | return rw.status != 0 76 | } 77 | 78 | func (rw *responseWriter) Before(before func(ResponseWriter)) { 79 | rw.beforeFuncs = append(rw.beforeFuncs, before) 80 | } 81 | 82 | func (rw *responseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) { 83 | hijacker, ok := rw.ResponseWriter.(http.Hijacker) 84 | if !ok { 85 | return nil, nil, fmt.Errorf("the ResponseWriter doesn't support the Hijacker interface") 86 | } 87 | return hijacker.Hijack() 88 | } 89 | 90 | func (rw *responseWriter) callBefore() { 91 | for i := len(rw.beforeFuncs) - 1; i >= 0; i-- { 92 | rw.beforeFuncs[i](rw) 93 | } 94 | } 95 | 96 | func (rw *responseWriter) Flush() { 97 | flusher, ok := rw.ResponseWriter.(http.Flusher) 98 | if ok { 99 | if !rw.Written() { 100 | // The status will be StatusOK if WriteHeader has not been called yet 101 | rw.WriteHeader(http.StatusOK) 102 | } 103 | flusher.Flush() 104 | } 105 | } 106 | 107 | type responseWriterCloseNotifer struct { 108 | *responseWriter 109 | } 110 | 111 | func (rw *responseWriterCloseNotifer) CloseNotify() <-chan bool { 112 | return rw.ResponseWriter.(http.CloseNotifier).CloseNotify() 113 | } 114 | -------------------------------------------------------------------------------- /vendor/github.com/urfave/negroni/response_writer_pusher.go: -------------------------------------------------------------------------------- 1 | //+build go1.8 2 | 3 | package negroni 4 | 5 | import ( 6 | "fmt" 7 | "net/http" 8 | ) 9 | 10 | func (rw *responseWriter) Push(target string, opts *http.PushOptions) error { 11 | pusher, ok := rw.ResponseWriter.(http.Pusher) 12 | if ok { 13 | return pusher.Push(target, opts) 14 | } 15 | return fmt.Errorf("the ResponseWriter doesn't support the Pusher interface") 16 | } 17 | -------------------------------------------------------------------------------- /vendor/github.com/urfave/negroni/static.go: -------------------------------------------------------------------------------- 1 | package negroni 2 | 3 | import ( 4 | "net/http" 5 | "path" 6 | "strings" 7 | ) 8 | 9 | // Static is a middleware handler that serves static files in the given 10 | // directory/filesystem. If the file does not exist on the filesystem, it 11 | // passes along to the next middleware in the chain. If you desire "fileserver" 12 | // type behavior where it returns a 404 for unfound files, you should consider 13 | // using http.FileServer from the Go stdlib. 14 | type Static struct { 15 | // Dir is the directory to serve static files from 16 | Dir http.FileSystem 17 | // Prefix is the optional prefix used to serve the static directory content 18 | Prefix string 19 | // IndexFile defines which file to serve as index if it exists. 20 | IndexFile string 21 | } 22 | 23 | // NewStatic returns a new instance of Static 24 | func NewStatic(directory http.FileSystem) *Static { 25 | return &Static{ 26 | Dir: directory, 27 | Prefix: "", 28 | IndexFile: "index.html", 29 | } 30 | } 31 | 32 | func (s *Static) ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) { 33 | if r.Method != "GET" && r.Method != "HEAD" { 34 | next(rw, r) 35 | return 36 | } 37 | file := r.URL.Path 38 | // if we have a prefix, filter requests by stripping the prefix 39 | if s.Prefix != "" { 40 | if !strings.HasPrefix(file, s.Prefix) { 41 | next(rw, r) 42 | return 43 | } 44 | file = file[len(s.Prefix):] 45 | if file != "" && file[0] != '/' { 46 | next(rw, r) 47 | return 48 | } 49 | } 50 | f, err := s.Dir.Open(file) 51 | if err != nil { 52 | // discard the error? 53 | next(rw, r) 54 | return 55 | } 56 | defer f.Close() 57 | 58 | fi, err := f.Stat() 59 | if err != nil { 60 | next(rw, r) 61 | return 62 | } 63 | 64 | // try to serve index file 65 | if fi.IsDir() { 66 | // redirect if missing trailing slash 67 | if !strings.HasSuffix(r.URL.Path, "/") { 68 | http.Redirect(rw, r, r.URL.Path+"/", http.StatusFound) 69 | return 70 | } 71 | 72 | file = path.Join(file, s.IndexFile) 73 | f, err = s.Dir.Open(file) 74 | if err != nil { 75 | next(rw, r) 76 | return 77 | } 78 | defer f.Close() 79 | 80 | fi, err = f.Stat() 81 | if err != nil || fi.IsDir() { 82 | next(rw, r) 83 | return 84 | } 85 | } 86 | 87 | http.ServeContent(rw, r, file, fi.ModTime(), f) 88 | } 89 | -------------------------------------------------------------------------------- /vendor/go.uber.org/atomic/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /vendor 3 | /cover 4 | cover.out 5 | lint.log 6 | 7 | # Binaries 8 | *.test 9 | 10 | # Profiling output 11 | *.prof 12 | -------------------------------------------------------------------------------- /vendor/go.uber.org/atomic/.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: go 3 | go_import_path: go.uber.org/atomic 4 | 5 | go: 6 | - 1.5 7 | - 1.6 8 | - tip 9 | 10 | cache: 11 | directories: 12 | - vendor 13 | 14 | install: 15 | - make install_ci 16 | 17 | script: 18 | - make test_ci 19 | - scripts/test-ubergo.sh 20 | - make lint 21 | - travis_retry goveralls -coverprofile=cover.out -service=travis-ci 22 | -------------------------------------------------------------------------------- /vendor/go.uber.org/atomic/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016 Uber Technologies, Inc. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /vendor/go.uber.org/atomic/Makefile: -------------------------------------------------------------------------------- 1 | PACKAGES := $(shell glide nv) 2 | # Many Go tools take file globs or directories as arguments instead of packages. 3 | PACKAGE_FILES ?= *.go 4 | 5 | 6 | # The linting tools evolve with each Go version, so run them only on the latest 7 | # stable release. 8 | GO_VERSION := $(shell go version | cut -d " " -f 3) 9 | GO_MINOR_VERSION := $(word 2,$(subst ., ,$(GO_VERSION))) 10 | LINTABLE_MINOR_VERSIONS := 7 8 11 | ifneq ($(filter $(LINTABLE_MINOR_VERSIONS),$(GO_MINOR_VERSION)),) 12 | SHOULD_LINT := true 13 | endif 14 | 15 | 16 | export GO15VENDOREXPERIMENT=1 17 | 18 | 19 | .PHONY: build 20 | build: 21 | go build -i $(PACKAGES) 22 | 23 | 24 | .PHONY: install 25 | install: 26 | glide --version || go get github.com/Masterminds/glide 27 | glide install 28 | 29 | 30 | .PHONY: test 31 | test: 32 | go test -cover -race $(PACKAGES) 33 | 34 | 35 | .PHONY: install_ci 36 | install_ci: install 37 | go get github.com/wadey/gocovmerge 38 | go get github.com/mattn/goveralls 39 | go get golang.org/x/tools/cmd/cover 40 | ifdef SHOULD_LINT 41 | go get github.com/golang/lint/golint 42 | endif 43 | 44 | .PHONY: lint 45 | lint: 46 | ifdef SHOULD_LINT 47 | @rm -rf lint.log 48 | @echo "Checking formatting..." 49 | @gofmt -d -s $(PACKAGE_FILES) 2>&1 | tee lint.log 50 | @echo "Checking vet..." 51 | @$(foreach dir,$(PACKAGE_FILES),go tool vet $(dir) 2>&1 | tee -a lint.log;) 52 | @echo "Checking lint..." 53 | @$(foreach dir,$(PKGS),golint $(dir) 2>&1 | tee -a lint.log;) 54 | @echo "Checking for unresolved FIXMEs..." 55 | @git grep -i fixme | grep -v -e vendor -e Makefile | tee -a lint.log 56 | @[ ! -s lint.log ] 57 | else 58 | @echo "Skipping linters on" $(GO_VERSION) 59 | endif 60 | 61 | 62 | .PHONY: test_ci 63 | test_ci: install_ci build 64 | ./scripts/cover.sh $(shell go list $(PACKAGES)) 65 | -------------------------------------------------------------------------------- /vendor/go.uber.org/atomic/README.md: -------------------------------------------------------------------------------- 1 | # atomic [![GoDoc][doc-img]][doc] [![Build Status][ci-img]][ci] [![Coverage Status][cov-img]][cov] 2 | 3 | Simple wrappers for primitive types to enforce atomic access. 4 | 5 | ## Installation 6 | `go get -u go.uber.org/atomic` 7 | 8 | ## Usage 9 | The standard library's `sync/atomic` is powerful, but it's easy to forget which 10 | variables must be accessed atomically. `go.uber.org/atomic` preserves all the 11 | functionality of the standard library, but wraps the primitive types to 12 | provide a safer, more convenient API. 13 | 14 | ```go 15 | var atom atomic.Uint32 16 | atom.Store(42) 17 | atom.Sub(2) 18 | atom.CAS(40, 11) 19 | ``` 20 | 21 | See the [documentation][doc] for a complete API specification. 22 | 23 | ## Development Status 24 | Stable. 25 | 26 |
27 | Released under the [MIT License](LICENSE.txt). 28 | 29 | [doc-img]: https://godoc.org/github.com/uber-go/atomic?status.svg 30 | [doc]: https://godoc.org/go.uber.org/atomic 31 | [ci-img]: https://travis-ci.org/uber-go/atomic.svg?branch=master 32 | [ci]: https://travis-ci.org/uber-go/atomic 33 | [cov-img]: https://coveralls.io/repos/github/uber-go/atomic/badge.svg?branch=master 34 | [cov]: https://coveralls.io/github/uber-go/atomic?branch=master 35 | -------------------------------------------------------------------------------- /vendor/go.uber.org/atomic/glide.lock: -------------------------------------------------------------------------------- 1 | hash: f14d51408e3e0e4f73b34e4039484c78059cd7fc5f4996fdd73db20dc8d24f53 2 | updated: 2016-10-27T00:10:51.16960137-07:00 3 | imports: [] 4 | testImports: 5 | - name: github.com/davecgh/go-spew 6 | version: 5215b55f46b2b919f50a1df0eaa5886afe4e3b3d 7 | subpackages: 8 | - spew 9 | - name: github.com/pmezard/go-difflib 10 | version: d8ed2627bdf02c080bf22230dbb337003b7aba2d 11 | subpackages: 12 | - difflib 13 | - name: github.com/stretchr/testify 14 | version: d77da356e56a7428ad25149ca77381849a6a5232 15 | subpackages: 16 | - assert 17 | - require 18 | -------------------------------------------------------------------------------- /vendor/go.uber.org/atomic/glide.yaml: -------------------------------------------------------------------------------- 1 | package: go.uber.org/atomic 2 | testImport: 3 | - package: github.com/stretchr/testify 4 | subpackages: 5 | - assert 6 | - require 7 | -------------------------------------------------------------------------------- /vendor/go.uber.org/atomic/string.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016 Uber Technologies, Inc. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | package atomic 22 | 23 | import "sync/atomic" 24 | 25 | // String is an atomic type-safe wrapper around atomic.Value for strings. 26 | type String struct{ v atomic.Value } 27 | 28 | // NewString creates a String. 29 | func NewString(str string) *String { 30 | s := &String{} 31 | if str != "" { 32 | s.Store(str) 33 | } 34 | return s 35 | } 36 | 37 | // Load atomically loads the wrapped string. 38 | func (s *String) Load() string { 39 | v := s.v.Load() 40 | if v == nil { 41 | return "" 42 | } 43 | return v.(string) 44 | } 45 | 46 | // Store atomically stores the passed string. 47 | // Note: Converting the string to an interface{} to store in the atomic.Value 48 | // requires an allocation. 49 | func (s *String) Store(str string) { 50 | s.v.Store(str) 51 | } 52 | -------------------------------------------------------------------------------- /vendor/go.uber.org/multierr/.codecov.yml: -------------------------------------------------------------------------------- 1 | coverage: 2 | range: 80..100 3 | round: down 4 | precision: 2 5 | 6 | status: 7 | project: # measuring the overall project coverage 8 | default: # context, you can create multiple ones with custom titles 9 | enabled: yes # must be yes|true to enable this status 10 | target: 100 # specify the target coverage for each commit status 11 | # option: "auto" (must increase from parent commit or pull request base) 12 | # option: "X%" a static target percentage to hit 13 | if_not_found: success # if parent is not found report status as success, error, or failure 14 | if_ci_failed: error # if ci fails report status as success, error, or failure 15 | 16 | -------------------------------------------------------------------------------- /vendor/go.uber.org/multierr/.gitignore: -------------------------------------------------------------------------------- 1 | /vendor 2 | -------------------------------------------------------------------------------- /vendor/go.uber.org/multierr/.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: go 3 | go_import_path: go.uber.org/multierr 4 | 5 | env: 6 | global: 7 | - GO15VENDOREXPERIMENT=1 8 | 9 | go: 10 | - 1.7 11 | - 1.8 12 | - tip 13 | 14 | cache: 15 | directories: 16 | - vendor 17 | 18 | before_install: 19 | - go version 20 | 21 | install: 22 | - | 23 | set -e 24 | make install_ci 25 | 26 | script: 27 | - | 28 | set -e 29 | make lint 30 | make test_ci 31 | 32 | after_success: 33 | - bash <(curl -s https://codecov.io/bash) 34 | -------------------------------------------------------------------------------- /vendor/go.uber.org/multierr/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | Releases 2 | ======== 3 | 4 | v1.1.0 (2017-06-30) 5 | =================== 6 | 7 | - Added an `Errors(error) []error` function to extract the underlying list of 8 | errors for a multierr error. 9 | 10 | 11 | v1.0.0 (2017-05-31) 12 | =================== 13 | 14 | No changes since v0.2.0. This release is committing to making no breaking 15 | changes to the current API in the 1.X series. 16 | 17 | 18 | v0.2.0 (2017-04-11) 19 | =================== 20 | 21 | - Repeatedly appending to the same error is now faster due to fewer 22 | allocations. 23 | 24 | 25 | v0.1.0 (2017-31-03) 26 | =================== 27 | 28 | - Initial release 29 | -------------------------------------------------------------------------------- /vendor/go.uber.org/multierr/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2017 Uber Technologies, Inc. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /vendor/go.uber.org/multierr/Makefile: -------------------------------------------------------------------------------- 1 | export GO15VENDOREXPERIMENT=1 2 | 3 | PACKAGES := $(shell glide nv) 4 | 5 | GO_FILES := $(shell \ 6 | find . '(' -path '*/.*' -o -path './vendor' ')' -prune \ 7 | -o -name '*.go' -print | cut -b3-) 8 | 9 | .PHONY: install 10 | install: 11 | glide --version || go get github.com/Masterminds/glide 12 | glide install 13 | 14 | .PHONY: build 15 | build: 16 | go build -i $(PACKAGES) 17 | 18 | .PHONY: test 19 | test: 20 | go test -cover -race $(PACKAGES) 21 | 22 | .PHONY: gofmt 23 | gofmt: 24 | $(eval FMT_LOG := $(shell mktemp -t gofmt.XXXXX)) 25 | @gofmt -e -s -l $(GO_FILES) > $(FMT_LOG) || true 26 | @[ ! -s "$(FMT_LOG)" ] || (echo "gofmt failed:" | cat - $(FMT_LOG) && false) 27 | 28 | .PHONY: govet 29 | govet: 30 | $(eval VET_LOG := $(shell mktemp -t govet.XXXXX)) 31 | @go vet $(PACKAGES) 2>&1 \ 32 | | grep -v '^exit status' > $(VET_LOG) || true 33 | @[ ! -s "$(VET_LOG)" ] || (echo "govet failed:" | cat - $(VET_LOG) && false) 34 | 35 | .PHONY: golint 36 | golint: 37 | @go get github.com/golang/lint/golint 38 | $(eval LINT_LOG := $(shell mktemp -t golint.XXXXX)) 39 | @cat /dev/null > $(LINT_LOG) 40 | @$(foreach pkg, $(PACKAGES), golint $(pkg) >> $(LINT_LOG) || true;) 41 | @[ ! -s "$(LINT_LOG)" ] || (echo "golint failed:" | cat - $(LINT_LOG) && false) 42 | 43 | .PHONY: staticcheck 44 | staticcheck: 45 | @go get honnef.co/go/tools/cmd/staticcheck 46 | $(eval STATICCHECK_LOG := $(shell mktemp -t staticcheck.XXXXX)) 47 | @staticcheck $(PACKAGES) 2>&1 > $(STATICCHECK_LOG) || true 48 | @[ ! -s "$(STATICCHECK_LOG)" ] || (echo "staticcheck failed:" | cat - $(STATICCHECK_LOG) && false) 49 | 50 | .PHONY: lint 51 | lint: gofmt govet golint staticcheck 52 | 53 | .PHONY: cover 54 | cover: 55 | ./scripts/cover.sh $(shell go list $(PACKAGES)) 56 | go tool cover -html=cover.out -o cover.html 57 | 58 | update-license: 59 | @go get go.uber.org/tools/update-license 60 | @update-license \ 61 | $(shell go list -json $(PACKAGES) | \ 62 | jq -r '.Dir + "/" + (.GoFiles | .[])') 63 | 64 | ############################################################################## 65 | 66 | .PHONY: install_ci 67 | install_ci: install 68 | go get github.com/wadey/gocovmerge 69 | go get github.com/mattn/goveralls 70 | go get golang.org/x/tools/cmd/cover 71 | 72 | .PHONY: test_ci 73 | test_ci: install_ci 74 | ./scripts/cover.sh $(shell go list $(PACKAGES)) 75 | -------------------------------------------------------------------------------- /vendor/go.uber.org/multierr/README.md: -------------------------------------------------------------------------------- 1 | # multierr [![GoDoc][doc-img]][doc] [![Build Status][ci-img]][ci] [![Coverage Status][cov-img]][cov] 2 | 3 | `multierr` allows combining one or more Go `error`s together. 4 | 5 | ## Installation 6 | 7 | go get -u go.uber.org/multierr 8 | 9 | ## Status 10 | 11 | Stable: No breaking changes will be made before 2.0. 12 | 13 | ------------------------------------------------------------------------------- 14 | 15 | Released under the [MIT License]. 16 | 17 | [MIT License]: LICENSE.txt 18 | [doc-img]: https://godoc.org/go.uber.org/multierr?status.svg 19 | [doc]: https://godoc.org/go.uber.org/multierr 20 | [ci-img]: https://travis-ci.org/uber-go/multierr.svg?branch=master 21 | [cov-img]: https://codecov.io/gh/uber-go/multierr/branch/master/graph/badge.svg 22 | [ci]: https://travis-ci.org/uber-go/multierr 23 | [cov]: https://codecov.io/gh/uber-go/multierr 24 | -------------------------------------------------------------------------------- /vendor/go.uber.org/multierr/glide.lock: -------------------------------------------------------------------------------- 1 | hash: b53b5e9a84b9cb3cc4b2d0499e23da2feca1eec318ce9bb717ecf35bf24bf221 2 | updated: 2017-04-10T13:34:45.671678062-07:00 3 | imports: 4 | - name: go.uber.org/atomic 5 | version: 3b8db5e93c4c02efbc313e17b2e796b0914a01fb 6 | testImports: 7 | - name: github.com/davecgh/go-spew 8 | version: 6d212800a42e8ab5c146b8ace3490ee17e5225f9 9 | subpackages: 10 | - spew 11 | - name: github.com/pmezard/go-difflib 12 | version: d8ed2627bdf02c080bf22230dbb337003b7aba2d 13 | subpackages: 14 | - difflib 15 | - name: github.com/stretchr/testify 16 | version: 69483b4bd14f5845b5a1e55bca19e954e827f1d0 17 | subpackages: 18 | - assert 19 | - require 20 | -------------------------------------------------------------------------------- /vendor/go.uber.org/multierr/glide.yaml: -------------------------------------------------------------------------------- 1 | package: go.uber.org/multierr 2 | import: 3 | - package: go.uber.org/atomic 4 | version: ^1 5 | testImport: 6 | - package: github.com/stretchr/testify 7 | subpackages: 8 | - assert 9 | -------------------------------------------------------------------------------- /vendor/go.uber.org/zap/.codecov.yml: -------------------------------------------------------------------------------- 1 | coverage: 2 | range: 80..100 3 | round: down 4 | precision: 2 5 | 6 | status: 7 | project: # measuring the overall project coverage 8 | default: # context, you can create multiple ones with custom titles 9 | enabled: yes # must be yes|true to enable this status 10 | target: 95% # specify the target coverage for each commit status 11 | # option: "auto" (must increase from parent commit or pull request base) 12 | # option: "X%" a static target percentage to hit 13 | if_not_found: success # if parent is not found report status as success, error, or failure 14 | if_ci_failed: error # if ci fails report status as success, error, or failure 15 | ignore: 16 | - internal/readme/readme.go 17 | 18 | -------------------------------------------------------------------------------- /vendor/go.uber.org/zap/.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 2 | *.o 3 | *.a 4 | *.so 5 | 6 | # Folders 7 | _obj 8 | _test 9 | vendor 10 | 11 | # Architecture specific extensions/prefixes 12 | *.[568vq] 13 | [568vq].out 14 | 15 | *.cgo1.go 16 | *.cgo2.c 17 | _cgo_defun.c 18 | _cgo_gotypes.go 19 | _cgo_export.* 20 | 21 | _testmain.go 22 | 23 | *.exe 24 | *.test 25 | *.prof 26 | *.pprof 27 | *.out 28 | *.log 29 | -------------------------------------------------------------------------------- /vendor/go.uber.org/zap/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | sudo: false 3 | go: 4 | - 1.9.x 5 | - 1.10.x 6 | go_import_path: go.uber.org/zap 7 | env: 8 | global: 9 | - TEST_TIMEOUT_SCALE=10 10 | cache: 11 | directories: 12 | - vendor 13 | install: 14 | - make dependencies 15 | script: 16 | - make lint 17 | - make test 18 | - make bench 19 | after_success: 20 | - make cover 21 | - bash <(curl -s https://codecov.io/bash) 22 | -------------------------------------------------------------------------------- /vendor/go.uber.org/zap/CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, 8 | body size, disability, ethnicity, gender identity and expression, level of 9 | experience, nationality, personal appearance, race, religion, or sexual 10 | identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an 52 | appointed representative at an online or offline event. Representation of a 53 | project may be further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at oss-conduct@uber.com. The project 59 | team will review and investigate all complaints, and will respond in a way 60 | that it deems appropriate to the circumstances. The project team is obligated 61 | to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 71 | version 1.4, available at 72 | [http://contributor-covenant.org/version/1/4][version]. 73 | 74 | [homepage]: http://contributor-covenant.org 75 | [version]: http://contributor-covenant.org/version/1/4/ 76 | -------------------------------------------------------------------------------- /vendor/go.uber.org/zap/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | We'd love your help making zap the very best structured logging library in Go! 4 | 5 | If you'd like to add new exported APIs, please [open an issue][open-issue] 6 | describing your proposal — discussing API changes ahead of time makes 7 | pull request review much smoother. In your issue, pull request, and any other 8 | communications, please remember to treat your fellow contributors with 9 | respect! We take our [code of conduct](CODE_OF_CONDUCT.md) seriously. 10 | 11 | Note that you'll need to sign [Uber's Contributor License Agreement][cla] 12 | before we can accept any of your contributions. If necessary, a bot will remind 13 | you to accept the CLA when you open your pull request. 14 | 15 | ## Setup 16 | 17 | [Fork][fork], then clone the repository: 18 | 19 | ``` 20 | mkdir -p $GOPATH/src/go.uber.org 21 | cd $GOPATH/src/go.uber.org 22 | git clone git@github.com:your_github_username/zap.git 23 | cd zap 24 | git remote add upstream https://github.com/uber-go/zap.git 25 | git fetch upstream 26 | ``` 27 | 28 | Install zap's dependencies: 29 | 30 | ``` 31 | make dependencies 32 | ``` 33 | 34 | Make sure that the tests and the linters pass: 35 | 36 | ``` 37 | make test 38 | make lint 39 | ``` 40 | 41 | If you're not using the minor version of Go specified in the Makefile's 42 | `LINTABLE_MINOR_VERSIONS` variable, `make lint` doesn't do anything. This is 43 | fine, but it means that you'll only discover lint failures after you open your 44 | pull request. 45 | 46 | ## Making Changes 47 | 48 | Start by creating a new branch for your changes: 49 | 50 | ``` 51 | cd $GOPATH/src/go.uber.org/zap 52 | git checkout master 53 | git fetch upstream 54 | git rebase upstream/master 55 | git checkout -b cool_new_feature 56 | ``` 57 | 58 | Make your changes, then ensure that `make lint` and `make test` still pass. If 59 | you're satisfied with your changes, push them to your fork. 60 | 61 | ``` 62 | git push origin cool_new_feature 63 | ``` 64 | 65 | Then use the GitHub UI to open a pull request. 66 | 67 | At this point, you're waiting on us to review your changes. We *try* to respond 68 | to issues and pull requests within a few business days, and we may suggest some 69 | improvements or alternatives. Once your changes are approved, one of the 70 | project maintainers will merge them. 71 | 72 | We're much more likely to approve your changes if you: 73 | 74 | * Add tests for new functionality. 75 | * Write a [good commit message][commit-message]. 76 | * Maintain backward compatibility. 77 | 78 | [fork]: https://github.com/uber-go/zap/fork 79 | [open-issue]: https://github.com/uber-go/zap/issues/new 80 | [cla]: https://cla-assistant.io/uber-go/zap 81 | [commit-message]: http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html 82 | -------------------------------------------------------------------------------- /vendor/go.uber.org/zap/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016-2017 Uber Technologies, Inc. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /vendor/go.uber.org/zap/Makefile: -------------------------------------------------------------------------------- 1 | export GO15VENDOREXPERIMENT=1 2 | 3 | BENCH_FLAGS ?= -cpuprofile=cpu.pprof -memprofile=mem.pprof -benchmem 4 | PKGS ?= $(shell glide novendor) 5 | # Many Go tools take file globs or directories as arguments instead of packages. 6 | PKG_FILES ?= *.go zapcore benchmarks buffer zapgrpc zaptest zaptest/observer internal/bufferpool internal/exit internal/color internal/ztest 7 | 8 | # The linting tools evolve with each Go version, so run them only on the latest 9 | # stable release. 10 | GO_VERSION := $(shell go version | cut -d " " -f 3) 11 | GO_MINOR_VERSION := $(word 2,$(subst ., ,$(GO_VERSION))) 12 | LINTABLE_MINOR_VERSIONS := 10 13 | ifneq ($(filter $(LINTABLE_MINOR_VERSIONS),$(GO_MINOR_VERSION)),) 14 | SHOULD_LINT := true 15 | endif 16 | 17 | 18 | .PHONY: all 19 | all: lint test 20 | 21 | .PHONY: dependencies 22 | dependencies: 23 | @echo "Installing Glide and locked dependencies..." 24 | glide --version || go get -u -f github.com/Masterminds/glide 25 | glide install 26 | @echo "Installing test dependencies..." 27 | go install ./vendor/github.com/axw/gocov/gocov 28 | go install ./vendor/github.com/mattn/goveralls 29 | ifdef SHOULD_LINT 30 | @echo "Installing golint..." 31 | go install ./vendor/github.com/golang/lint/golint 32 | else 33 | @echo "Not installing golint, since we don't expect to lint on" $(GO_VERSION) 34 | endif 35 | 36 | # Disable printf-like invocation checking due to testify.assert.Error() 37 | VET_RULES := -printf=false 38 | 39 | .PHONY: lint 40 | lint: 41 | ifdef SHOULD_LINT 42 | @rm -rf lint.log 43 | @echo "Checking formatting..." 44 | @gofmt -d -s $(PKG_FILES) 2>&1 | tee lint.log 45 | @echo "Installing test dependencies for vet..." 46 | @go test -i $(PKGS) 47 | @echo "Checking vet..." 48 | @$(foreach dir,$(PKG_FILES),go tool vet $(VET_RULES) $(dir) 2>&1 | tee -a lint.log;) 49 | @echo "Checking lint..." 50 | @$(foreach dir,$(PKGS),golint $(dir) 2>&1 | tee -a lint.log;) 51 | @echo "Checking for unresolved FIXMEs..." 52 | @git grep -i fixme | grep -v -e vendor -e Makefile | tee -a lint.log 53 | @echo "Checking for license headers..." 54 | @./check_license.sh | tee -a lint.log 55 | @[ ! -s lint.log ] 56 | else 57 | @echo "Skipping linters on" $(GO_VERSION) 58 | endif 59 | 60 | .PHONY: test 61 | test: 62 | go test -race $(PKGS) 63 | 64 | .PHONY: cover 65 | cover: 66 | ./scripts/cover.sh $(PKGS) 67 | 68 | .PHONY: bench 69 | BENCH ?= . 70 | bench: 71 | @$(foreach pkg,$(PKGS),go test -bench=$(BENCH) -run="^$$" $(BENCH_FLAGS) $(pkg);) 72 | 73 | .PHONY: updatereadme 74 | updatereadme: 75 | rm -f README.md 76 | cat .readme.tmpl | go run internal/readme/readme.go > README.md 77 | -------------------------------------------------------------------------------- /vendor/go.uber.org/zap/buffer/pool.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016 Uber Technologies, Inc. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | package buffer 22 | 23 | import "sync" 24 | 25 | // A Pool is a type-safe wrapper around a sync.Pool. 26 | type Pool struct { 27 | p *sync.Pool 28 | } 29 | 30 | // NewPool constructs a new Pool. 31 | func NewPool() Pool { 32 | return Pool{p: &sync.Pool{ 33 | New: func() interface{} { 34 | return &Buffer{bs: make([]byte, 0, _size)} 35 | }, 36 | }} 37 | } 38 | 39 | // Get retrieves a Buffer from the pool, creating one if necessary. 40 | func (p Pool) Get() *Buffer { 41 | buf := p.p.Get().(*Buffer) 42 | buf.Reset() 43 | buf.pool = p 44 | return buf 45 | } 46 | 47 | func (p Pool) put(buf *Buffer) { 48 | p.p.Put(buf) 49 | } 50 | -------------------------------------------------------------------------------- /vendor/go.uber.org/zap/check_license.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | 3 | ERROR_COUNT=0 4 | while read -r file 5 | do 6 | case "$(head -1 "${file}")" in 7 | *"Copyright (c) "*" Uber Technologies, Inc.") 8 | # everything's cool 9 | ;; 10 | *) 11 | echo "$file is missing license header." 12 | (( ERROR_COUNT++ )) 13 | ;; 14 | esac 15 | done < <(git ls-files "*\.go") 16 | 17 | exit $ERROR_COUNT 18 | -------------------------------------------------------------------------------- /vendor/go.uber.org/zap/encoder.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016 Uber Technologies, Inc. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | package zap 22 | 23 | import ( 24 | "errors" 25 | "fmt" 26 | "sync" 27 | 28 | "go.uber.org/zap/zapcore" 29 | ) 30 | 31 | var ( 32 | errNoEncoderNameSpecified = errors.New("no encoder name specified") 33 | 34 | _encoderNameToConstructor = map[string]func(zapcore.EncoderConfig) (zapcore.Encoder, error){ 35 | "console": func(encoderConfig zapcore.EncoderConfig) (zapcore.Encoder, error) { 36 | return zapcore.NewConsoleEncoder(encoderConfig), nil 37 | }, 38 | "json": func(encoderConfig zapcore.EncoderConfig) (zapcore.Encoder, error) { 39 | return zapcore.NewJSONEncoder(encoderConfig), nil 40 | }, 41 | } 42 | _encoderMutex sync.RWMutex 43 | ) 44 | 45 | // RegisterEncoder registers an encoder constructor, which the Config struct 46 | // can then reference. By default, the "json" and "console" encoders are 47 | // registered. 48 | // 49 | // Attempting to register an encoder whose name is already taken returns an 50 | // error. 51 | func RegisterEncoder(name string, constructor func(zapcore.EncoderConfig) (zapcore.Encoder, error)) error { 52 | _encoderMutex.Lock() 53 | defer _encoderMutex.Unlock() 54 | if name == "" { 55 | return errNoEncoderNameSpecified 56 | } 57 | if _, ok := _encoderNameToConstructor[name]; ok { 58 | return fmt.Errorf("encoder already registered for name %q", name) 59 | } 60 | _encoderNameToConstructor[name] = constructor 61 | return nil 62 | } 63 | 64 | func newEncoder(name string, encoderConfig zapcore.EncoderConfig) (zapcore.Encoder, error) { 65 | _encoderMutex.RLock() 66 | defer _encoderMutex.RUnlock() 67 | if name == "" { 68 | return nil, errNoEncoderNameSpecified 69 | } 70 | constructor, ok := _encoderNameToConstructor[name] 71 | if !ok { 72 | return nil, fmt.Errorf("no encoder registered for name %q", name) 73 | } 74 | return constructor(encoderConfig) 75 | } 76 | -------------------------------------------------------------------------------- /vendor/go.uber.org/zap/error.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Uber Technologies, Inc. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | package zap 22 | 23 | import ( 24 | "sync" 25 | 26 | "go.uber.org/zap/zapcore" 27 | ) 28 | 29 | var _errArrayElemPool = sync.Pool{New: func() interface{} { 30 | return &errArrayElem{} 31 | }} 32 | 33 | // Error is shorthand for the common idiom NamedError("error", err). 34 | func Error(err error) Field { 35 | return NamedError("error", err) 36 | } 37 | 38 | // NamedError constructs a field that lazily stores err.Error() under the 39 | // provided key. Errors which also implement fmt.Formatter (like those produced 40 | // by github.com/pkg/errors) will also have their verbose representation stored 41 | // under key+"Verbose". If passed a nil error, the field is a no-op. 42 | // 43 | // For the common case in which the key is simply "error", the Error function 44 | // is shorter and less repetitive. 45 | func NamedError(key string, err error) Field { 46 | if err == nil { 47 | return Skip() 48 | } 49 | return Field{Key: key, Type: zapcore.ErrorType, Interface: err} 50 | } 51 | 52 | type errArray []error 53 | 54 | func (errs errArray) MarshalLogArray(arr zapcore.ArrayEncoder) error { 55 | for i := range errs { 56 | if errs[i] == nil { 57 | continue 58 | } 59 | // To represent each error as an object with an "error" attribute and 60 | // potentially an "errorVerbose" attribute, we need to wrap it in a 61 | // type that implements LogObjectMarshaler. To prevent this from 62 | // allocating, pool the wrapper type. 63 | elem := _errArrayElemPool.Get().(*errArrayElem) 64 | elem.error = errs[i] 65 | arr.AppendObject(elem) 66 | elem.error = nil 67 | _errArrayElemPool.Put(elem) 68 | } 69 | return nil 70 | } 71 | 72 | type errArrayElem struct { 73 | error 74 | } 75 | 76 | func (e *errArrayElem) MarshalLogObject(enc zapcore.ObjectEncoder) error { 77 | // Re-use the error field's logic, which supports non-standard error types. 78 | Error(e.error).AddTo(enc) 79 | return nil 80 | } 81 | -------------------------------------------------------------------------------- /vendor/go.uber.org/zap/flag.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016 Uber Technologies, Inc. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | package zap 22 | 23 | import ( 24 | "flag" 25 | 26 | "go.uber.org/zap/zapcore" 27 | ) 28 | 29 | // LevelFlag uses the standard library's flag.Var to declare a global flag 30 | // with the specified name, default, and usage guidance. The returned value is 31 | // a pointer to the value of the flag. 32 | // 33 | // If you don't want to use the flag package's global state, you can use any 34 | // non-nil *Level as a flag.Value with your own *flag.FlagSet. 35 | func LevelFlag(name string, defaultLevel zapcore.Level, usage string) *zapcore.Level { 36 | lvl := defaultLevel 37 | flag.Var(&lvl, name, usage) 38 | return &lvl 39 | } 40 | -------------------------------------------------------------------------------- /vendor/go.uber.org/zap/glide.lock: -------------------------------------------------------------------------------- 1 | hash: f073ba522c06c88ea3075bde32a8aaf0969a840a66cab6318a0897d141ffee92 2 | updated: 2017-07-22T18:06:49.598185334-07:00 3 | imports: 4 | - name: go.uber.org/atomic 5 | version: 4e336646b2ef9fc6e47be8e21594178f98e5ebcf 6 | - name: go.uber.org/multierr 7 | version: 3c4937480c32f4c13a875a1829af76c98ca3d40a 8 | testImports: 9 | - name: github.com/apex/log 10 | version: d9b960447bfa720077b2da653cc79e533455b499 11 | subpackages: 12 | - handlers/json 13 | - name: github.com/axw/gocov 14 | version: 3a69a0d2a4ef1f263e2d92b041a69593d6964fe8 15 | subpackages: 16 | - gocov 17 | - name: github.com/davecgh/go-spew 18 | version: 04cdfd42973bb9c8589fd6a731800cf222fde1a9 19 | subpackages: 20 | - spew 21 | - name: github.com/fatih/color 22 | version: 62e9147c64a1ed519147b62a56a14e83e2be02c1 23 | - name: github.com/go-kit/kit 24 | version: e10f5bf035be9af21fd5b2fb4469d5716c6ab07d 25 | subpackages: 26 | - log 27 | - name: github.com/go-logfmt/logfmt 28 | version: 390ab7935ee28ec6b286364bba9b4dd6410cb3d5 29 | - name: github.com/go-stack/stack 30 | version: 54be5f394ed2c3e19dac9134a40a95ba5a017f7b 31 | - name: github.com/golang/lint 32 | version: c5fb716d6688a859aae56d26d3e6070808df29f7 33 | subpackages: 34 | - golint 35 | - name: github.com/kr/logfmt 36 | version: b84e30acd515aadc4b783ad4ff83aff3299bdfe0 37 | - name: github.com/mattn/go-colorable 38 | version: 3fa8c76f9daed4067e4a806fb7e4dc86455c6d6a 39 | - name: github.com/mattn/go-isatty 40 | version: fc9e8d8ef48496124e79ae0df75490096eccf6fe 41 | - name: github.com/mattn/goveralls 42 | version: 6efce81852ad1b7567c17ad71b03aeccc9dd9ae0 43 | - name: github.com/pborman/uuid 44 | version: e790cca94e6cc75c7064b1332e63811d4aae1a53 45 | - name: github.com/pkg/errors 46 | version: 645ef00459ed84a119197bfb8d8205042c6df63d 47 | - name: github.com/pmezard/go-difflib 48 | version: d8ed2627bdf02c080bf22230dbb337003b7aba2d 49 | subpackages: 50 | - difflib 51 | - name: github.com/rs/zerolog 52 | version: eed4c2b94d945e0b2456ad6aa518a443986b5f22 53 | - name: github.com/satori/go.uuid 54 | version: 5bf94b69c6b68ee1b541973bb8e1144db23a194b 55 | - name: github.com/sirupsen/logrus 56 | version: 7dd06bf38e1e13df288d471a57d5adbac106be9e 57 | - name: github.com/stretchr/testify 58 | version: f6abca593680b2315d2075e0f5e2a9751e3f431a 59 | subpackages: 60 | - assert 61 | - require 62 | - name: go.pedge.io/lion 63 | version: 87958e8713f1fa138d993087133b97e976642159 64 | - name: golang.org/x/sys 65 | version: c4489faa6e5ab84c0ef40d6ee878f7a030281f0f 66 | subpackages: 67 | - unix 68 | - name: golang.org/x/tools 69 | version: 496819729719f9d07692195e0a94d6edd2251389 70 | subpackages: 71 | - cover 72 | - name: gopkg.in/inconshreveable/log15.v2 73 | version: b105bd37f74e5d9dc7b6ad7806715c7a2b83fd3f 74 | subpackages: 75 | - stack 76 | - term 77 | -------------------------------------------------------------------------------- /vendor/go.uber.org/zap/glide.yaml: -------------------------------------------------------------------------------- 1 | package: go.uber.org/zap 2 | license: MIT 3 | import: 4 | - package: go.uber.org/atomic 5 | version: ^1 6 | - package: go.uber.org/multierr 7 | version: ^1 8 | testImport: 9 | - package: github.com/satori/go.uuid 10 | - package: github.com/sirupsen/logrus 11 | - package: github.com/apex/log 12 | subpackages: 13 | - handlers/json 14 | - package: github.com/go-kit/kit 15 | subpackages: 16 | - log 17 | - package: github.com/stretchr/testify 18 | subpackages: 19 | - assert 20 | - require 21 | - package: gopkg.in/inconshreveable/log15.v2 22 | - package: github.com/mattn/goveralls 23 | - package: github.com/pborman/uuid 24 | - package: github.com/pkg/errors 25 | - package: go.pedge.io/lion 26 | - package: github.com/rs/zerolog 27 | - package: golang.org/x/tools 28 | subpackages: 29 | - cover 30 | - package: github.com/golang/lint 31 | subpackages: 32 | - golint 33 | - package: github.com/axw/gocov 34 | subpackages: 35 | - gocov 36 | -------------------------------------------------------------------------------- /vendor/go.uber.org/zap/http_handler.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016 Uber Technologies, Inc. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | package zap 22 | 23 | import ( 24 | "encoding/json" 25 | "fmt" 26 | "net/http" 27 | 28 | "go.uber.org/zap/zapcore" 29 | ) 30 | 31 | // ServeHTTP is a simple JSON endpoint that can report on or change the current 32 | // logging level. 33 | // 34 | // GET requests return a JSON description of the current logging level. PUT 35 | // requests change the logging level and expect a payload like: 36 | // {"level":"info"} 37 | // 38 | // It's perfectly safe to change the logging level while a program is running. 39 | func (lvl AtomicLevel) ServeHTTP(w http.ResponseWriter, r *http.Request) { 40 | type errorResponse struct { 41 | Error string `json:"error"` 42 | } 43 | type payload struct { 44 | Level *zapcore.Level `json:"level"` 45 | } 46 | 47 | enc := json.NewEncoder(w) 48 | 49 | switch r.Method { 50 | 51 | case http.MethodGet: 52 | current := lvl.Level() 53 | enc.Encode(payload{Level: ¤t}) 54 | 55 | case http.MethodPut: 56 | var req payload 57 | 58 | if errmess := func() string { 59 | if err := json.NewDecoder(r.Body).Decode(&req); err != nil { 60 | return fmt.Sprintf("Request body must be well-formed JSON: %v", err) 61 | } 62 | if req.Level == nil { 63 | return "Must specify a logging level." 64 | } 65 | return "" 66 | }(); errmess != "" { 67 | w.WriteHeader(http.StatusBadRequest) 68 | enc.Encode(errorResponse{Error: errmess}) 69 | return 70 | } 71 | 72 | lvl.SetLevel(*req.Level) 73 | enc.Encode(req) 74 | 75 | default: 76 | w.WriteHeader(http.StatusMethodNotAllowed) 77 | enc.Encode(errorResponse{ 78 | Error: "Only GET and PUT are supported.", 79 | }) 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /vendor/go.uber.org/zap/internal/bufferpool/bufferpool.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016 Uber Technologies, Inc. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | // Package bufferpool houses zap's shared internal buffer pool. Third-party 22 | // packages can recreate the same functionality with buffers.NewPool. 23 | package bufferpool 24 | 25 | import "go.uber.org/zap/buffer" 26 | 27 | var ( 28 | _pool = buffer.NewPool() 29 | // Get retrieves a buffer from the pool, creating one if necessary. 30 | Get = _pool.Get 31 | ) 32 | -------------------------------------------------------------------------------- /vendor/go.uber.org/zap/internal/color/color.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016 Uber Technologies, Inc. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | // Package color adds coloring functionality for TTY output. 22 | package color 23 | 24 | import "fmt" 25 | 26 | // Foreground colors. 27 | const ( 28 | Black Color = iota + 30 29 | Red 30 | Green 31 | Yellow 32 | Blue 33 | Magenta 34 | Cyan 35 | White 36 | ) 37 | 38 | // Color represents a text color. 39 | type Color uint8 40 | 41 | // Add adds the coloring to the given string. 42 | func (c Color) Add(s string) string { 43 | return fmt.Sprintf("\x1b[%dm%s\x1b[0m", uint8(c), s) 44 | } 45 | -------------------------------------------------------------------------------- /vendor/go.uber.org/zap/internal/exit/exit.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016 Uber Technologies, Inc. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | // Package exit provides stubs so that unit tests can exercise code that calls 22 | // os.Exit(1). 23 | package exit 24 | 25 | import "os" 26 | 27 | var real = func() { os.Exit(1) } 28 | 29 | // Exit normally terminates the process by calling os.Exit(1). If the package 30 | // is stubbed, it instead records a call in the testing spy. 31 | func Exit() { 32 | real() 33 | } 34 | 35 | // A StubbedExit is a testing fake for os.Exit. 36 | type StubbedExit struct { 37 | Exited bool 38 | prev func() 39 | } 40 | 41 | // Stub substitutes a fake for the call to os.Exit(1). 42 | func Stub() *StubbedExit { 43 | s := &StubbedExit{prev: real} 44 | real = s.exit 45 | return s 46 | } 47 | 48 | // WithStub runs the supplied function with Exit stubbed. It returns the stub 49 | // used, so that users can test whether the process would have crashed. 50 | func WithStub(f func()) *StubbedExit { 51 | s := Stub() 52 | defer s.Unstub() 53 | f() 54 | return s 55 | } 56 | 57 | // Unstub restores the previous exit function. 58 | func (se *StubbedExit) Unstub() { 59 | real = se.prev 60 | } 61 | 62 | func (se *StubbedExit) exit() { 63 | se.Exited = true 64 | } 65 | -------------------------------------------------------------------------------- /vendor/go.uber.org/zap/time.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016 Uber Technologies, Inc. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | package zap 22 | 23 | import "time" 24 | 25 | func timeToMillis(t time.Time) int64 { 26 | return t.UnixNano() / int64(time.Millisecond) 27 | } 28 | -------------------------------------------------------------------------------- /vendor/go.uber.org/zap/writer.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016 Uber Technologies, Inc. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | package zap 22 | 23 | import ( 24 | "fmt" 25 | "io" 26 | "io/ioutil" 27 | 28 | "go.uber.org/zap/zapcore" 29 | 30 | "go.uber.org/multierr" 31 | ) 32 | 33 | // Open is a high-level wrapper that takes a variadic number of URLs, opens or 34 | // creates each of the specified resources, and combines them into a locked 35 | // WriteSyncer. It also returns any error encountered and a function to close 36 | // any opened files. 37 | // 38 | // Passing no URLs returns a no-op WriteSyncer. Zap handles URLs without a 39 | // scheme and URLs with the "file" scheme. Third-party code may register 40 | // factories for other schemes using RegisterSink. 41 | // 42 | // URLs with the "file" scheme must use absolute paths on the local 43 | // filesystem. No user, password, port, fragments, or query parameters are 44 | // allowed, and the hostname must be empty or "localhost". 45 | // 46 | // Since it's common to write logs to the local filesystem, URLs without a 47 | // scheme (e.g., "/var/log/foo.log") are treated as local file paths. Without 48 | // a scheme, the special paths "stdout" and "stderr" are interpreted as 49 | // os.Stdout and os.Stderr. When specified without a scheme, relative file 50 | // paths also work. 51 | func Open(paths ...string) (zapcore.WriteSyncer, func(), error) { 52 | writers, close, err := open(paths) 53 | if err != nil { 54 | return nil, nil, err 55 | } 56 | 57 | writer := CombineWriteSyncers(writers...) 58 | return writer, close, nil 59 | } 60 | 61 | func open(paths []string) ([]zapcore.WriteSyncer, func(), error) { 62 | writers := make([]zapcore.WriteSyncer, 0, len(paths)) 63 | closers := make([]io.Closer, 0, len(paths)) 64 | close := func() { 65 | for _, c := range closers { 66 | c.Close() 67 | } 68 | } 69 | 70 | var openErr error 71 | for _, path := range paths { 72 | sink, err := newSink(path) 73 | if err != nil { 74 | openErr = multierr.Append(openErr, fmt.Errorf("couldn't open sink %q: %v", path, err)) 75 | continue 76 | } 77 | writers = append(writers, sink) 78 | closers = append(closers, sink) 79 | } 80 | if openErr != nil { 81 | close() 82 | return writers, nil, openErr 83 | } 84 | 85 | return writers, close, nil 86 | } 87 | 88 | // CombineWriteSyncers is a utility that combines multiple WriteSyncers into a 89 | // single, locked WriteSyncer. If no inputs are supplied, it returns a no-op 90 | // WriteSyncer. 91 | // 92 | // It's provided purely as a convenience; the result is no different from 93 | // using zapcore.NewMultiWriteSyncer and zapcore.Lock individually. 94 | func CombineWriteSyncers(writers ...zapcore.WriteSyncer) zapcore.WriteSyncer { 95 | if len(writers) == 0 { 96 | return zapcore.AddSync(ioutil.Discard) 97 | } 98 | return zapcore.Lock(zapcore.NewMultiWriteSyncer(writers...)) 99 | } 100 | -------------------------------------------------------------------------------- /vendor/go.uber.org/zap/zapcore/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016 Uber Technologies, Inc. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | // Package zapcore defines and implements the low-level interfaces upon which 22 | // zap is built. By providing alternate implementations of these interfaces, 23 | // external packages can extend zap's capabilities. 24 | package zapcore // import "go.uber.org/zap/zapcore" 25 | -------------------------------------------------------------------------------- /vendor/go.uber.org/zap/zapcore/hook.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016 Uber Technologies, Inc. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | package zapcore 22 | 23 | import "go.uber.org/multierr" 24 | 25 | type hooked struct { 26 | Core 27 | funcs []func(Entry) error 28 | } 29 | 30 | // RegisterHooks wraps a Core and runs a collection of user-defined callback 31 | // hooks each time a message is logged. Execution of the callbacks is blocking. 32 | // 33 | // This offers users an easy way to register simple callbacks (e.g., metrics 34 | // collection) without implementing the full Core interface. 35 | func RegisterHooks(core Core, hooks ...func(Entry) error) Core { 36 | funcs := append([]func(Entry) error{}, hooks...) 37 | return &hooked{ 38 | Core: core, 39 | funcs: funcs, 40 | } 41 | } 42 | 43 | func (h *hooked) Check(ent Entry, ce *CheckedEntry) *CheckedEntry { 44 | // Let the wrapped Core decide whether to log this message or not. This 45 | // also gives the downstream a chance to register itself directly with the 46 | // CheckedEntry. 47 | if downstream := h.Core.Check(ent, ce); downstream != nil { 48 | return downstream.AddCore(ent, h) 49 | } 50 | return ce 51 | } 52 | 53 | func (h *hooked) With(fields []Field) Core { 54 | return &hooked{ 55 | Core: h.Core.With(fields), 56 | funcs: h.funcs, 57 | } 58 | } 59 | 60 | func (h *hooked) Write(ent Entry, _ []Field) error { 61 | // Since our downstream had a chance to register itself directly with the 62 | // CheckedMessage, we don't need to call it here. 63 | var err error 64 | for i := range h.funcs { 65 | err = multierr.Append(err, h.funcs[i](ent)) 66 | } 67 | return err 68 | } 69 | -------------------------------------------------------------------------------- /vendor/go.uber.org/zap/zapcore/level_strings.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016 Uber Technologies, Inc. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | package zapcore 22 | 23 | import "go.uber.org/zap/internal/color" 24 | 25 | var ( 26 | _levelToColor = map[Level]color.Color{ 27 | DebugLevel: color.Magenta, 28 | InfoLevel: color.Blue, 29 | WarnLevel: color.Yellow, 30 | ErrorLevel: color.Red, 31 | DPanicLevel: color.Red, 32 | PanicLevel: color.Red, 33 | FatalLevel: color.Red, 34 | } 35 | _unknownLevelColor = color.Red 36 | 37 | _levelToLowercaseColorString = make(map[Level]string, len(_levelToColor)) 38 | _levelToCapitalColorString = make(map[Level]string, len(_levelToColor)) 39 | ) 40 | 41 | func init() { 42 | for level, color := range _levelToColor { 43 | _levelToLowercaseColorString[level] = color.Add(level.String()) 44 | _levelToCapitalColorString[level] = color.Add(level.CapitalString()) 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /vendor/go.uber.org/zap/zapcore/marshaler.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016 Uber Technologies, Inc. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | package zapcore 22 | 23 | // ObjectMarshaler allows user-defined types to efficiently add themselves to the 24 | // logging context, and to selectively omit information which shouldn't be 25 | // included in logs (e.g., passwords). 26 | type ObjectMarshaler interface { 27 | MarshalLogObject(ObjectEncoder) error 28 | } 29 | 30 | // ObjectMarshalerFunc is a type adapter that turns a function into an 31 | // ObjectMarshaler. 32 | type ObjectMarshalerFunc func(ObjectEncoder) error 33 | 34 | // MarshalLogObject calls the underlying function. 35 | func (f ObjectMarshalerFunc) MarshalLogObject(enc ObjectEncoder) error { 36 | return f(enc) 37 | } 38 | 39 | // ArrayMarshaler allows user-defined types to efficiently add themselves to the 40 | // logging context, and to selectively omit information which shouldn't be 41 | // included in logs (e.g., passwords). 42 | type ArrayMarshaler interface { 43 | MarshalLogArray(ArrayEncoder) error 44 | } 45 | 46 | // ArrayMarshalerFunc is a type adapter that turns a function into an 47 | // ArrayMarshaler. 48 | type ArrayMarshalerFunc func(ArrayEncoder) error 49 | 50 | // MarshalLogArray calls the underlying function. 51 | func (f ArrayMarshalerFunc) MarshalLogArray(enc ArrayEncoder) error { 52 | return f(enc) 53 | } 54 | -------------------------------------------------------------------------------- /vendor/go.uber.org/zap/zapcore/tee.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016 Uber Technologies, Inc. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | package zapcore 22 | 23 | import "go.uber.org/multierr" 24 | 25 | type multiCore []Core 26 | 27 | // NewTee creates a Core that duplicates log entries into two or more 28 | // underlying Cores. 29 | // 30 | // Calling it with a single Core returns the input unchanged, and calling 31 | // it with no input returns a no-op Core. 32 | func NewTee(cores ...Core) Core { 33 | switch len(cores) { 34 | case 0: 35 | return NewNopCore() 36 | case 1: 37 | return cores[0] 38 | default: 39 | return multiCore(cores) 40 | } 41 | } 42 | 43 | func (mc multiCore) With(fields []Field) Core { 44 | clone := make(multiCore, len(mc)) 45 | for i := range mc { 46 | clone[i] = mc[i].With(fields) 47 | } 48 | return clone 49 | } 50 | 51 | func (mc multiCore) Enabled(lvl Level) bool { 52 | for i := range mc { 53 | if mc[i].Enabled(lvl) { 54 | return true 55 | } 56 | } 57 | return false 58 | } 59 | 60 | func (mc multiCore) Check(ent Entry, ce *CheckedEntry) *CheckedEntry { 61 | for i := range mc { 62 | ce = mc[i].Check(ent, ce) 63 | } 64 | return ce 65 | } 66 | 67 | func (mc multiCore) Write(ent Entry, fields []Field) error { 68 | var err error 69 | for i := range mc { 70 | err = multierr.Append(err, mc[i].Write(ent, fields)) 71 | } 72 | return err 73 | } 74 | 75 | func (mc multiCore) Sync() error { 76 | var err error 77 | for i := range mc { 78 | err = multierr.Append(err, mc[i].Sync()) 79 | } 80 | return err 81 | } 82 | -------------------------------------------------------------------------------- /vendor/go.uber.org/zap/zapcore/write_syncer.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016 Uber Technologies, Inc. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | package zapcore 22 | 23 | import ( 24 | "io" 25 | "sync" 26 | 27 | "go.uber.org/multierr" 28 | ) 29 | 30 | // A WriteSyncer is an io.Writer that can also flush any buffered data. Note 31 | // that *os.File (and thus, os.Stderr and os.Stdout) implement WriteSyncer. 32 | type WriteSyncer interface { 33 | io.Writer 34 | Sync() error 35 | } 36 | 37 | // AddSync converts an io.Writer to a WriteSyncer. It attempts to be 38 | // intelligent: if the concrete type of the io.Writer implements WriteSyncer, 39 | // we'll use the existing Sync method. If it doesn't, we'll add a no-op Sync. 40 | func AddSync(w io.Writer) WriteSyncer { 41 | switch w := w.(type) { 42 | case WriteSyncer: 43 | return w 44 | default: 45 | return writerWrapper{w} 46 | } 47 | } 48 | 49 | type lockedWriteSyncer struct { 50 | sync.Mutex 51 | ws WriteSyncer 52 | } 53 | 54 | // Lock wraps a WriteSyncer in a mutex to make it safe for concurrent use. In 55 | // particular, *os.Files must be locked before use. 56 | func Lock(ws WriteSyncer) WriteSyncer { 57 | if _, ok := ws.(*lockedWriteSyncer); ok { 58 | // no need to layer on another lock 59 | return ws 60 | } 61 | return &lockedWriteSyncer{ws: ws} 62 | } 63 | 64 | func (s *lockedWriteSyncer) Write(bs []byte) (int, error) { 65 | s.Lock() 66 | n, err := s.ws.Write(bs) 67 | s.Unlock() 68 | return n, err 69 | } 70 | 71 | func (s *lockedWriteSyncer) Sync() error { 72 | s.Lock() 73 | err := s.ws.Sync() 74 | s.Unlock() 75 | return err 76 | } 77 | 78 | type writerWrapper struct { 79 | io.Writer 80 | } 81 | 82 | func (w writerWrapper) Sync() error { 83 | return nil 84 | } 85 | 86 | type multiWriteSyncer []WriteSyncer 87 | 88 | // NewMultiWriteSyncer creates a WriteSyncer that duplicates its writes 89 | // and sync calls, much like io.MultiWriter. 90 | func NewMultiWriteSyncer(ws ...WriteSyncer) WriteSyncer { 91 | if len(ws) == 1 { 92 | return ws[0] 93 | } 94 | // Copy to protect against https://github.com/golang/go/issues/7809 95 | return multiWriteSyncer(append([]WriteSyncer(nil), ws...)) 96 | } 97 | 98 | // See https://golang.org/src/io/multi.go 99 | // When not all underlying syncers write the same number of bytes, 100 | // the smallest number is returned even though Write() is called on 101 | // all of them. 102 | func (ws multiWriteSyncer) Write(p []byte) (int, error) { 103 | var writeErr error 104 | nWritten := 0 105 | for _, w := range ws { 106 | n, err := w.Write(p) 107 | writeErr = multierr.Append(writeErr, err) 108 | if nWritten == 0 && n != 0 { 109 | nWritten = n 110 | } else if n < nWritten { 111 | nWritten = n 112 | } 113 | } 114 | return nWritten, writeErr 115 | } 116 | 117 | func (ws multiWriteSyncer) Sync() error { 118 | var err error 119 | for _, w := range ws { 120 | err = multierr.Append(err, w.Sync()) 121 | } 122 | return err 123 | } 124 | -------------------------------------------------------------------------------- /vendor/gopkg.in/alecthomas/kingpin.v2/.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: go 3 | install: go get -t -v ./... 4 | go: 1.2 5 | -------------------------------------------------------------------------------- /vendor/gopkg.in/alecthomas/kingpin.v2/COPYING: -------------------------------------------------------------------------------- 1 | Copyright (C) 2014 Alec Thomas 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | this software and associated documentation files (the "Software"), to deal in 5 | the Software without restriction, including without limitation the rights to 6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 7 | of the Software, and to permit persons to whom the Software is furnished to do 8 | so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /vendor/gopkg.in/alecthomas/kingpin.v2/actions.go: -------------------------------------------------------------------------------- 1 | package kingpin 2 | 3 | // Action callback executed at various stages after all values are populated. 4 | // The application, commands, arguments and flags all have corresponding 5 | // actions. 6 | type Action func(*ParseContext) error 7 | 8 | type actionMixin struct { 9 | actions []Action 10 | preActions []Action 11 | } 12 | 13 | type actionApplier interface { 14 | applyActions(*ParseContext) error 15 | applyPreActions(*ParseContext) error 16 | } 17 | 18 | func (a *actionMixin) addAction(action Action) { 19 | a.actions = append(a.actions, action) 20 | } 21 | 22 | func (a *actionMixin) addPreAction(action Action) { 23 | a.preActions = append(a.preActions, action) 24 | } 25 | 26 | func (a *actionMixin) applyActions(context *ParseContext) error { 27 | for _, action := range a.actions { 28 | if err := action(context); err != nil { 29 | return err 30 | } 31 | } 32 | return nil 33 | } 34 | 35 | func (a *actionMixin) applyPreActions(context *ParseContext) error { 36 | for _, preAction := range a.preActions { 37 | if err := preAction(context); err != nil { 38 | return err 39 | } 40 | } 41 | return nil 42 | } 43 | -------------------------------------------------------------------------------- /vendor/gopkg.in/alecthomas/kingpin.v2/completions.go: -------------------------------------------------------------------------------- 1 | package kingpin 2 | 3 | // HintAction is a function type who is expected to return a slice of possible 4 | // command line arguments. 5 | type HintAction func() []string 6 | type completionsMixin struct { 7 | hintActions []HintAction 8 | builtinHintActions []HintAction 9 | } 10 | 11 | func (a *completionsMixin) addHintAction(action HintAction) { 12 | a.hintActions = append(a.hintActions, action) 13 | } 14 | 15 | // Allow adding of HintActions which are added internally, ie, EnumVar 16 | func (a *completionsMixin) addHintActionBuiltin(action HintAction) { 17 | a.builtinHintActions = append(a.builtinHintActions, action) 18 | } 19 | 20 | func (a *completionsMixin) resolveCompletions() []string { 21 | var hints []string 22 | 23 | options := a.builtinHintActions 24 | if len(a.hintActions) > 0 { 25 | // User specified their own hintActions. Use those instead. 26 | options = a.hintActions 27 | } 28 | 29 | for _, hintAction := range options { 30 | hints = append(hints, hintAction()...) 31 | } 32 | return hints 33 | } 34 | -------------------------------------------------------------------------------- /vendor/gopkg.in/alecthomas/kingpin.v2/doc.go: -------------------------------------------------------------------------------- 1 | // Package kingpin provides command line interfaces like this: 2 | // 3 | // $ chat 4 | // usage: chat [] [] [ ...] 5 | // 6 | // Flags: 7 | // --debug enable debug mode 8 | // --help Show help. 9 | // --server=127.0.0.1 server address 10 | // 11 | // Commands: 12 | // help 13 | // Show help for a command. 14 | // 15 | // post [] 16 | // Post a message to a channel. 17 | // 18 | // register 19 | // Register a new user. 20 | // 21 | // $ chat help post 22 | // usage: chat [] post [] [] 23 | // 24 | // Post a message to a channel. 25 | // 26 | // Flags: 27 | // --image=IMAGE image to post 28 | // 29 | // Args: 30 | // channel to post to 31 | // [] text to post 32 | // $ chat post --image=~/Downloads/owls.jpg pics 33 | // 34 | // From code like this: 35 | // 36 | // package main 37 | // 38 | // import "gopkg.in/alecthomas/kingpin.v2" 39 | // 40 | // var ( 41 | // debug = kingpin.Flag("debug", "enable debug mode").Default("false").Bool() 42 | // serverIP = kingpin.Flag("server", "server address").Default("127.0.0.1").IP() 43 | // 44 | // register = kingpin.Command("register", "Register a new user.") 45 | // registerNick = register.Arg("nick", "nickname for user").Required().String() 46 | // registerName = register.Arg("name", "name of user").Required().String() 47 | // 48 | // post = kingpin.Command("post", "Post a message to a channel.") 49 | // postImage = post.Flag("image", "image to post").ExistingFile() 50 | // postChannel = post.Arg("channel", "channel to post to").Required().String() 51 | // postText = post.Arg("text", "text to post").String() 52 | // ) 53 | // 54 | // func main() { 55 | // switch kingpin.Parse() { 56 | // // Register user 57 | // case "register": 58 | // println(*registerNick) 59 | // 60 | // // Post message 61 | // case "post": 62 | // if *postImage != nil { 63 | // } 64 | // if *postText != "" { 65 | // } 66 | // } 67 | // } 68 | package kingpin 69 | -------------------------------------------------------------------------------- /vendor/gopkg.in/alecthomas/kingpin.v2/envar.go: -------------------------------------------------------------------------------- 1 | package kingpin 2 | 3 | import ( 4 | "os" 5 | "regexp" 6 | ) 7 | 8 | var ( 9 | envVarValuesSeparator = "\r?\n" 10 | envVarValuesTrimmer = regexp.MustCompile(envVarValuesSeparator + "$") 11 | envVarValuesSplitter = regexp.MustCompile(envVarValuesSeparator) 12 | ) 13 | 14 | type envarMixin struct { 15 | envar string 16 | noEnvar bool 17 | } 18 | 19 | func (e *envarMixin) HasEnvarValue() bool { 20 | return e.GetEnvarValue() != "" 21 | } 22 | 23 | func (e *envarMixin) GetEnvarValue() string { 24 | if e.noEnvar || e.envar == "" { 25 | return "" 26 | } 27 | return os.Getenv(e.envar) 28 | } 29 | 30 | func (e *envarMixin) GetSplitEnvarValue() []string { 31 | values := make([]string, 0) 32 | 33 | envarValue := e.GetEnvarValue() 34 | if envarValue == "" { 35 | return values 36 | } 37 | 38 | // Split by new line to extract multiple values, if any. 39 | trimmed := envVarValuesTrimmer.ReplaceAllString(envarValue, "") 40 | for _, value := range envVarValuesSplitter.Split(trimmed, -1) { 41 | values = append(values, value) 42 | } 43 | 44 | return values 45 | } 46 | -------------------------------------------------------------------------------- /vendor/gopkg.in/alecthomas/kingpin.v2/global.go: -------------------------------------------------------------------------------- 1 | package kingpin 2 | 3 | import ( 4 | "os" 5 | "path/filepath" 6 | ) 7 | 8 | var ( 9 | // CommandLine is the default Kingpin parser. 10 | CommandLine = New(filepath.Base(os.Args[0]), "") 11 | // Global help flag. Exposed for user customisation. 12 | HelpFlag = CommandLine.HelpFlag 13 | // Top-level help command. Exposed for user customisation. May be nil. 14 | HelpCommand = CommandLine.HelpCommand 15 | // Global version flag. Exposed for user customisation. May be nil. 16 | VersionFlag = CommandLine.VersionFlag 17 | ) 18 | 19 | // Command adds a new command to the default parser. 20 | func Command(name, help string) *CmdClause { 21 | return CommandLine.Command(name, help) 22 | } 23 | 24 | // Flag adds a new flag to the default parser. 25 | func Flag(name, help string) *FlagClause { 26 | return CommandLine.Flag(name, help) 27 | } 28 | 29 | // Arg adds a new argument to the top-level of the default parser. 30 | func Arg(name, help string) *ArgClause { 31 | return CommandLine.Arg(name, help) 32 | } 33 | 34 | // Parse and return the selected command. Will call the termination handler if 35 | // an error is encountered. 36 | func Parse() string { 37 | selected := MustParse(CommandLine.Parse(os.Args[1:])) 38 | if selected == "" && CommandLine.cmdGroup.have() { 39 | Usage() 40 | CommandLine.terminate(0) 41 | } 42 | return selected 43 | } 44 | 45 | // Errorf prints an error message to stderr. 46 | func Errorf(format string, args ...interface{}) { 47 | CommandLine.Errorf(format, args...) 48 | } 49 | 50 | // Fatalf prints an error message to stderr and exits. 51 | func Fatalf(format string, args ...interface{}) { 52 | CommandLine.Fatalf(format, args...) 53 | } 54 | 55 | // FatalIfError prints an error and exits if err is not nil. The error is printed 56 | // with the given prefix. 57 | func FatalIfError(err error, format string, args ...interface{}) { 58 | CommandLine.FatalIfError(err, format, args...) 59 | } 60 | 61 | // FatalUsage prints an error message followed by usage information, then 62 | // exits with a non-zero status. 63 | func FatalUsage(format string, args ...interface{}) { 64 | CommandLine.FatalUsage(format, args...) 65 | } 66 | 67 | // FatalUsageContext writes a printf formatted error message to stderr, then 68 | // usage information for the given ParseContext, before exiting. 69 | func FatalUsageContext(context *ParseContext, format string, args ...interface{}) { 70 | CommandLine.FatalUsageContext(context, format, args...) 71 | } 72 | 73 | // Usage prints usage to stderr. 74 | func Usage() { 75 | CommandLine.Usage(os.Args[1:]) 76 | } 77 | 78 | // Set global usage template to use (defaults to DefaultUsageTemplate). 79 | func UsageTemplate(template string) *Application { 80 | return CommandLine.UsageTemplate(template) 81 | } 82 | 83 | // MustParse can be used with app.Parse(args) to exit with an error if parsing fails. 84 | func MustParse(command string, err error) string { 85 | if err != nil { 86 | Fatalf("%s, try --help", err) 87 | } 88 | return command 89 | } 90 | 91 | // Version adds a flag for displaying the application version number. 92 | func Version(version string) *Application { 93 | return CommandLine.Version(version) 94 | } 95 | -------------------------------------------------------------------------------- /vendor/gopkg.in/alecthomas/kingpin.v2/guesswidth.go: -------------------------------------------------------------------------------- 1 | // +build appengine !linux,!freebsd,!darwin,!dragonfly,!netbsd,!openbsd 2 | 3 | package kingpin 4 | 5 | import "io" 6 | 7 | func guessWidth(w io.Writer) int { 8 | return 80 9 | } 10 | -------------------------------------------------------------------------------- /vendor/gopkg.in/alecthomas/kingpin.v2/guesswidth_unix.go: -------------------------------------------------------------------------------- 1 | // +build !appengine,linux freebsd darwin dragonfly netbsd openbsd 2 | 3 | package kingpin 4 | 5 | import ( 6 | "io" 7 | "os" 8 | "strconv" 9 | "syscall" 10 | "unsafe" 11 | ) 12 | 13 | func guessWidth(w io.Writer) int { 14 | // check if COLUMNS env is set to comply with 15 | // http://pubs.opengroup.org/onlinepubs/009604499/basedefs/xbd_chap08.html 16 | colsStr := os.Getenv("COLUMNS") 17 | if colsStr != "" { 18 | if cols, err := strconv.Atoi(colsStr); err == nil { 19 | return cols 20 | } 21 | } 22 | 23 | if t, ok := w.(*os.File); ok { 24 | fd := t.Fd() 25 | var dimensions [4]uint16 26 | 27 | if _, _, err := syscall.Syscall6( 28 | syscall.SYS_IOCTL, 29 | uintptr(fd), 30 | uintptr(syscall.TIOCGWINSZ), 31 | uintptr(unsafe.Pointer(&dimensions)), 32 | 0, 0, 0, 33 | ); err == 0 { 34 | return int(dimensions[1]) 35 | } 36 | } 37 | return 80 38 | } 39 | -------------------------------------------------------------------------------- /vendor/gopkg.in/alecthomas/kingpin.v2/values.json: -------------------------------------------------------------------------------- 1 | [ 2 | {"type": "bool", "parser": "strconv.ParseBool(s)"}, 3 | {"type": "string", "parser": "s, error(nil)", "format": "string(*f.v)", "plural": "Strings"}, 4 | {"type": "uint", "parser": "strconv.ParseUint(s, 0, 64)", "plural": "Uints"}, 5 | {"type": "uint8", "parser": "strconv.ParseUint(s, 0, 8)"}, 6 | {"type": "uint16", "parser": "strconv.ParseUint(s, 0, 16)"}, 7 | {"type": "uint32", "parser": "strconv.ParseUint(s, 0, 32)"}, 8 | {"type": "uint64", "parser": "strconv.ParseUint(s, 0, 64)"}, 9 | {"type": "int", "parser": "strconv.ParseFloat(s, 64)", "plural": "Ints"}, 10 | {"type": "int8", "parser": "strconv.ParseInt(s, 0, 8)"}, 11 | {"type": "int16", "parser": "strconv.ParseInt(s, 0, 16)"}, 12 | {"type": "int32", "parser": "strconv.ParseInt(s, 0, 32)"}, 13 | {"type": "int64", "parser": "strconv.ParseInt(s, 0, 64)"}, 14 | {"type": "float64", "parser": "strconv.ParseFloat(s, 64)"}, 15 | {"type": "float32", "parser": "strconv.ParseFloat(s, 32)"}, 16 | {"name": "Duration", "type": "time.Duration", "no_value_parser": true}, 17 | {"name": "IP", "type": "net.IP", "no_value_parser": true}, 18 | {"name": "TCPAddr", "Type": "*net.TCPAddr", "plural": "TCPList", "no_value_parser": true}, 19 | {"name": "ExistingFile", "Type": "string", "plural": "ExistingFiles", "no_value_parser": true}, 20 | {"name": "ExistingDir", "Type": "string", "plural": "ExistingDirs", "no_value_parser": true}, 21 | {"name": "ExistingFileOrDir", "Type": "string", "plural": "ExistingFilesOrDirs", "no_value_parser": true}, 22 | {"name": "Regexp", "Type": "*regexp.Regexp", "parser": "regexp.Compile(s)"}, 23 | {"name": "ResolvedIP", "Type": "net.IP", "parser": "resolveHost(s)", "help": "Resolve a hostname or IP to an IP."}, 24 | {"name": "HexBytes", "Type": "[]byte", "parser": "hex.DecodeString(s)", "help": "Bytes as a hex string."} 25 | ] 26 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v2/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | 3 | go: 4 | - 1.4 5 | - 1.5 6 | - 1.6 7 | - 1.7 8 | - 1.8 9 | - 1.9 10 | - tip 11 | 12 | go_import_path: gopkg.in/yaml.v2 13 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v2/LICENSE.libyaml: -------------------------------------------------------------------------------- 1 | The following files were ported to Go from C files of libyaml, and thus 2 | are still covered by their original copyright and license: 3 | 4 | apic.go 5 | emitterc.go 6 | parserc.go 7 | readerc.go 8 | scannerc.go 9 | writerc.go 10 | yamlh.go 11 | yamlprivateh.go 12 | 13 | Copyright (c) 2006 Kirill Simonov 14 | 15 | Permission is hereby granted, free of charge, to any person obtaining a copy of 16 | this software and associated documentation files (the "Software"), to deal in 17 | the Software without restriction, including without limitation the rights to 18 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 19 | of the Software, and to permit persons to whom the Software is furnished to do 20 | so, subject to the following conditions: 21 | 22 | The above copyright notice and this permission notice shall be included in all 23 | copies or substantial portions of the Software. 24 | 25 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 26 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 27 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 28 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 29 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 30 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 31 | SOFTWARE. 32 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v2/NOTICE: -------------------------------------------------------------------------------- 1 | Copyright 2011-2016 Canonical Ltd. 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v2/README.md: -------------------------------------------------------------------------------- 1 | # YAML support for the Go language 2 | 3 | Introduction 4 | ------------ 5 | 6 | The yaml package enables Go programs to comfortably encode and decode YAML 7 | values. It was developed within [Canonical](https://www.canonical.com) as 8 | part of the [juju](https://juju.ubuntu.com) project, and is based on a 9 | pure Go port of the well-known [libyaml](http://pyyaml.org/wiki/LibYAML) 10 | C library to parse and generate YAML data quickly and reliably. 11 | 12 | Compatibility 13 | ------------- 14 | 15 | The yaml package supports most of YAML 1.1 and 1.2, including support for 16 | anchors, tags, map merging, etc. Multi-document unmarshalling is not yet 17 | implemented, and base-60 floats from YAML 1.1 are purposefully not 18 | supported since they're a poor design and are gone in YAML 1.2. 19 | 20 | Installation and usage 21 | ---------------------- 22 | 23 | The import path for the package is *gopkg.in/yaml.v2*. 24 | 25 | To install it, run: 26 | 27 | go get gopkg.in/yaml.v2 28 | 29 | API documentation 30 | ----------------- 31 | 32 | If opened in a browser, the import path itself leads to the API documentation: 33 | 34 | * [https://gopkg.in/yaml.v2](https://gopkg.in/yaml.v2) 35 | 36 | API stability 37 | ------------- 38 | 39 | The package API for yaml v2 will remain stable as described in [gopkg.in](https://gopkg.in). 40 | 41 | 42 | License 43 | ------- 44 | 45 | The yaml package is licensed under the Apache License 2.0. Please see the LICENSE file for details. 46 | 47 | 48 | Example 49 | ------- 50 | 51 | ```Go 52 | package main 53 | 54 | import ( 55 | "fmt" 56 | "log" 57 | 58 | "gopkg.in/yaml.v2" 59 | ) 60 | 61 | var data = ` 62 | a: Easy! 63 | b: 64 | c: 2 65 | d: [3, 4] 66 | ` 67 | 68 | // Note: struct fields must be public in order for unmarshal to 69 | // correctly populate the data. 70 | type T struct { 71 | A string 72 | B struct { 73 | RenamedC int `yaml:"c"` 74 | D []int `yaml:",flow"` 75 | } 76 | } 77 | 78 | func main() { 79 | t := T{} 80 | 81 | err := yaml.Unmarshal([]byte(data), &t) 82 | if err != nil { 83 | log.Fatalf("error: %v", err) 84 | } 85 | fmt.Printf("--- t:\n%v\n\n", t) 86 | 87 | d, err := yaml.Marshal(&t) 88 | if err != nil { 89 | log.Fatalf("error: %v", err) 90 | } 91 | fmt.Printf("--- t dump:\n%s\n\n", string(d)) 92 | 93 | m := make(map[interface{}]interface{}) 94 | 95 | err = yaml.Unmarshal([]byte(data), &m) 96 | if err != nil { 97 | log.Fatalf("error: %v", err) 98 | } 99 | fmt.Printf("--- m:\n%v\n\n", m) 100 | 101 | d, err = yaml.Marshal(&m) 102 | if err != nil { 103 | log.Fatalf("error: %v", err) 104 | } 105 | fmt.Printf("--- m dump:\n%s\n\n", string(d)) 106 | } 107 | ``` 108 | 109 | This example will generate the following output: 110 | 111 | ``` 112 | --- t: 113 | {Easy! {2 [3 4]}} 114 | 115 | --- t dump: 116 | a: Easy! 117 | b: 118 | c: 2 119 | d: [3, 4] 120 | 121 | 122 | --- m: 123 | map[a:Easy! b:map[c:2 d:[3 4]]] 124 | 125 | --- m dump: 126 | a: Easy! 127 | b: 128 | c: 2 129 | d: 130 | - 3 131 | - 4 132 | ``` 133 | 134 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v2/go.mod: -------------------------------------------------------------------------------- 1 | module "gopkg.in/yaml.v2" 2 | 3 | require ( 4 | "gopkg.in/check.v1" v0.0.0-20161208181325-20d25e280405 5 | ) 6 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v2/sorter.go: -------------------------------------------------------------------------------- 1 | package yaml 2 | 3 | import ( 4 | "reflect" 5 | "unicode" 6 | ) 7 | 8 | type keyList []reflect.Value 9 | 10 | func (l keyList) Len() int { return len(l) } 11 | func (l keyList) Swap(i, j int) { l[i], l[j] = l[j], l[i] } 12 | func (l keyList) Less(i, j int) bool { 13 | a := l[i] 14 | b := l[j] 15 | ak := a.Kind() 16 | bk := b.Kind() 17 | for (ak == reflect.Interface || ak == reflect.Ptr) && !a.IsNil() { 18 | a = a.Elem() 19 | ak = a.Kind() 20 | } 21 | for (bk == reflect.Interface || bk == reflect.Ptr) && !b.IsNil() { 22 | b = b.Elem() 23 | bk = b.Kind() 24 | } 25 | af, aok := keyFloat(a) 26 | bf, bok := keyFloat(b) 27 | if aok && bok { 28 | if af != bf { 29 | return af < bf 30 | } 31 | if ak != bk { 32 | return ak < bk 33 | } 34 | return numLess(a, b) 35 | } 36 | if ak != reflect.String || bk != reflect.String { 37 | return ak < bk 38 | } 39 | ar, br := []rune(a.String()), []rune(b.String()) 40 | for i := 0; i < len(ar) && i < len(br); i++ { 41 | if ar[i] == br[i] { 42 | continue 43 | } 44 | al := unicode.IsLetter(ar[i]) 45 | bl := unicode.IsLetter(br[i]) 46 | if al && bl { 47 | return ar[i] < br[i] 48 | } 49 | if al || bl { 50 | return bl 51 | } 52 | var ai, bi int 53 | var an, bn int64 54 | if ar[i] == '0' || br[i] == '0' { 55 | for j := i-1; j >= 0 && unicode.IsDigit(ar[j]); j-- { 56 | if ar[j] != '0' { 57 | an = 1 58 | bn = 1 59 | break 60 | } 61 | } 62 | } 63 | for ai = i; ai < len(ar) && unicode.IsDigit(ar[ai]); ai++ { 64 | an = an*10 + int64(ar[ai]-'0') 65 | } 66 | for bi = i; bi < len(br) && unicode.IsDigit(br[bi]); bi++ { 67 | bn = bn*10 + int64(br[bi]-'0') 68 | } 69 | if an != bn { 70 | return an < bn 71 | } 72 | if ai != bi { 73 | return ai < bi 74 | } 75 | return ar[i] < br[i] 76 | } 77 | return len(ar) < len(br) 78 | } 79 | 80 | // keyFloat returns a float value for v if it is a number/bool 81 | // and whether it is a number/bool or not. 82 | func keyFloat(v reflect.Value) (f float64, ok bool) { 83 | switch v.Kind() { 84 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 85 | return float64(v.Int()), true 86 | case reflect.Float32, reflect.Float64: 87 | return v.Float(), true 88 | case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: 89 | return float64(v.Uint()), true 90 | case reflect.Bool: 91 | if v.Bool() { 92 | return 1, true 93 | } 94 | return 0, true 95 | } 96 | return 0, false 97 | } 98 | 99 | // numLess returns whether a < b. 100 | // a and b must necessarily have the same kind. 101 | func numLess(a, b reflect.Value) bool { 102 | switch a.Kind() { 103 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 104 | return a.Int() < b.Int() 105 | case reflect.Float32, reflect.Float64: 106 | return a.Float() < b.Float() 107 | case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: 108 | return a.Uint() < b.Uint() 109 | case reflect.Bool: 110 | return !a.Bool() && b.Bool() 111 | } 112 | panic("not a number") 113 | } 114 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v2/writerc.go: -------------------------------------------------------------------------------- 1 | package yaml 2 | 3 | // Set the writer error and return false. 4 | func yaml_emitter_set_writer_error(emitter *yaml_emitter_t, problem string) bool { 5 | emitter.error = yaml_WRITER_ERROR 6 | emitter.problem = problem 7 | return false 8 | } 9 | 10 | // Flush the output buffer. 11 | func yaml_emitter_flush(emitter *yaml_emitter_t) bool { 12 | if emitter.write_handler == nil { 13 | panic("write handler not set") 14 | } 15 | 16 | // Check if the buffer is empty. 17 | if emitter.buffer_pos == 0 { 18 | return true 19 | } 20 | 21 | if err := emitter.write_handler(emitter, emitter.buffer[:emitter.buffer_pos]); err != nil { 22 | return yaml_emitter_set_writer_error(emitter, "write error: "+err.Error()) 23 | } 24 | emitter.buffer_pos = 0 25 | return true 26 | } 27 | -------------------------------------------------------------------------------- /vendor/modules.txt: -------------------------------------------------------------------------------- 1 | # github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc 2 | ## explicit 3 | github.com/alecthomas/template 4 | github.com/alecthomas/template/parse 5 | # github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf 6 | ## explicit 7 | github.com/alecthomas/units 8 | # github.com/davecgh/go-spew v1.1.0 9 | github.com/davecgh/go-spew/spew 10 | # github.com/gorilla/websocket v1.4.0 11 | ## explicit 12 | github.com/gorilla/websocket 13 | # github.com/hashicorp/go-cleanhttp v0.5.1 14 | ## explicit 15 | github.com/hashicorp/go-cleanhttp 16 | # github.com/heptio/workgroup v0.8.0-beta.1 17 | ## explicit 18 | github.com/heptio/workgroup 19 | # github.com/mailru/easyjson v0.0.0-20190403194419-1ea4449da983 20 | ## explicit 21 | github.com/mailru/easyjson 22 | github.com/mailru/easyjson/buffer 23 | github.com/mailru/easyjson/jlexer 24 | github.com/mailru/easyjson/jwriter 25 | # github.com/pkg/errors v0.9.1 26 | ## explicit 27 | # github.com/pmezard/go-difflib v1.0.0 28 | github.com/pmezard/go-difflib/difflib 29 | # github.com/stretchr/testify v1.5.1 30 | ## explicit 31 | github.com/stretchr/testify/assert 32 | # github.com/urfave/negroni v1.0.0 33 | ## explicit 34 | github.com/urfave/negroni 35 | # go.uber.org/atomic v1.2.0 36 | ## explicit 37 | go.uber.org/atomic 38 | # go.uber.org/multierr v1.1.0 39 | ## explicit 40 | go.uber.org/multierr 41 | # go.uber.org/zap v1.9.1 42 | ## explicit 43 | go.uber.org/zap 44 | go.uber.org/zap/buffer 45 | go.uber.org/zap/internal/bufferpool 46 | go.uber.org/zap/internal/color 47 | go.uber.org/zap/internal/exit 48 | go.uber.org/zap/zapcore 49 | # gopkg.in/alecthomas/kingpin.v2 v2.2.6 50 | ## explicit 51 | gopkg.in/alecthomas/kingpin.v2 52 | # gopkg.in/yaml.v2 v2.2.2 53 | gopkg.in/yaml.v2 54 | -------------------------------------------------------------------------------- /version/version.go: -------------------------------------------------------------------------------- 1 | package version 2 | 3 | import ( 4 | "runtime" 5 | 6 | "github.com/webhookrelay/relay-go/pkg/types" 7 | ) 8 | 9 | const ( 10 | ProductName = "relay-go" 11 | APIVersion = "1" 12 | ) 13 | 14 | // Revision that was compiled. This will be filled in by the compiler. 15 | var Revision string 16 | 17 | // BuildDate is when the binary was compiled. This will be filled in by the 18 | // compiler. 19 | var BuildDate string 20 | 21 | // Version number that is being run at the moment. Version should use semver. 22 | var Version = "develop" 23 | 24 | // Experimental is intended to be used to enable alpha features. 25 | var Experimental string 26 | 27 | // GetWebhookRelayVersion returns version info. 28 | func GetWebhookRelayVersion() types.VersionInfo { 29 | v := types.VersionInfo{ 30 | Name: ProductName, 31 | Revision: Revision, 32 | BuildDate: BuildDate, 33 | Version: Version, 34 | APIVersion: APIVersion, 35 | GoVersion: runtime.Version(), 36 | OS: runtime.GOOS, 37 | Arch: runtime.GOARCH, 38 | } 39 | return v 40 | } 41 | --------------------------------------------------------------------------------