Merge pull request #4403 from flycash/http-mock

Move mock to mock directory
This commit is contained in:
Ming Deng 2021-01-03 17:07:14 +08:00 committed by GitHub
commit 65f8590910
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 258 additions and 89 deletions

View File

@ -0,0 +1,36 @@
// Copyright 2020 beego
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package httplib
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestNewHttpResponseWithJsonBody(t *testing.T) {
// string
resp := NewHttpResponseWithJsonBody("{}")
assert.Equal(t, int64(2), resp.ContentLength)
resp = NewHttpResponseWithJsonBody([]byte("{}"))
assert.Equal(t, int64(2), resp.ContentLength)
resp = NewHttpResponseWithJsonBody(&user{
Name: "Tom",
})
assert.True(t, resp.ContentLength > 0)
}

View File

@ -44,49 +44,22 @@ import (
"mime/multipart" "mime/multipart"
"net" "net"
"net/http" "net/http"
"net/http/cookiejar"
"net/http/httputil" "net/http/httputil"
"net/url" "net/url"
"os" "os"
"path" "path"
"strings" "strings"
"sync"
"time" "time"
"gopkg.in/yaml.v2" "gopkg.in/yaml.v2"
) )
var defaultSetting = BeegoHTTPSettings{
UserAgent: "beegoServer",
ConnectTimeout: 60 * time.Second,
ReadWriteTimeout: 60 * time.Second,
Gzip: true,
DumpBody: true,
FilterChains: []FilterChain{mockFilter.FilterChain},
}
var defaultCookieJar http.CookieJar
var settingMutex sync.Mutex
// it will be the last filter and execute request.Do // it will be the last filter and execute request.Do
var doRequestFilter = func(ctx context.Context, req *BeegoHTTPRequest) (*http.Response, error) { var doRequestFilter = func(ctx context.Context, req *BeegoHTTPRequest) (*http.Response, error) {
return req.doRequest(ctx) return req.doRequest(ctx)
} }
// createDefaultCookie creates a global cookiejar to store cookies.
func createDefaultCookie() {
settingMutex.Lock()
defer settingMutex.Unlock()
defaultCookieJar, _ = cookiejar.New(nil)
}
// SetDefaultSetting overwrites default settings
func SetDefaultSetting(setting BeegoHTTPSettings) {
settingMutex.Lock()
defer settingMutex.Unlock()
defaultSetting = setting
}
// NewBeegoRequest returns *BeegoHttpRequest with specific method // NewBeegoRequest returns *BeegoHttpRequest with specific method
func NewBeegoRequest(rawurl, method string) *BeegoHTTPRequest { func NewBeegoRequest(rawurl, method string) *BeegoHTTPRequest {
var resp http.Response var resp http.Response
@ -137,23 +110,7 @@ func Head(url string) *BeegoHTTPRequest {
return NewBeegoRequest(url, "HEAD") return NewBeegoRequest(url, "HEAD")
} }
// BeegoHTTPSettings is the http.Client setting
type BeegoHTTPSettings struct {
ShowDebug bool
UserAgent string
ConnectTimeout time.Duration
ReadWriteTimeout time.Duration
TLSClientConfig *tls.Config
Proxy func(*http.Request) (*url.URL, error)
Transport http.RoundTripper
CheckRedirect func(req *http.Request, via []*http.Request) error
EnableCookie bool
Gzip bool
DumpBody bool
Retries int // if set to -1 means will retry forever
RetryDelay time.Duration
FilterChains []FilterChain
}
// BeegoHTTPRequest provides more useful methods than http.Request for requesting a url. // BeegoHTTPRequest provides more useful methods than http.Request for requesting a url.
type BeegoHTTPRequest struct { type BeegoHTTPRequest struct {
@ -362,6 +319,9 @@ func (b *BeegoHTTPRequest) XMLBody(obj interface{}) (*BeegoHTTPRequest, error) {
return b, err return b, err
} }
b.req.Body = ioutil.NopCloser(bytes.NewReader(byts)) b.req.Body = ioutil.NopCloser(bytes.NewReader(byts))
b.req.GetBody = func() (io.ReadCloser, error) {
return ioutil.NopCloser(bytes.NewReader(byts)), nil
}
b.req.ContentLength = int64(len(byts)) b.req.ContentLength = int64(len(byts))
b.req.Header.Set("Content-Type", "application/xml") b.req.Header.Set("Content-Type", "application/xml")
} }

View File

@ -300,3 +300,81 @@ func TestAddFilter(t *testing.T) {
r := Get("http://beego.me") r := Get("http://beego.me")
assert.Equal(t, 1, len(req.setting.FilterChains)-len(r.setting.FilterChains)) assert.Equal(t, 1, len(req.setting.FilterChains)-len(r.setting.FilterChains))
} }
func TestHead(t *testing.T) {
req := Head("http://beego.me")
assert.NotNil(t, req)
assert.Equal(t, "HEAD", req.req.Method)
}
func TestDelete(t *testing.T) {
req := Delete("http://beego.me")
assert.NotNil(t, req)
assert.Equal(t, "DELETE", req.req.Method)
}
func TestPost(t *testing.T) {
req := Post("http://beego.me")
assert.NotNil(t, req)
assert.Equal(t, "POST", req.req.Method)
}
func TestNewBeegoRequest(t *testing.T) {
req := NewBeegoRequest("http://beego.me", "GET")
assert.NotNil(t, req)
assert.Equal(t, "GET", req.req.Method)
}
func TestPut(t *testing.T) {
req := Put("http://beego.me")
assert.NotNil(t, req)
assert.Equal(t, "PUT", req.req.Method)
}
func TestBeegoHTTPRequest_Header(t *testing.T) {
req := Post("http://beego.me")
key, value := "test-header", "test-header-value"
req.Header(key, value)
assert.Equal(t, value, req.req.Header.Get(key))
}
func TestBeegoHTTPRequest_SetHost(t *testing.T) {
req := Post("http://beego.me")
host := "test-hose"
req.SetHost(host)
assert.Equal(t, host, req.req.Host)
}
func TestBeegoHTTPRequest_Param(t *testing.T) {
req := Post("http://beego.me")
key, value := "test-param", "test-param-value"
req.Param(key, value)
assert.Equal(t, value, req.params[key][0])
value1 := "test-param-value-1"
req.Param(key, value1)
assert.Equal(t, value1, req.params[key][1])
}
func TestBeegoHTTPRequest_Body(t *testing.T) {
req := Post("http://beego.me")
body := `hello, world`
req.Body([]byte(body))
assert.Equal(t, int64(len(body)), req.req.ContentLength)
assert.NotNil(t, req.req.GetBody)
}
type user struct {
Name string `xml:"name"`
}
func TestBeegoHTTPRequest_XMLBody(t *testing.T) {
req := Post("http://beego.me")
body := &user{
Name: "Tom",
}
_, err := req.XMLBody(body)
assert.True(t, req.req.ContentLength > 0)
assert.Nil(t, err)
assert.NotNil(t, req.req.GetBody)
}

View File

@ -12,17 +12,22 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
package httplib package mock
import ( import (
"context" "context"
"net/http" "net/http"
"github.com/beego/beego/v2/client/httplib"
"github.com/beego/beego/v2/core/logs" "github.com/beego/beego/v2/core/logs"
) )
const mockCtxKey = "beego-httplib-mock" const mockCtxKey = "beego-httplib-mock"
func init() {
InitMockSetting()
}
type Stub interface { type Stub interface {
Mock(cond RequestCondition, resp *http.Response, err error) Mock(cond RequestCondition, resp *http.Response, err error)
Clear() Clear()
@ -31,6 +36,10 @@ type Stub interface {
var mockFilter = &MockResponseFilter{} var mockFilter = &MockResponseFilter{}
func InitMockSetting() {
httplib.AddDefaultFilter(mockFilter.FilterChain)
}
func StartMock() Stub { func StartMock() Stub {
return mockFilter return mockFilter
} }

View File

@ -12,17 +12,19 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
package httplib package mock
import ( import (
"context" "context"
"encoding/json" "encoding/json"
"net/textproto" "net/textproto"
"regexp" "regexp"
"github.com/beego/beego/v2/client/httplib"
) )
type RequestCondition interface { type RequestCondition interface {
Match(ctx context.Context, req *BeegoHTTPRequest) bool Match(ctx context.Context, req *httplib.BeegoHTTPRequest) bool
} }
// reqCondition create condition // reqCondition create condition
@ -54,7 +56,7 @@ func NewSimpleCondition(path string, opts ...simpleConditionOption) *SimpleCondi
return sc return sc
} }
func (sc *SimpleCondition) Match(ctx context.Context, req *BeegoHTTPRequest) bool { func (sc *SimpleCondition) Match(ctx context.Context, req *httplib.BeegoHTTPRequest) bool {
res := true res := true
if len(sc.path) > 0 { if len(sc.path) > 0 {
res = sc.matchPath(ctx, req) res = sc.matchPath(ctx, req)
@ -70,12 +72,12 @@ func (sc *SimpleCondition) Match(ctx context.Context, req *BeegoHTTPRequest) boo
sc.matchBodyFields(ctx, req) sc.matchBodyFields(ctx, req)
} }
func (sc *SimpleCondition) matchPath(ctx context.Context, req *BeegoHTTPRequest) bool { func (sc *SimpleCondition) matchPath(ctx context.Context, req *httplib.BeegoHTTPRequest) bool {
path := req.GetRequest().URL.Path path := req.GetRequest().URL.Path
return path == sc.path return path == sc.path
} }
func (sc *SimpleCondition) matchPathReg(ctx context.Context, req *BeegoHTTPRequest) bool { func (sc *SimpleCondition) matchPathReg(ctx context.Context, req *httplib.BeegoHTTPRequest) bool {
path := req.GetRequest().URL.Path path := req.GetRequest().URL.Path
if b, err := regexp.Match(sc.pathReg, []byte(path)); err == nil { if b, err := regexp.Match(sc.pathReg, []byte(path)); err == nil {
return b return b
@ -83,7 +85,7 @@ func (sc *SimpleCondition) matchPathReg(ctx context.Context, req *BeegoHTTPReque
return false return false
} }
func (sc *SimpleCondition) matchQuery(ctx context.Context, req *BeegoHTTPRequest) bool { func (sc *SimpleCondition) matchQuery(ctx context.Context, req *httplib.BeegoHTTPRequest) bool {
qs := req.GetRequest().URL.Query() qs := req.GetRequest().URL.Query()
for k, v := range sc.query { for k, v := range sc.query {
if uv, ok := qs[k]; !ok || uv[0] != v { if uv, ok := qs[k]; !ok || uv[0] != v {
@ -93,7 +95,7 @@ func (sc *SimpleCondition) matchQuery(ctx context.Context, req *BeegoHTTPRequest
return true return true
} }
func (sc *SimpleCondition) matchHeader(ctx context.Context, req *BeegoHTTPRequest) bool { func (sc *SimpleCondition) matchHeader(ctx context.Context, req *httplib.BeegoHTTPRequest) bool {
headers := req.GetRequest().Header headers := req.GetRequest().Header
for k, v := range sc.header { for k, v := range sc.header {
if uv, ok := headers[k]; !ok || uv[0] != v { if uv, ok := headers[k]; !ok || uv[0] != v {
@ -103,7 +105,7 @@ func (sc *SimpleCondition) matchHeader(ctx context.Context, req *BeegoHTTPReques
return true return true
} }
func (sc *SimpleCondition) matchBodyFields(ctx context.Context, req *BeegoHTTPRequest) bool { func (sc *SimpleCondition) matchBodyFields(ctx context.Context, req *httplib.BeegoHTTPRequest) bool {
if len(sc.body) == 0 { if len(sc.body) == 0 {
return true return true
} }
@ -135,7 +137,7 @@ func (sc *SimpleCondition) matchBodyFields(ctx context.Context, req *BeegoHTTPRe
return true return true
} }
func (sc *SimpleCondition) matchMethod(ctx context.Context, req *BeegoHTTPRequest) bool { func (sc *SimpleCondition) matchMethod(ctx context.Context, req *httplib.BeegoHTTPRequest) bool {
if len(sc.method) > 0 { if len(sc.method) > 0 {
return sc.method == req.GetRequest().Method return sc.method == req.GetRequest().Method
} }

View File

@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
package httplib package mock
import ( import (
"context" "context"
@ -20,6 +20,7 @@ import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/beego/beego/v2/client/httplib"
) )
func init() { func init() {
@ -28,37 +29,37 @@ func init() {
func TestSimpleCondition_MatchPath(t *testing.T) { func TestSimpleCondition_MatchPath(t *testing.T) {
sc := NewSimpleCondition("/abc/s") sc := NewSimpleCondition("/abc/s")
res := sc.Match(context.Background(), Get("http://localhost:8080/abc/s")) res := sc.Match(context.Background(), httplib.Get("http://localhost:8080/abc/s"))
assert.True(t, res) assert.True(t, res)
} }
func TestSimpleCondition_MatchQuery(t *testing.T) { func TestSimpleCondition_MatchQuery(t *testing.T) {
k, v := "my-key", "my-value" k, v := "my-key", "my-value"
sc := NewSimpleCondition("/abc/s") sc := NewSimpleCondition("/abc/s")
res := sc.Match(context.Background(), Get("http://localhost:8080/abc/s?my-key=my-value")) res := sc.Match(context.Background(), httplib.Get("http://localhost:8080/abc/s?my-key=my-value"))
assert.True(t, res) assert.True(t, res)
sc = NewSimpleCondition("/abc/s", WithQuery(k, v)) sc = NewSimpleCondition("/abc/s", WithQuery(k, v))
res = sc.Match(context.Background(), Get("http://localhost:8080/abc/s?my-key=my-value")) res = sc.Match(context.Background(), httplib.Get("http://localhost:8080/abc/s?my-key=my-value"))
assert.True(t, res) assert.True(t, res)
res = sc.Match(context.Background(), Get("http://localhost:8080/abc/s?my-key=my-valuesss")) res = sc.Match(context.Background(), httplib.Get("http://localhost:8080/abc/s?my-key=my-valuesss"))
assert.False(t, res) assert.False(t, res)
res = sc.Match(context.Background(), Get("http://localhost:8080/abc/s?my-key-a=my-value")) res = sc.Match(context.Background(), httplib.Get("http://localhost:8080/abc/s?my-key-a=my-value"))
assert.False(t, res) assert.False(t, res)
res = sc.Match(context.Background(), Get("http://localhost:8080/abc/s?my-key=my-value&abc=hello")) res = sc.Match(context.Background(), httplib.Get("http://localhost:8080/abc/s?my-key=my-value&abc=hello"))
assert.True(t, res) assert.True(t, res)
} }
func TestSimpleCondition_MatchHeader(t *testing.T) { func TestSimpleCondition_MatchHeader(t *testing.T) {
k, v := "my-header", "my-header-value" k, v := "my-header", "my-header-value"
sc := NewSimpleCondition("/abc/s") sc := NewSimpleCondition("/abc/s")
req := Get("http://localhost:8080/abc/s") req := httplib.Get("http://localhost:8080/abc/s")
assert.True(t, sc.Match(context.Background(), req)) assert.True(t, sc.Match(context.Background(), req))
req = Get("http://localhost:8080/abc/s") req = httplib.Get("http://localhost:8080/abc/s")
req.Header(k, v) req.Header(k, v)
assert.True(t, sc.Match(context.Background(), req)) assert.True(t, sc.Match(context.Background(), req))
@ -73,7 +74,7 @@ func TestSimpleCondition_MatchHeader(t *testing.T) {
func TestSimpleCondition_MatchBodyField(t *testing.T) { func TestSimpleCondition_MatchBodyField(t *testing.T) {
sc := NewSimpleCondition("/abc/s") sc := NewSimpleCondition("/abc/s")
req := Post("http://localhost:8080/abc/s") req := httplib.Post("http://localhost:8080/abc/s")
assert.True(t, sc.Match(context.Background(), req)) assert.True(t, sc.Match(context.Background(), req))
@ -102,7 +103,7 @@ func TestSimpleCondition_MatchBodyField(t *testing.T) {
func TestSimpleCondition_Match(t *testing.T) { func TestSimpleCondition_Match(t *testing.T) {
sc := NewSimpleCondition("/abc/s") sc := NewSimpleCondition("/abc/s")
req := Post("http://localhost:8080/abc/s") req := httplib.Post("http://localhost:8080/abc/s")
assert.True(t, sc.Match(context.Background(), req)) assert.True(t, sc.Match(context.Background(), req))
@ -115,9 +116,9 @@ func TestSimpleCondition_Match(t *testing.T) {
func TestSimpleCondition_MatchPathReg(t *testing.T) { func TestSimpleCondition_MatchPathReg(t *testing.T) {
sc := NewSimpleCondition("", WithPathReg(`\/abc\/.*`)) sc := NewSimpleCondition("", WithPathReg(`\/abc\/.*`))
req := Post("http://localhost:8080/abc/s") req := httplib.Post("http://localhost:8080/abc/s")
assert.True(t, sc.Match(context.Background(), req)) assert.True(t, sc.Match(context.Background(), req))
req = Post("http://localhost:8080/abcd/s") req = httplib.Post("http://localhost:8080/abcd/s")
assert.False(t, sc.Match(context.Background(), req)) assert.False(t, sc.Match(context.Background(), req))
} }

View File

@ -12,12 +12,13 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
package httplib package mock
import ( import (
"context" "context"
"fmt"
"net/http" "net/http"
"github.com/beego/beego/v2/client/httplib"
) )
// MockResponse will return mock response if find any suitable mock data // MockResponse will return mock response if find any suitable mock data
@ -32,13 +33,10 @@ func NewMockResponseFilter() *MockResponseFilter {
} }
} }
func (m *MockResponseFilter) FilterChain(next Filter) Filter { func (m *MockResponseFilter) FilterChain(next httplib.Filter) httplib.Filter {
return func(ctx context.Context, req *BeegoHTTPRequest) (*http.Response, error) { return func(ctx context.Context, req *httplib.BeegoHTTPRequest) (*http.Response, error) {
ms := mockFromCtx(ctx) ms := mockFromCtx(ctx)
ms = append(ms, m.ms...) ms = append(ms, m.ms...)
fmt.Printf("url: %s, mock: %d \n", req.url, len(ms))
for _, mock := range ms { for _, mock := range ms {
if mock.cond.Match(ctx, req) { if mock.cond.Match(ctx, req) {
return mock.resp, mock.err return mock.resp, mock.err

View File

@ -12,20 +12,22 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
package httplib package mock
import ( import (
"errors" "errors"
"testing" "testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/beego/beego/v2/client/httplib"
) )
func TestMockResponseFilter_FilterChain(t *testing.T) { func TestMockResponseFilter_FilterChain(t *testing.T) {
req := Get("http://localhost:8080/abc/s") req := httplib.Get("http://localhost:8080/abc/s")
ft := NewMockResponseFilter() ft := NewMockResponseFilter()
expectedResp := NewHttpResponseWithJsonBody(`{}`) expectedResp := httplib.NewHttpResponseWithJsonBody(`{}`)
expectedErr := errors.New("expected error") expectedErr := errors.New("expected error")
ft.Mock(NewSimpleCondition("/abc/s"), expectedResp, expectedErr) ft.Mock(NewSimpleCondition("/abc/s"), expectedResp, expectedErr)
@ -35,16 +37,16 @@ func TestMockResponseFilter_FilterChain(t *testing.T) {
assert.Equal(t, expectedErr, err) assert.Equal(t, expectedErr, err)
assert.Equal(t, expectedResp, resp) assert.Equal(t, expectedResp, resp)
req = Get("http://localhost:8080/abcd/s") req = httplib.Get("http://localhost:8080/abcd/s")
req.AddFilters(ft.FilterChain) req.AddFilters(ft.FilterChain)
resp, err = req.DoRequest() resp, err = req.DoRequest()
assert.NotEqual(t, expectedErr, err) assert.NotEqual(t, expectedErr, err)
assert.NotEqual(t, expectedResp, resp) assert.NotEqual(t, expectedResp, resp)
req = Get("http://localhost:8080/abc/s") req = httplib.Get("http://localhost:8080/abc/s")
req.AddFilters(ft.FilterChain) req.AddFilters(ft.FilterChain)
expectedResp1 := NewHttpResponseWithJsonBody(map[string]string{}) expectedResp1 := httplib.NewHttpResponseWithJsonBody(map[string]string{})
expectedErr1 := errors.New("expected error") expectedErr1 := errors.New("expected error")
ft.Mock(NewSimpleCondition("/abc/abs/bbc"), expectedResp1, expectedErr1) ft.Mock(NewSimpleCondition("/abc/abs/bbc"), expectedResp1, expectedErr1)
@ -52,7 +54,7 @@ func TestMockResponseFilter_FilterChain(t *testing.T) {
assert.Equal(t, expectedErr, err) assert.Equal(t, expectedErr, err)
assert.Equal(t, expectedResp, resp) assert.Equal(t, expectedResp, resp)
req = Get("http://localhost:8080/abc/abs/bbc") req = httplib.Get("http://localhost:8080/abc/abs/bbc")
req.AddFilters(ft.FilterChain) req.AddFilters(ft.FilterChain)
ft.Mock(NewSimpleCondition("/abc/abs/bbc"), expectedResp1, expectedErr1) ft.Mock(NewSimpleCondition("/abc/abs/bbc"), expectedResp1, expectedErr1)
resp, err = req.DoRequest() resp, err = req.DoRequest()

View File

@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
package httplib package mock
import ( import (
"context" "context"
@ -21,16 +21,18 @@ import (
"testing" "testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/beego/beego/v2/client/httplib"
) )
func TestStartMock(t *testing.T) { func TestStartMock(t *testing.T) {
defaultSetting.FilterChains = []FilterChain{mockFilter.FilterChain} // httplib.defaultSetting.FilterChains = []httplib.FilterChain{mockFilter.FilterChain}
stub := StartMock() stub := StartMock()
// defer stub.Clear() // defer stub.Clear()
expectedResp := NewHttpResponseWithJsonBody([]byte(`{}`)) expectedResp := httplib.NewHttpResponseWithJsonBody([]byte(`{}`))
expectedErr := errors.New("expected err") expectedErr := errors.New("expected err")
stub.Mock(NewSimpleCondition("/abc"), expectedResp, expectedErr) stub.Mock(NewSimpleCondition("/abc"), expectedResp, expectedErr)
@ -45,14 +47,14 @@ func TestStartMock(t *testing.T) {
// TestStartMock_Isolation Test StartMock that // TestStartMock_Isolation Test StartMock that
// mock only work for this request // mock only work for this request
func TestStartMock_Isolation(t *testing.T) { func TestStartMock_Isolation(t *testing.T) {
defaultSetting.FilterChains = []FilterChain{mockFilter.FilterChain} // httplib.defaultSetting.FilterChains = []httplib.FilterChain{mockFilter.FilterChain}
// setup global stub // setup global stub
stub := StartMock() stub := StartMock()
globalMockResp := NewHttpResponseWithJsonBody([]byte(`{}`)) globalMockResp := httplib.NewHttpResponseWithJsonBody([]byte(`{}`))
globalMockErr := errors.New("expected err") globalMockErr := errors.New("expected err")
stub.Mock(NewSimpleCondition("/abc"), globalMockResp, globalMockErr) stub.Mock(NewSimpleCondition("/abc"), globalMockResp, globalMockErr)
expectedResp := NewHttpResponseWithJsonBody(struct { expectedResp := httplib.NewHttpResponseWithJsonBody(struct {
A string `json:"a"` A string `json:"a"`
}{ }{
A: "aaa", A: "aaa",
@ -67,9 +69,9 @@ func TestStartMock_Isolation(t *testing.T) {
} }
func OriginnalCodeUsingHttplibPassCtx(ctx context.Context) (*http.Response, error) { func OriginnalCodeUsingHttplibPassCtx(ctx context.Context) (*http.Response, error) {
return Get("http://localhost:7777/abc").DoRequestWithCtx(ctx) return httplib.Get("http://localhost:7777/abc").DoRequestWithCtx(ctx)
} }
func OriginalCodeUsingHttplib() (*http.Response, error){ func OriginalCodeUsingHttplib() (*http.Response, error){
return Get("http://localhost:7777/abc").DoRequest() return httplib.Get("http://localhost:7777/abc").DoRequest()
} }

81
client/httplib/setting.go Normal file
View File

@ -0,0 +1,81 @@
// Copyright 2020 beego
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package httplib
import (
"crypto/tls"
"net/http"
"net/http/cookiejar"
"net/url"
"sync"
"time"
)
// BeegoHTTPSettings is the http.Client setting
type BeegoHTTPSettings struct {
ShowDebug bool
UserAgent string
ConnectTimeout time.Duration
ReadWriteTimeout time.Duration
TLSClientConfig *tls.Config
Proxy func(*http.Request) (*url.URL, error)
Transport http.RoundTripper
CheckRedirect func(req *http.Request, via []*http.Request) error
EnableCookie bool
Gzip bool
DumpBody bool
Retries int // if set to -1 means will retry forever
RetryDelay time.Duration
FilterChains []FilterChain
}
// createDefaultCookie creates a global cookiejar to store cookies.
func createDefaultCookie() {
settingMutex.Lock()
defer settingMutex.Unlock()
defaultCookieJar, _ = cookiejar.New(nil)
}
// SetDefaultSetting overwrites default settings
// Keep in mind that when you invoke the SetDefaultSetting
// some methods invoked before SetDefaultSetting
func SetDefaultSetting(setting BeegoHTTPSettings) {
settingMutex.Lock()
defer settingMutex.Unlock()
defaultSetting = setting
}
var defaultSetting = BeegoHTTPSettings{
UserAgent: "beegoServer",
ConnectTimeout: 60 * time.Second,
ReadWriteTimeout: 60 * time.Second,
Gzip: true,
DumpBody: true,
FilterChains: make([]FilterChain, 0, 4),
}
var defaultCookieJar http.CookieJar
var settingMutex sync.Mutex
// AddDefaultFilter add a new filter into defaultSetting
// Be careful about using this method if you invoke SetDefaultSetting somewhere
func AddDefaultFilter(fc FilterChain) {
settingMutex.Lock()
defer settingMutex.Unlock()
if defaultSetting.FilterChains == nil {
defaultSetting.FilterChains = make([]FilterChain, 0, 4)
}
defaultSetting.FilterChains = append(defaultSetting.FilterChains, fc)
}