Initial commit

This commit is contained in:
Donny
2019-04-22 20:46:32 +08:00
commit 49ab8aadd1
25441 changed files with 4055000 additions and 0 deletions

34
vendor/gopkg.in/h2non/gock.v1/BUILD.bazel generated vendored Normal file
View File

@@ -0,0 +1,34 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = [
"gock.go",
"matcher.go",
"matchers.go",
"mock.go",
"request.go",
"responder.go",
"response.go",
"store.go",
"transport.go",
"version.go",
],
importmap = "go-common/vendor/gopkg.in/h2non/gock.v1",
importpath = "gopkg.in/h2non/gock.v1",
visibility = ["//visibility:public"],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

80
vendor/gopkg.in/h2non/gock.v1/History.md generated vendored Normal file
View File

@@ -0,0 +1,80 @@
## v1.0.7 / 2017-12-21
* Make MatchHost case insensitive. (#31)
* refactor(docs): remove codesponsor :(
* add example when request reply with error (#28)
* feat(docs): add sponsor ad
* Add example networking partially enabled (#23)
## v1.0.6 / 2017-07-27
* fix(#23): mock transport deadlock
## v1.0.5 / 2017-07-26
* feat(#25, #24): use content type only if missing while matching JSON/XML
* feat(#24): add CleanUnmatchedRequests() and OffAll() public functions
* feat(version): bump to v1.0.5
* fix(store): use proper indent style
* fix(mutex): use different mutex for store
* feat(travis): add Go 1.8 CI support
## v1.0.4 / 2017-02-14
* Update README to include most up to date version (#17)
* Update MatchBody() to compare if key + value pairs of JSON match regardless of order they are in. (#16)
* feat(examples): add new example for unmatch case
* refactor(docs): add pook reference
## 1.0.3 / 14-11-2016
- feat(#13): adds `GetUnmatchedRequests()` and `HasUnmatchedRequests()` API functions.
## 1.0.2 / 10-11-2016
- fix(#11): adds `Compression()` method for output HTTP traffic body compression processing and matching.
## 1.0.1 / 07-09-2016
- fix(#9): missing URL query param matcher.
## 1.0.0 / 19-04-2016
- feat(version): first major version release.
## 0.1.6 / 19-04-2016
- fix(#7): if error configured, RoundTripper should reply with `nil` response.
## 0.1.5 / 09-04-2016
- feat(#5): support `ReplyFunc` for convenience.
## 0.1.4 / 16-03-2016
- feat(api): add `IsDone()` method.
- fix(responder): return mock error if present.
- feat(#4): support define request/response body from file disk.
## 0.1.3 / 09-03-2016
- feat(matcher): add content type matcher helper method supporting aliases.
- feat(interceptor): add function to restore HTTP client transport.
- feat(matcher): add URL scheme matcher function.
- fix(request): ignore base slash path.
- feat(api): add Off() method for easier restore and clean up.
- feat(store): add public API for pending mocks.
## 0.1.2 / 04-03-2016
- fix(matcher): body matchers no used by default.
- feat(matcher): add matcher factories for multiple cases.
## 0.1.1 / 04-03-2016
- fix(params): persist query params accordingly.
## 0.1.0 / 02-03-2016
- First release.

24
vendor/gopkg.in/h2non/gock.v1/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,24 @@
The MIT License
Copyright (c) 2016-2017 Tomas Aparicio
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

274
vendor/gopkg.in/h2non/gock.v1/README.md generated vendored Normal file
View File

@@ -0,0 +1,274 @@
# gock [![Build Status](https://travis-ci.org/h2non/gock.svg?branch=master)](https://travis-ci.org/h2non/gock) [![GitHub release](https://img.shields.io/badge/version-v1.0-orange.svg?style=flat)](https://github.com/h2non/gock/releases) [![GoDoc](https://godoc.org/github.com/h2non/gock?status.svg)](https://godoc.org/github.com/h2non/gock) [![Coverage Status](https://coveralls.io/repos/github/h2non/gock/badge.svg?branch=master)](https://coveralls.io/github/h2non/gock?branch=master) [![Go Report Card](https://img.shields.io/badge/go_report-A+-brightgreen.svg)](https://goreportcard.com/report/github.com/h2non/gock) [![license](https://img.shields.io/badge/license-MIT-blue.svg)]()
Versatile HTTP mocking made easy in [Go](https://golang.org).
Heavily inspired by [nock](https://github.com/node-nock/nock). See also its Python port, [pook](https://github.com/h2non/pook).
Take a look to the [examples](#examples) to get started.
## Features
- Simple, expressive, fluent API.
- Semantic DSL for easy HTTP mocks definition.
- Built-in helpers for easy JSON/XML mocking.
- Supports persistent and volatile mocks.
- Full regexp capable HTTP request matching.
- Designed for both testing and runtime scenarios.
- Match request by method, URL params, headers and bodies.
- Extensible and pluggable HTTP matching rules.
- Ability to switch between mock and real networking modes.
- Ability to filter/map HTTP requests for accurate mock matching.
- Supports map and filters to handle mocks easily.
- Wide compatible HTTP interceptor using `http.RoundTripper` interface.
- Works with any `net/http` compatible client, such as [gentleman](https://github.com/h2non/gentleman).
- Network delay simulation (beta).
- Extensible and hackable API.
- Dependency free.
## Installation
```bash
go get -u gopkg.in/h2non/gock.v1
```
## API
See [godoc reference](https://godoc.org/github.com/h2non/gock) for detailed API documentation.
## How it mocks
1. Intercepts any HTTP outgoing request via `http.DefaultTransport` or custom `http.Transport` used by any `http.Client`.
2. Matches outgoing HTTP requests against a pool of defined HTTP mock expectations in FIFO declaration order.
3. If at least one mock matches, it will be used in order to compose the mock HTTP response.
4. If no mock can be matched, it will resolve the request with an error, unless real networking mode is enable, in which case a real HTTP request will be performed.
## Tips
#### Testing
Declare your mocks before you start declaring the concrete test logic:
```go
func TestFoo(t *testing.T) {
defer gock.Off() // Flush pending mocks after test execution
gock.New("http://server.com").
Get("/bar").
Reply(200).
JSON(map[string]string{"foo": "bar"})
// Your test code starts here...
}
```
#### Race conditions
If you're running concurrent code, be aware that your mocks are declared first to avoid unexpected
race conditions while configuring `gock` or intercepting custom HTTP clients.
`gock` is not fully thread-safe, but sensible parts are. Any help making `gock` more reliable in this sense is highly appreciated.
#### Define complex mocks first
If you're mocking a bunch of mocks in the same test suite, it's recommended to define the more
concrete mocks first, and then the generic ones.
This approach usually avoids matching unexpected generic mocks (e.g: specific header, body payload...) instead of the generic ones that performs less complex matches.
## Examples
See [examples](https://github.com/h2non/gock/tree/master/_examples) directory for more featured use cases.
#### Simple mocking via tests
```go
package test
import (
"github.com/nbio/st"
"gopkg.in/h2non/gock.v1"
"io/ioutil"
"net/http"
"testing"
)
func TestSimple(t *testing.T) {
defer gock.Off()
gock.New("http://foo.com").
Get("/bar").
Reply(200).
JSON(map[string]string{"foo": "bar"})
res, err := http.Get("http://foo.com/bar")
st.Expect(t, err, nil)
st.Expect(t, res.StatusCode, 200)
body, _ := ioutil.ReadAll(res.Body)
st.Expect(t, string(body)[:13], `{"foo":"bar"}`)
// Verify that we don't have pending mocks
st.Expect(t, gock.IsDone(), true)
}
```
#### Request headers matching
```go
package test
import (
"github.com/nbio/st"
"gopkg.in/h2non/gock.v1"
"io/ioutil"
"net/http"
"testing"
)
func TestMatchHeaders(t *testing.T) {
defer gock.Off()
gock.New("http://foo.com").
MatchHeader("Authorization", "^foo bar$").
MatchHeader("API", "1.[0-9]+").
HeaderPresent("Accept").
Reply(200).
BodyString("foo foo")
req, err := http.NewRequest("GET", "http://foo.com", nil)
req.Header.Set("Authorization", "foo bar")
req.Header.Set("API", "1.0")
req.Header.Set("Accept", "text/plain")
res, err := (&http.Client{}).Do(req)
st.Expect(t, err, nil)
st.Expect(t, res.StatusCode, 200)
body, _ := ioutil.ReadAll(res.Body)
st.Expect(t, string(body), "foo foo")
// Verify that we don't have pending mocks
st.Expect(t, gock.IsDone(), true)
}
```
#### JSON body matching and response
```go
package test
import (
"bytes"
"github.com/nbio/st"
"gopkg.in/h2non/gock.v1"
"io/ioutil"
"net/http"
"testing"
)
func TestMockSimple(t *testing.T) {
defer gock.Off()
gock.New("http://foo.com").
Post("/bar").
MatchType("json").
JSON(map[string]string{"foo": "bar"}).
Reply(201).
JSON(map[string]string{"bar": "foo"})
body := bytes.NewBuffer([]byte(`{"foo":"bar"}`))
res, err := http.Post("http://foo.com/bar", "application/json", body)
st.Expect(t, err, nil)
st.Expect(t, res.StatusCode, 201)
resBody, _ := ioutil.ReadAll(res.Body)
st.Expect(t, string(resBody)[:13], `{"bar":"foo"}`)
// Verify that we don't have pending mocks
st.Expect(t, gock.IsDone(), true)
}
```
#### Mocking a custom http.Client and http.RoundTripper
```go
package test
import (
"github.com/nbio/st"
"gopkg.in/h2non/gock.v1"
"io/ioutil"
"net/http"
"testing"
)
func TestClient(t *testing.T) {
defer gock.Off()
gock.New("http://foo.com").
Reply(200).
BodyString("foo foo")
req, err := http.NewRequest("GET", "http://foo.com", nil)
client := &http.Client{Transport: &http.Transport{}}
gock.InterceptClient(client)
res, err := client.Do(req)
st.Expect(t, err, nil)
st.Expect(t, res.StatusCode, 200)
body, _ := ioutil.ReadAll(res.Body)
st.Expect(t, string(body), "foo foo")
// Verify that we don't have pending mocks
st.Expect(t, gock.IsDone(), true)
}
```
#### Enable real networking
```go
package main
import (
"fmt"
"gopkg.in/h2non/gock.v1"
"io/ioutil"
"net/http"
)
func main() {
defer gock.Off()
defer gock.DisableNetworking()
gock.EnableNetworking()
gock.New("http://httpbin.org").
Get("/get").
Reply(201).
SetHeader("Server", "gock")
res, err := http.Get("http://httpbin.org/get")
if err != nil {
fmt.Errorf("Error: %s", err)
}
// The response status comes from the mock
fmt.Printf("Status: %d\n", res.StatusCode)
// The server header comes from mock as well
fmt.Printf("Server header: %s\n", res.Header.Get("Server"))
// Response body is the original
body, _ := ioutil.ReadAll(res.Body)
fmt.Printf("Body: %s", string(body))
// Verify that we don't have pending mocks
st.Expect(t, gock.IsDone(), true)
}
```
## Hacking it!
You can easily hack `gock` defining custom matcher functions with own matching rules.
See [add matcher functions](https://github.com/h2non/gock/blob/master/_examples/add_matchers/matchers.go) and [custom matching layer](https://github.com/h2non/gock/blob/master/_examples/custom_matcher/matcher.go) examples for further details.
## License
MIT - Tomas Aparicio

149
vendor/gopkg.in/h2non/gock.v1/gock.go generated vendored Normal file
View File

@@ -0,0 +1,149 @@
package gock
import (
"net/http"
"net/url"
"regexp"
"sync"
)
// mutex is used interally for locking thread-sensitive functions.
var mutex = &sync.Mutex{}
// config global singleton store.
var config = struct {
Networking bool
NetworkingFilters []FilterRequestFunc
}{}
// track unmatched requests so they can be tested for
var unmatchedRequests = []*http.Request{}
// New creates and registers a new HTTP mock with
// default settings and returns the Request DSL for HTTP mock
// definition and set up.
func New(uri string) *Request {
Intercept()
res := NewResponse()
req := NewRequest()
req.URLStruct, res.Error = url.Parse(normalizeURI(uri))
// Create the new mock expectation
exp := NewMock(req, res)
Register(exp)
return req
}
// Intercepting returns true if gock is currently able to intercept.
func Intercepting() bool {
return http.DefaultTransport == DefaultTransport
}
// Intercept enables HTTP traffic interception via http.DefaultTransport.
// If you are using a custom HTTP transport, you have to use `gock.Transport()`
func Intercept() {
if !Intercepting() {
http.DefaultTransport = DefaultTransport
}
}
// InterceptClient allows the developer to intercept HTTP traffic using
// a custom http.Client who uses a non default http.Transport/http.RoundTripper implementation.
func InterceptClient(cli *http.Client) {
trans := NewTransport()
trans.Transport = cli.Transport
cli.Transport = trans
}
// RestoreClient allows the developer to disable and restore the
// original transport in the given http.Client.
func RestoreClient(cli *http.Client) {
trans, ok := cli.Transport.(*Transport)
if !ok {
return
}
cli.Transport = trans.Transport
}
// Disable disables HTTP traffic interception by gock.
func Disable() {
mutex.Lock()
defer mutex.Unlock()
http.DefaultTransport = NativeTransport
}
// Off disables the default HTTP interceptors and removes
// all the registered mocks, even if they has not been intercepted yet.
func Off() {
Flush()
Disable()
}
// OffAll is like `Off()`, but it also removes the unmatched requests registry.
func OffAll() {
Flush()
Disable()
CleanUnmatchedRequest()
}
// EnableNetworking enables real HTTP networking
func EnableNetworking() {
mutex.Lock()
defer mutex.Unlock()
config.Networking = true
}
// DisableNetworking disables real HTTP networking
func DisableNetworking() {
mutex.Lock()
defer mutex.Unlock()
config.Networking = false
}
// NetworkingFilter determines if an http.Request should be triggered or not.
func NetworkingFilter(fn FilterRequestFunc) {
mutex.Lock()
defer mutex.Unlock()
config.NetworkingFilters = append(config.NetworkingFilters, fn)
}
// DisableNetworkingFilters disables registered networking filters.
func DisableNetworkingFilters() {
mutex.Lock()
defer mutex.Unlock()
config.NetworkingFilters = []FilterRequestFunc{}
}
// GetUnmatchedRequests returns all requests that have been received but haven't matched any mock
func GetUnmatchedRequests() []*http.Request {
mutex.Lock()
defer mutex.Unlock()
return unmatchedRequests
}
// HasUnmatchedRequest returns true if gock has received any requests that didn't match a mock
func HasUnmatchedRequest() bool {
return len(GetUnmatchedRequests()) > 0
}
// CleanUnmatchedRequest cleans the unmatched requests internal registry.
func CleanUnmatchedRequest() {
mutex.Lock()
defer mutex.Unlock()
unmatchedRequests = []*http.Request{}
}
func trackUnmatchedRequest(req *http.Request) {
mutex.Lock()
defer mutex.Unlock()
unmatchedRequests = append(unmatchedRequests, req)
}
func normalizeURI(uri string) string {
if ok, _ := regexp.MatchString("^http[s]?", uri); !ok {
return "http://" + uri
}
return uri
}

117
vendor/gopkg.in/h2non/gock.v1/matcher.go generated vendored Normal file
View File

@@ -0,0 +1,117 @@
package gock
import "net/http"
// MatchersHeader exposes an slice of HTTP header specific mock matchers.
var MatchersHeader = []MatchFunc{
MatchMethod,
MatchScheme,
MatchHost,
MatchPath,
MatchHeaders,
MatchQueryParams,
}
// MatchersBody exposes an slice of HTTP body specific built-in mock matchers.
var MatchersBody = []MatchFunc{
MatchBody,
}
// Matchers stores all the built-in mock matchers.
var Matchers = append(MatchersHeader, MatchersBody...)
// DefaultMatcher stores the default Matcher instance used to match mocks.
var DefaultMatcher = NewMatcher()
// MatchFunc represents the required function
// interface implemented by matchers.
type MatchFunc func(*http.Request, *Request) (bool, error)
// Matcher represents the required interface implemented by mock matchers.
type Matcher interface {
// Get returns a slice of registered function matchers.
Get() []MatchFunc
// Add adds a new matcher function.
Add(MatchFunc)
// Set sets the matchers functions stack.
Set([]MatchFunc)
// Flush flushes the current matchers function stack.
Flush()
// Match matches the given http.Request with a mock Request.
Match(*http.Request, *Request) (bool, error)
}
// MockMatcher implements a mock matcher
type MockMatcher struct {
Matchers []MatchFunc
}
// NewMatcher creates a new mock matcher
// using the default matcher functions.
func NewMatcher() *MockMatcher {
return &MockMatcher{Matchers: Matchers}
}
// NewBasicMatcher creates a new matcher with header only mock matchers.
func NewBasicMatcher() *MockMatcher {
return &MockMatcher{Matchers: MatchersHeader}
}
// NewEmptyMatcher creates a new empty matcher with out default amtchers.
func NewEmptyMatcher() *MockMatcher {
return &MockMatcher{Matchers: []MatchFunc{}}
}
// Get returns a slice of registered function matchers.
func (m *MockMatcher) Get() []MatchFunc {
return m.Matchers
}
// Add adds a new function matcher.
func (m *MockMatcher) Add(fn MatchFunc) {
m.Matchers = append(m.Matchers, fn)
}
// Set sets a new stack of matchers functions.
func (m *MockMatcher) Set(stack []MatchFunc) {
m.Matchers = stack
}
// Flush flushes the current matcher
func (m *MockMatcher) Flush() {
m.Matchers = []MatchFunc{}
}
// Match matches the given http.Request with a mock request
// returning true in case that the request matches, otherwise false.
func (m *MockMatcher) Match(req *http.Request, ereq *Request) (bool, error) {
for _, matcher := range m.Matchers {
matches, err := matcher(req, ereq)
if err != nil {
return false, err
}
if !matches {
return false, nil
}
}
return true, nil
}
// MatchMock is a helper function that matches the given http.Request
// in the list of registered mocks, returning it if matches or error if it fails.
func MatchMock(req *http.Request) (Mock, error) {
for _, mock := range GetAll() {
matches, err := mock.Match(req)
if err != nil {
return nil, err
}
if matches {
return mock, nil
}
}
return nil, nil
}

232
vendor/gopkg.in/h2non/gock.v1/matchers.go generated vendored Normal file
View File

@@ -0,0 +1,232 @@
package gock
import (
"compress/gzip"
"encoding/json"
"io"
"io/ioutil"
"net/http"
"reflect"
"regexp"
"strings"
)
// EOL represents the end of line character.
const EOL = 0xa
// BodyTypes stores the supported MIME body types for matching.
// Currently only text-based types.
var BodyTypes = []string{
"text/html",
"text/plain",
"application/json",
"application/xml",
"multipart/form-data",
"application/x-www-form-urlencoded",
}
// BodyTypeAliases stores a generic MIME type by alias.
var BodyTypeAliases = map[string]string{
"html": "text/html",
"text": "text/plain",
"json": "application/json",
"xml": "application/xml",
"form": "multipart/form-data",
"url": "application/x-www-form-urlencoded",
}
// CompressionSchemes stores the supported Content-Encoding types for decompression.
var CompressionSchemes = []string{
"gzip",
}
// MatchMethod matches the HTTP method of the given request.
func MatchMethod(req *http.Request, ereq *Request) (bool, error) {
return ereq.Method == "" || req.Method == ereq.Method, nil
}
// MatchScheme matches the request URL protocol scheme.
func MatchScheme(req *http.Request, ereq *Request) (bool, error) {
return ereq.URLStruct.Scheme == "" || req.URL.Scheme == "" || ereq.URLStruct.Scheme == req.URL.Scheme, nil
}
// MatchHost matches the HTTP host header field of the given request.
func MatchHost(req *http.Request, ereq *Request) (bool, error) {
url := ereq.URLStruct
if strings.EqualFold(url.Host, req.URL.Host) {
return true, nil
}
return regexp.MatchString(url.Host, req.URL.Host)
}
// MatchPath matches the HTTP URL path of the given request.
func MatchPath(req *http.Request, ereq *Request) (bool, error) {
return regexp.MatchString(ereq.URLStruct.Path, req.URL.Path)
}
// MatchHeaders matches the headers fields of the given request.
func MatchHeaders(req *http.Request, ereq *Request) (bool, error) {
for key, value := range ereq.Header {
var err error
var match bool
for _, field := range req.Header[key] {
match, err = regexp.MatchString(value[0], field)
if err != nil {
return false, err
}
if match {
break
}
}
if !match {
return false, nil
}
}
return true, nil
}
// MatchQueryParams matches the URL query params fields of the given request.
func MatchQueryParams(req *http.Request, ereq *Request) (bool, error) {
for key, value := range ereq.URLStruct.Query() {
var err error
var match bool
for _, field := range req.URL.Query()[key] {
match, err = regexp.MatchString(value[0], field)
if err != nil {
return false, err
}
if match {
break
}
}
if !match {
return false, nil
}
}
return true, nil
}
// MatchBody tries to match the request body.
// TODO: not too smart now, needs several improvements.
func MatchBody(req *http.Request, ereq *Request) (bool, error) {
// If match body is empty, just continue
if req.Method == "HEAD" || len(ereq.BodyBuffer) == 0 {
return true, nil
}
// Only can match certain MIME body types
if !supportedType(req) {
return false, nil
}
// Can only match certain compression schemes
if !supportedCompressionScheme(req) {
return false, nil
}
// Create a reader for the body depending on compression type
bodyReader := req.Body
if ereq.CompressionScheme != "" {
if ereq.CompressionScheme != req.Header.Get("Content-Encoding") {
return false, nil
}
compressedBodyReader, err := compressionReader(req.Body, ereq.CompressionScheme)
if err != nil {
return false, err
}
bodyReader = compressedBodyReader
}
// Read the whole request body
body, err := ioutil.ReadAll(bodyReader)
if err != nil {
return false, err
}
// Restore body reader stream
req.Body = createReadCloser(body)
// If empty, ignore the match
if len(body) == 0 && len(ereq.BodyBuffer) != 0 {
return false, nil
}
// Match body by atomic string comparison
bodyStr := castToString(body)
matchStr := castToString(ereq.BodyBuffer)
if bodyStr == matchStr {
return true, nil
}
// Match request body by regexp
match, _ := regexp.MatchString(matchStr, bodyStr)
if match == true {
return true, nil
}
// todo - add conditional do only perform the conversion of body bytes
// representation of JSON to a map and then compare them for equality.
// Check if the key + value pairs match
var bodyMap map[string]interface{}
var matchMap map[string]interface{}
// Ensure that both byte bodies that that should be JSON can be converted to maps.
umErr := json.Unmarshal(body, &bodyMap)
umErr2 := json.Unmarshal(ereq.BodyBuffer, &matchMap)
if umErr == nil && umErr2 == nil && reflect.DeepEqual(bodyMap, matchMap) {
return true, nil
}
return false, nil
}
func supportedType(req *http.Request) bool {
mime := req.Header.Get("Content-Type")
if mime == "" {
return true
}
for _, kind := range BodyTypes {
if match, _ := regexp.MatchString(kind, mime); match {
return true
}
}
return false
}
func supportedCompressionScheme(req *http.Request) bool {
encoding := req.Header.Get("Content-Encoding")
if encoding == "" {
return true
}
for _, kind := range CompressionSchemes {
if match, _ := regexp.MatchString(kind, encoding); match {
return true
}
}
return false
}
func castToString(buf []byte) string {
str := string(buf)
tail := len(str) - 1
if str[tail] == EOL {
str = str[:tail]
}
return str
}
func compressionReader(r io.ReadCloser, scheme string) (io.ReadCloser, error) {
switch scheme {
case "gzip":
return gzip.NewReader(r)
default:
return r, nil
}
}

146
vendor/gopkg.in/h2non/gock.v1/mock.go generated vendored Normal file
View File

@@ -0,0 +1,146 @@
package gock
import (
"net/http"
"sync"
)
// Mock represents the required interface that must
// be implemented by HTTP mock instances.
type Mock interface {
// Disable disables the current mock manually.
Disable()
// Done returns true if the current mock is disabled.
Done() bool
// Request returns the mock Request instance.
Request() *Request
// Response returns the mock Response instance.
Response() *Response
// Match matches the given http.Request with the current mock.
Match(*http.Request) (bool, error)
// AddMatcher adds a new matcher function.
AddMatcher(MatchFunc)
// SetMatcher uses a new matcher implementation.
SetMatcher(Matcher)
}
// Mocker implements a Mock capable interface providing
// a default mock configuration used internally to store mocks.
type Mocker struct {
// disabled stores if the current mock is disabled.
disabled bool
// mutex stores the mock mutex for thread safity.
mutex sync.Mutex
// matcher stores a Matcher capable instance to match the given http.Request.
matcher Matcher
// request stores the mock Request to match.
request *Request
// response stores the mock Response to use in case of match.
response *Response
}
// NewMock creates a new HTTP mock based on the given request and response instances.
// It's mostly used internally.
func NewMock(req *Request, res *Response) *Mocker {
mock := &Mocker{
request: req,
response: res,
matcher: DefaultMatcher,
}
res.Mock = mock
req.Mock = mock
req.Response = res
return mock
}
// Disable disables the current mock manually.
func (m *Mocker) Disable() {
m.disabled = true
}
// Done returns true in case that the current mock
// instance is disabled and therefore must be removed.
func (m *Mocker) Done() bool {
m.mutex.Lock()
defer m.mutex.Unlock()
return m.disabled || (!m.request.Persisted && m.request.Counter == 0)
}
// Request returns the Request instance
// configured for the current HTTP mock.
func (m *Mocker) Request() *Request {
return m.request
}
// Response returns the Response instance
// configured for the current HTTP mock.
func (m *Mocker) Response() *Response {
return m.response
}
// Match matches the given http.Request with the current Request
// mock expectation, returning true if matches.
func (m *Mocker) Match(req *http.Request) (bool, error) {
if m.disabled {
return false, nil
}
// Filter
for _, filter := range m.request.Filters {
if !filter(req) {
return false, nil
}
}
// Map
for _, mapper := range m.request.Mappers {
if treq := mapper(req); treq != nil {
req = treq
}
}
// Match
matches, err := m.matcher.Match(req, m.request)
if matches {
m.decrement()
}
return matches, err
}
// SetMatcher sets a new matcher implementation
// for the current mock expectation.
func (m *Mocker) SetMatcher(matcher Matcher) {
m.matcher = matcher
}
// AddMatcher adds a new matcher function
// for the current mock expectation.
func (m *Mocker) AddMatcher(fn MatchFunc) {
m.matcher.Add(fn)
}
// decrement decrements the current mock Request counter.
func (m *Mocker) decrement() {
if m.request.Persisted {
return
}
m.mutex.Lock()
defer m.mutex.Unlock()
m.request.Counter--
if m.request.Counter == 0 {
m.disabled = true
}
}

283
vendor/gopkg.in/h2non/gock.v1/request.go generated vendored Normal file
View File

@@ -0,0 +1,283 @@
package gock
import (
"io"
"io/ioutil"
"net/http"
"net/url"
"strings"
)
// MapRequestFunc represents the required function interface for request mappers.
type MapRequestFunc func(*http.Request) *http.Request
// FilterRequestFunc represents the required function interface for request filters.
type FilterRequestFunc func(*http.Request) bool
// Request represents the high-level HTTP request used to store
// request fields used to match intercepted requests.
type Request struct {
// Mock stores the parent mock reference for the current request mock used for method delegation.
Mock Mock
// Response stores the current Response instance for the current matches Request.
Response *Response
// Error stores the latest mock request configuration error.
Error error
// Counter stores the pending times that the current mock should be active.
Counter int
// Persisted stores if the current mock should be always active.
Persisted bool
// URLStruct stores the parsed URL as *url.URL struct.
URLStruct *url.URL
// Method stores the Request HTTP method to match.
Method string
// CompressionScheme stores the Request Compression scheme to match and use for decompression.
CompressionScheme string
// Header stores the HTTP header fields to match.
Header http.Header
// Cookies stores the Request HTTP cookies values to match.
Cookies []*http.Cookie
// BodyBuffer stores the body data to match.
BodyBuffer []byte
// Mappers stores the request functions mappers used for matching.
Mappers []MapRequestFunc
// Filters stores the request functions filters used for matching.
Filters []FilterRequestFunc
}
// NewRequest creates a new Request instance.
func NewRequest() *Request {
return &Request{
Counter: 1,
URLStruct: &url.URL{},
Header: make(http.Header),
}
}
// URL defines the mock URL to match.
func (r *Request) URL(uri string) *Request {
r.URLStruct, r.Error = url.Parse(uri)
return r
}
// SetURL defines the url.URL struct to be used for matching.
func (r *Request) SetURL(u *url.URL) *Request {
r.URLStruct = u
return r
}
// Path defines the mock URL path value to match.
func (r *Request) Path(path string) *Request {
r.URLStruct.Path = path
return r
}
// Get specifies the GET method and the given URL path to match.
func (r *Request) Get(path string) *Request {
return r.method("GET", path)
}
// Post specifies the POST method and the given URL path to match.
func (r *Request) Post(path string) *Request {
return r.method("POST", path)
}
// Put specifies the PUT method and the given URL path to match.
func (r *Request) Put(path string) *Request {
return r.method("PUT", path)
}
// Delete specifies the DELETE method and the given URL path to match.
func (r *Request) Delete(path string) *Request {
return r.method("DELETE", path)
}
// Patch specifies the PATCH method and the given URL path to match.
func (r *Request) Patch(path string) *Request {
return r.method("PATCH", path)
}
// Head specifies the HEAD method and the given URL path to match.
func (r *Request) Head(path string) *Request {
return r.method("HEAD", path)
}
// method is a DRY shortcut used to declare the expected HTTP method and URL path.
func (r *Request) method(method, path string) *Request {
if path != "/" {
r.URLStruct.Path = path
}
r.Method = strings.ToUpper(method)
return r
}
// Body defines the body data to match based on a io.Reader interface.
func (r *Request) Body(body io.Reader) *Request {
r.BodyBuffer, r.Error = ioutil.ReadAll(body)
return r
}
// BodyString defines the body to match based on a given string.
func (r *Request) BodyString(body string) *Request {
r.BodyBuffer = []byte(body)
return r
}
// File defines the body to match based on the given file path string.
func (r *Request) File(path string) *Request {
r.BodyBuffer, r.Error = ioutil.ReadFile(path)
return r
}
// Compression defines the request compression scheme, and enables automatic body decompression.
// Supports only the "gzip" scheme so far.
func (r *Request) Compression(scheme string) *Request {
r.Header.Set("Content-Encoding", scheme)
r.CompressionScheme = scheme
return r
}
// JSON defines the JSON body to match based on a given structure.
func (r *Request) JSON(data interface{}) *Request {
if r.Header.Get("Content-Type") == "" {
r.Header.Set("Content-Type", "application/json")
}
r.BodyBuffer, r.Error = readAndDecode(data, "json")
return r
}
// XML defines the XML body to match based on a given structure.
func (r *Request) XML(data interface{}) *Request {
if r.Header.Get("Content-Type") == "" {
r.Header.Set("Content-Type", "application/xml")
}
r.BodyBuffer, r.Error = readAndDecode(data, "xml")
return r
}
// MatchType defines the request Content-Type MIME header field.
// Supports type alias. E.g: json, xml, form, text...
func (r *Request) MatchType(kind string) *Request {
mime := BodyTypeAliases[kind]
if mime != "" {
kind = mime
}
r.Header.Set("Content-Type", kind)
return r
}
// MatchHeader defines a new key and value header to match.
func (r *Request) MatchHeader(key, value string) *Request {
r.Header.Set(key, value)
return r
}
// HeaderPresent defines that a header field must be present in the request.
func (r *Request) HeaderPresent(key string) *Request {
r.Header.Set(key, ".*")
return r
}
// MatchHeaders defines a map of key-value headers to match.
func (r *Request) MatchHeaders(headers map[string]string) *Request {
for key, value := range headers {
r.Header.Set(key, value)
}
return r
}
// MatchParam defines a new key and value URL query param to match.
func (r *Request) MatchParam(key, value string) *Request {
query := r.URLStruct.Query()
query.Set(key, value)
r.URLStruct.RawQuery = query.Encode()
return r
}
// MatchParams defines a map of URL query param key-value to match.
func (r *Request) MatchParams(params map[string]string) *Request {
query := r.URLStruct.Query()
for key, value := range params {
query.Set(key, value)
}
r.URLStruct.RawQuery = query.Encode()
return r
}
// ParamPresent matches if the given query param key is present in the URL.
func (r *Request) ParamPresent(key string) *Request {
r.MatchParam(key, ".*")
return r
}
// Persist defines the current HTTP mock as persistent and won't be removed after intercepting it.
func (r *Request) Persist() *Request {
r.Persisted = true
return r
}
// Times defines the number of times that the current HTTP mock should remain active.
func (r *Request) Times(num int) *Request {
r.Counter = num
return r
}
// AddMatcher adds a new matcher function to match the request.
func (r *Request) AddMatcher(fn MatchFunc) *Request {
r.Mock.AddMatcher(fn)
return r
}
// SetMatcher sets a new matcher function to match the request.
func (r *Request) SetMatcher(matcher Matcher) *Request {
r.Mock.SetMatcher(matcher)
return r
}
// Map adds a new request mapper function to map http.Request before the matching process.
func (r *Request) Map(fn MapRequestFunc) *Request {
r.Mappers = append(r.Mappers, fn)
return r
}
// Filter filters a new request filter function to filter http.Request before the matching process.
func (r *Request) Filter(fn FilterRequestFunc) *Request {
r.Filters = append(r.Filters, fn)
return r
}
// EnableNetworking enables the use real networking for the current mock.
func (r *Request) EnableNetworking() *Request {
if r.Response != nil {
r.Response.UseNetwork = true
}
return r
}
// Reply defines the Response status code and returns the mock Response DSL.
func (r *Request) Reply(status int) *Response {
return r.Response.Status(status)
}
// ReplyError defines the Response simulated error.
func (r *Request) ReplyError(err error) *Response {
return r.Response.SetError(err)
}
// ReplyFunc allows the developer to define the mock response via a custom function.
func (r *Request) ReplyFunc(replier func(*Response)) *Response {
replier(r.Response)
return r.Response
}

103
vendor/gopkg.in/h2non/gock.v1/responder.go generated vendored Normal file
View File

@@ -0,0 +1,103 @@
package gock
import (
"bytes"
"io"
"net/http"
"strconv"
"time"
)
// Responder builds a mock http.Response based on the given Response mock.
func Responder(req *http.Request, mock *Response, res *http.Response) (*http.Response, error) {
// If error present, reply it
err := mock.Error
if err != nil {
return nil, err
}
if res == nil {
res = createResponse(req)
}
// Apply response filter
for _, filter := range mock.Filters {
if !filter(res) {
return res, nil
}
}
// Define mock status code
if mock.StatusCode != 0 {
res.Status = strconv.Itoa(mock.StatusCode) + " " + http.StatusText(mock.StatusCode)
res.StatusCode = mock.StatusCode
}
// Define headers by merging fields
res.Header = mergeHeaders(res, mock)
// Define mock body, if present
if len(mock.BodyBuffer) > 0 {
res.ContentLength = int64(len(mock.BodyBuffer))
res.Body = createReadCloser(mock.BodyBuffer)
}
// Apply response mappers
for _, mapper := range mock.Mappers {
if tres := mapper(res); tres != nil {
res = tres
}
}
// Sleep to simulate delay, if necessary
if mock.ResponseDelay > 0 {
time.Sleep(mock.ResponseDelay)
}
return res, err
}
// createResponse creates a new http.Response with default fields.
func createResponse(req *http.Request) *http.Response {
return &http.Response{
ProtoMajor: 1,
ProtoMinor: 1,
Proto: "HTTP/1.1",
Request: req,
Header: make(http.Header),
Body: createReadCloser([]byte{}),
}
}
// mergeHeaders copies the mock headers.
func mergeHeaders(res *http.Response, mres *Response) http.Header {
for key := range mres.Header {
res.Header.Set(key, mres.Header.Get(key))
}
return res.Header
}
// createReadCloser creates an io.ReadCloser from a byte slice that is suitable for use as an
// http response body.
func createReadCloser(body []byte) io.ReadCloser {
return &dummyReadCloser{body: bytes.NewReader(body)}
}
// dummyReadCloser is used internally as io.ReadCloser capable interface for bodies.
type dummyReadCloser struct {
body io.ReadSeeker
}
// Read implements the required method by io.ReadClose interface.
func (d *dummyReadCloser) Read(p []byte) (n int, err error) {
n, err = d.body.Read(p)
if err == io.EOF {
d.body.Seek(0, 0)
}
return n, err
}
// Close implements a no-op required method by io.ReadClose interface.
func (d *dummyReadCloser) Close() error {
return nil
}

186
vendor/gopkg.in/h2non/gock.v1/response.go generated vendored Normal file
View File

@@ -0,0 +1,186 @@
package gock
import (
"bytes"
"encoding/json"
"encoding/xml"
"io"
"io/ioutil"
"net/http"
"time"
)
// MapResponseFunc represents the required function interface impletemed by response mappers.
type MapResponseFunc func(*http.Response) *http.Response
// FilterResponseFunc represents the required function interface impletemed by response filters.
type FilterResponseFunc func(*http.Response) bool
// Response represents high-level HTTP fields to configure
// and define HTTP responses intercepted by gock.
type Response struct {
// Mock stores the parent mock reference for the current response mock used for method delegation.
Mock Mock
// Error stores the latest response configuration or injected error.
Error error
// UseNetwork enables the use of real network for the current mock.
UseNetwork bool
// StatusCode stores the response status code.
StatusCode int
// Headers stores the response headers.
Header http.Header
// Cookies stores the response cookie fields.
Cookies []*http.Cookie
// BodyBuffer stores the array of bytes to use as body.
BodyBuffer []byte
// ResponseDelay stores the simulated response delay.
ResponseDelay time.Duration
// Mappers stores the request functions mappers used for matching.
Mappers []MapResponseFunc
// Filters stores the request functions filters used for matching.
Filters []FilterResponseFunc
}
// NewResponse creates a new Response.
func NewResponse() *Response {
return &Response{Header: make(http.Header)}
}
// Status defines the desired HTTP status code to reply in the current response.
func (r *Response) Status(code int) *Response {
r.StatusCode = code
return r
}
// Type defines the response Content-Type MIME header field.
// Supports type alias. E.g: json, xml, form, text...
func (r *Response) Type(kind string) *Response {
mime := BodyTypeAliases[kind]
if mime != "" {
kind = mime
}
r.Header.Set("Content-Type", kind)
return r
}
// SetHeader sets a new header field in the mock response.
func (r *Response) SetHeader(key, value string) *Response {
r.Header.Set(key, value)
return r
}
// AddHeader adds a new header field in the mock response
// with out removing an existent one.
func (r *Response) AddHeader(key, value string) *Response {
r.Header.Add(key, value)
return r
}
// SetHeaders sets a map of header fields in the mock response.
func (r *Response) SetHeaders(headers map[string]string) *Response {
for key, value := range headers {
r.Header.Add(key, value)
}
return r
}
// Body sets the HTTP response body to be used.
func (r *Response) Body(body io.Reader) *Response {
r.BodyBuffer, r.Error = ioutil.ReadAll(body)
return r
}
// BodyString defines the response body as string.
func (r *Response) BodyString(body string) *Response {
r.BodyBuffer = []byte(body)
return r
}
// File defines the response body reading the data
// from disk based on the file path string.
func (r *Response) File(path string) *Response {
r.BodyBuffer, r.Error = ioutil.ReadFile(path)
return r
}
// JSON defines the response body based on a JSON based input.
func (r *Response) JSON(data interface{}) *Response {
r.Header.Set("Content-Type", "application/json")
r.BodyBuffer, r.Error = readAndDecode(data, "json")
return r
}
// XML defines the response body based on a XML based input.
func (r *Response) XML(data interface{}) *Response {
r.Header.Set("Content-Type", "application/xml")
r.BodyBuffer, r.Error = readAndDecode(data, "xml")
return r
}
// SetError defines the response simulated error.
func (r *Response) SetError(err error) *Response {
r.Error = err
return r
}
// Delay defines the response simulated delay.
// This feature is still experimental and will be improved in the future.
func (r *Response) Delay(delay time.Duration) *Response {
r.ResponseDelay = delay
return r
}
// Map adds a new response mapper function to map http.Response before the matching process.
func (r *Response) Map(fn MapResponseFunc) *Response {
r.Mappers = append(r.Mappers, fn)
return r
}
// Filter filters a new request filter function to filter http.Request before the matching process.
func (r *Response) Filter(fn FilterResponseFunc) *Response {
r.Filters = append(r.Filters, fn)
return r
}
// EnableNetworking enables the use real networking for the current mock.
func (r *Response) EnableNetworking() *Response {
r.UseNetwork = true
return r
}
// Done returns true if the mock was done and disabled.
func (r *Response) Done() bool {
return r.Mock.Done()
}
func readAndDecode(data interface{}, kind string) ([]byte, error) {
buf := &bytes.Buffer{}
switch data.(type) {
case string:
buf.WriteString(data.(string))
case []byte:
buf.Write(data.([]byte))
default:
var err error
if kind == "xml" {
err = xml.NewEncoder(buf).Encode(data)
} else {
err = json.NewEncoder(buf).Encode(data)
}
if err != nil {
return nil, err
}
}
return ioutil.ReadAll(buf)
}

100
vendor/gopkg.in/h2non/gock.v1/store.go generated vendored Normal file
View File

@@ -0,0 +1,100 @@
package gock
import (
"sync"
)
// storeMutex is used interally for store synchronization.
var storeMutex = sync.RWMutex{}
// mocks is internally used to store registered mocks.
var mocks = []Mock{}
// Register registers a new mock in the current mocks stack.
func Register(mock Mock) {
if Exists(mock) {
return
}
// Make ops thread safe
mutex.Lock()
defer mutex.Unlock()
// Expose mock in request/response for delegation
mock.Request().Mock = mock
mock.Response().Mock = mock
// Registers the mock in the global store
mocks = append(mocks, mock)
}
// GetAll returns the current stack of registed mocks.
func GetAll() []Mock {
storeMutex.RLock()
defer storeMutex.RUnlock()
return mocks
}
// Exists checks if the given Mock is already registered.
func Exists(m Mock) bool {
storeMutex.RLock()
defer storeMutex.RUnlock()
for _, mock := range mocks {
if mock == m {
return true
}
}
return false
}
// Remove removes a registered mock by reference.
func Remove(m Mock) {
for i, mock := range mocks {
if mock == m {
storeMutex.Lock()
mocks = append(mocks[:i], mocks[i+1:]...)
storeMutex.Unlock()
}
}
}
// Flush flushes the current stack of registered mocks.
func Flush() {
storeMutex.Lock()
defer storeMutex.Unlock()
mocks = []Mock{}
}
// Pending returns an slice of pending mocks.
func Pending() []Mock {
Clean()
storeMutex.RLock()
defer storeMutex.RUnlock()
return mocks
}
// IsDone returns true if all the registered mocks has been triggered successfully.
func IsDone() bool {
return !IsPending()
}
// IsPending returns true if there are pending mocks.
func IsPending() bool {
return len(Pending()) > 0
}
// Clean cleans the mocks store removing disabled or obsolete mocks.
func Clean() {
storeMutex.Lock()
defer storeMutex.Unlock()
buf := []Mock{}
for _, mock := range mocks {
if mock.Done() {
continue
}
buf = append(buf, mock)
}
mocks = buf
}

107
vendor/gopkg.in/h2non/gock.v1/transport.go generated vendored Normal file
View File

@@ -0,0 +1,107 @@
package gock
import (
"errors"
"net/http"
"sync"
)
// var mutex *sync.Mutex = &sync.Mutex{}
var (
// DefaultTransport stores the default mock transport used by gock.
DefaultTransport = NewTransport()
// NativeTransport stores the native net/http default transport
// in order to restore it when needed.
NativeTransport = http.DefaultTransport
)
var (
// ErrCannotMatch store the error returned in case of no matches.
ErrCannotMatch = errors.New("gock: cannot match any request")
)
// Transport implements http.RoundTripper, which fulfills single http requests issued by
// an http.Client.
//
// gock's Transport encapsulates a given or default http.Transport for further
// delegation, if needed.
type Transport struct {
// mutex is used to make transport thread-safe of concurrent uses across goroutines.
mutex sync.Mutex
// Transport encapsulates the original http.RoundTripper transport interface for delegation.
Transport http.RoundTripper
}
// NewTransport creates a new *Transport with no responders.
func NewTransport() *Transport {
return &Transport{Transport: NativeTransport}
}
// RoundTrip receives HTTP requests and routes them to the appropriate responder. It is required to
// implement the http.RoundTripper interface. You will not interact with this directly, instead
// the *http.Client you are using will call it for you.
func (m *Transport) RoundTrip(req *http.Request) (*http.Response, error) {
// Just act as a proxy if not intercepting
if !Intercepting() {
return m.Transport.RoundTrip(req)
}
m.mutex.Lock()
defer Clean()
var err error
var res *http.Response
// Match mock for the incoming http.Request
mock, err := MatchMock(req)
if err != nil {
m.mutex.Unlock()
return nil, err
}
// Verify if should use real networking
networking := shouldUseNetwork(req, mock)
if !networking && mock == nil {
m.mutex.Unlock()
trackUnmatchedRequest(req)
return nil, ErrCannotMatch
}
// Ensure me unlock the mutex before building the response
m.mutex.Unlock()
// Perform real networking via original transport
if networking {
res, err = m.Transport.RoundTrip(req)
// In no mock matched, continue with the response
if err != nil || mock == nil {
return res, err
}
}
return Responder(req, mock.Response(), res)
}
// CancelRequest is a no-op function.
func (m *Transport) CancelRequest(req *http.Request) {}
func shouldUseNetwork(req *http.Request, mock Mock) bool {
if mock != nil && mock.Response().UseNetwork {
return true
}
if !config.Networking {
return false
}
if len(config.NetworkingFilters) == 0 {
return true
}
for _, filter := range config.NetworkingFilters {
if !filter(req) {
return false
}
}
return true
}

4
vendor/gopkg.in/h2non/gock.v1/version.go generated vendored Normal file
View File

@@ -0,0 +1,4 @@
package gock
// Version defines the current package semantic version.
const Version = "1.0.7"