Skip to content

Commit 7a8a931

Browse files
authored
Merge pull request #58 from dyweb/requests/default
[requests] Use new default transport and http client
2 parents 7360581 + 3bcf758 commit 7a8a931

File tree

10 files changed

+118
-57
lines changed

10 files changed

+118
-57
lines changed

noodle/fs_embed_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import (
88
)
99

1010
func TestGenerateEmbed(t *testing.T) {
11+
t.Skip("modification time result in different binary data")
12+
1113
b, err := GenerateEmbed("_examples/embed/assets")
1214
if err != nil {
1315
t.Fatal(err)

requests/README.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,14 @@ Originally from [xephon-b](https://github.com/xephonhq/xephon-b)
66

77
## Usage
88

9-
TODO: it is mainly used for building config for http client to use socks5 proxy
9+
TODO:
10+
11+
- it was mainly used for building config for http client to use socks5 proxy
12+
- [ ] https://github.com/hashicorp/go-getter like features
1013

1114
## Changelog
1215

16+
- use same config as `DefaultTransport` in `net/http`
1317
- add client struct and default client which wraps `http.Client`
1418
- support socks5 proxy https://github.com/dyweb/gommon/issues/18
1519
- rename `GetJSON` to get `GetJSONStringMap`, this should break old Xephon-B code, which is now in tsdb-proxy

requests/auth.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@ import (
88
"github.com/pkg/errors"
99
)
1010

11-
// TODO: it is already in net/http https://golang.org/pkg/net/http/#Request.BasicAuth
12-
11+
// NOTE: net/http already implemented it https://golang.org/pkg/net/http/#Request.BasicAuth
1312
const AuthorizationHeader = "Authorization"
1413

1514
func GenerateBasicAuth(username string, password string) string {

requests/builder.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import (
99

1010
// TODO: might switch to functional options https://dave.cheney.net/2014/10/17/functional-options-for-friendly-apis
1111
// TODO: http proxy? might just use environment variable? https://stackoverflow.com/questions/14661511/setting-up-proxy-for-http-client
12-
// TransportBuilder is the initial builder, its method return a new copy for chaining and keep itself unchanged
12+
// TransportBuilder is the initial builder, its method use value receiver and return a new copy for chaining and keep itself unchanged
1313
var TransportBuilder transportBuilder
1414

1515
type transportBuilder struct {
@@ -40,7 +40,7 @@ func (b transportBuilder) UseSocks5(host string, username string, password strin
4040
}
4141

4242
func (b transportBuilder) Build() (*http.Transport, error) {
43-
transport := &http.Transport{}
43+
transport := NewDefaultTransport()
4444
if b.skipKeyVerify {
4545
transport.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
4646
}

requests/default.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package requests
2+
3+
import (
4+
"net"
5+
"net/http"
6+
"time"
7+
)
8+
9+
// Default Transport Client that is same as https://golang.org/src/net/http/transport.go
10+
// It's similar to https://github.com/hashicorp/go-cleanhttp
11+
12+
// NewDefaultTransport is copied from net/http/transport.go
13+
func NewDefaultTransport() *http.Transport {
14+
return &http.Transport{
15+
Proxy: http.ProxyFromEnvironment,
16+
DialContext: (&net.Dialer{
17+
Timeout: 30 * time.Second,
18+
KeepAlive: 30 * time.Second,
19+
DualStack: true,
20+
}).DialContext,
21+
MaxIdleConns: 100,
22+
IdleConnTimeout: 90 * time.Second,
23+
TLSHandshakeTimeout: 10 * time.Second,
24+
ExpectContinueTimeout: 1 * time.Second,
25+
}
26+
}
27+
28+
// NewDefaultClient returns a client using NewDefaultTransport
29+
func NewDefaultClient() *http.Client {
30+
return &http.Client{
31+
Transport: NewDefaultTransport(),
32+
}
33+
}

requests/doc.go

Lines changed: 0 additions & 2 deletions
This file was deleted.

requests/pkg.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1+
// Package requests is a pythonic HTTP library for Gopher
12
package requests

requests/requests.go

Lines changed: 40 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -3,52 +3,46 @@
33
package requests
44

55
import (
6+
"bytes"
7+
"io"
68
"io/ioutil"
79
"net/http"
10+
"strings"
811

9-
"bytes"
1012
"github.com/pkg/errors"
11-
"io"
12-
"strings"
1313
)
1414

1515
const (
1616
ShadowSocksLocal = "127.0.0.1:1080"
1717
ContentJSON = "application/json"
1818
)
1919

20-
var (
21-
defaultClient = &Client{http: &http.Client{Transport: &http.Transport{}}}
22-
)
20+
var defaultClient = &Client{h: NewDefaultClient(), content: ContentJSON}
2321

2422
type Client struct {
25-
http *http.Client
23+
h *http.Client
24+
content string
2625
}
2726

28-
func NewClient(options ...func(h *http.Client)) (*Client, error) {
29-
c := &Client{http: &http.Client{Transport: &http.Transport{}}}
27+
func NewClient(options ...func(h *http.Client)) *Client {
28+
c := &Client{h: NewDefaultClient(), content: ContentJSON}
3029
for _, option := range options {
31-
option(c.http)
30+
option(c.h)
3231
}
33-
return c, nil
32+
return c
3433
}
3534

36-
func makeRequest(method string, url string, body io.Reader) (*Response, error) {
37-
return defaultClient.makeRequest(method, url, body)
38-
}
39-
40-
func (client *Client) makeRequest(method string, url string, body io.Reader) (*Response, error) {
41-
if client.http == nil {
35+
func (c *Client) makeRequest(method string, url string, body io.Reader) (*Response, error) {
36+
if c.h == nil {
4237
return nil, errors.New("http client is not initialized")
4338
}
4439
var res *http.Response
4540
var err error
4641
switch method {
4742
case http.MethodGet:
48-
res, err = client.http.Get(url)
43+
res, err = c.h.Get(url)
4944
case http.MethodPost:
50-
// TODO: we only support JSON for now
51-
res, err = client.http.Post(url, ContentJSON, body)
45+
res, err = c.h.Post(url, c.content, body)
5246
}
5347
response := &Response{}
5448
if err != nil {
@@ -60,42 +54,50 @@ func (client *Client) makeRequest(method string, url string, body io.Reader) (*R
6054
return response, errors.Wrap(err, "error reading body")
6155
}
6256
response.Res = res
63-
response.Text = resContent
57+
response.StatusCode = res.StatusCode
58+
response.Data = resContent
6459
return response, nil
6560
}
6661

67-
func Get(url string) (*Response, error) {
68-
return makeRequest(http.MethodGet, url, nil)
62+
// TODO: this defaultish wrapping methods should be generated by gommon generator
63+
func Post(url string, data io.Reader) (*Response, error) {
64+
return defaultClient.Post(url, data)
6965
}
7066

71-
func (client *Client) Get(url string) (*Response, error) {
72-
return client.makeRequest(http.MethodGet, url, nil)
67+
func (c *Client) Post(url string, data io.Reader) (*Response, error) {
68+
return c.makeRequest(http.MethodPost, url, data)
7369
}
7470

75-
// TODO: accept io.reader
71+
func PostString(url string, data string) (*Response, error) {
72+
return defaultClient.PostString(url, data)
73+
}
7674

77-
func PostJSONString(url string, data string) (*Response, error) {
78-
return makeRequest(http.MethodPost, url, ioutil.NopCloser(strings.NewReader(data)))
75+
func (c *Client) PostString(url string, data string) (*Response, error) {
76+
return c.makeRequest(http.MethodPost, url, ioutil.NopCloser(strings.NewReader(data)))
7977
}
8078

81-
func (client *Client) PostJSONString(url string, data string) (*Response, error) {
82-
return client.makeRequest(http.MethodPost, url, ioutil.NopCloser(strings.NewReader(data)))
79+
func PostBytes(url string, data []byte) (*Response, error) {
80+
return defaultClient.PostBytes(url, data)
8381
}
8482

85-
func PostJSONBytes(url string, data []byte) (*Response, error) {
86-
return makeRequest(http.MethodPost, url, ioutil.NopCloser(bytes.NewReader(data)))
83+
func (c *Client) PostBytes(url string, data []byte) (*Response, error) {
84+
return c.makeRequest(http.MethodPost, url, ioutil.NopCloser(bytes.NewReader(data)))
85+
}
86+
87+
func Get(url string) (*Response, error) {
88+
return defaultClient.Get(url)
8789
}
8890

89-
func (client *Client) PostJSONBytes(url string, data []byte) (*Response, error) {
90-
return client.makeRequest(http.MethodPost, url, ioutil.NopCloser(bytes.NewReader(data)))
91+
func (c *Client) Get(url string) (*Response, error) {
92+
return c.makeRequest(http.MethodGet, url, nil)
9193
}
9294

9395
func GetJSON(url string, data interface{}) error {
9496
return defaultClient.GetJSON(url, data)
9597
}
9698

97-
func (client *Client) GetJSON(url string, data interface{}) error {
98-
res, err := client.Get(url)
99+
func (c *Client) GetJSON(url string, data interface{}) error {
100+
res, err := c.Get(url)
99101
if err != nil {
100102
return errors.Wrap(err, "error getting response")
101103
}
@@ -110,9 +112,9 @@ func GetJSONStringMap(url string) (map[string]string, error) {
110112
return defaultClient.GetJSONStringMap(url)
111113
}
112114

113-
func (client *Client) GetJSONStringMap(url string) (map[string]string, error) {
115+
func (c *Client) GetJSONStringMap(url string) (map[string]string, error) {
114116
var data map[string]string
115-
res, err := client.Get(url)
117+
res, err := c.Get(url)
116118
if err != nil {
117119
return data, errors.Wrap(err, "error getting response")
118120
}

requests/requests_test.go

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,12 @@ package requests
22

33
import (
44
"fmt"
5-
asst "github.com/stretchr/testify/assert"
65
"io/ioutil"
76
"net/http"
87
"net/http/httptest"
98
"testing"
9+
10+
asst "github.com/stretchr/testify/assert"
1011
)
1112

1213
func TestRequestsE2E(t *testing.T) {
@@ -37,37 +38,59 @@ func TestRequestsE2E(t *testing.T) {
3738
versionURL := testServer.URL + "/version"
3839
echoURL := testServer.URL + "/echo"
3940

41+
c := NewClient()
42+
t.Run("c.Get", func(t *testing.T) {
43+
assert := asst.New(t)
44+
res, err := c.Get(versionURL)
45+
assert.Nil(err)
46+
assert.Equal(http.StatusOK, res.Res.StatusCode)
47+
})
48+
4049
t.Run("Get", func(t *testing.T) {
4150
assert := asst.New(t)
4251
res, err := Get(versionURL)
4352
assert.Nil(err)
4453
assert.Equal(http.StatusOK, res.Res.StatusCode)
4554
})
4655

56+
t.Run("c.GetJSONStringMap", func(t *testing.T) {
57+
assert := asst.New(t)
58+
data, err := c.GetJSONStringMap(versionURL)
59+
assert.Nil(err)
60+
assert.Equal(version, data["version"])
61+
})
62+
4763
t.Run("GetJSONStringMap", func(t *testing.T) {
4864
assert := asst.New(t)
4965
data, err := GetJSONStringMap(versionURL)
5066
assert.Nil(err)
5167
assert.Equal(version, data["version"])
5268
})
5369

54-
t.Run("PostJSONString", func(t *testing.T) {
70+
t.Run("c.PostString", func(t *testing.T) {
5571
assert := asst.New(t)
5672
payload := fmt.Sprintf("{\"version\": \"%s\"}", version)
57-
res, err := PostJSONString(echoURL, payload)
73+
res, err := c.PostString(echoURL, payload)
5874
assert.Nil(err)
59-
assert.Equal(payload, string(res.Text))
75+
assert.Equal(payload, string(res.Data))
76+
})
77+
78+
t.Run("c.PostString", func(t *testing.T) {
79+
assert := asst.New(t)
80+
payload := fmt.Sprintf("{\"version\": \"%s\"}", version)
81+
res, err := PostString(echoURL, payload)
82+
assert.Nil(err)
83+
assert.Equal(payload, string(res.Data))
6084
})
6185
}
6286

6387
func TestNewClient(t *testing.T) {
6488
assert := asst.New(t)
6589
tr, err := TransportBuilder.UseShadowSocks().Build()
6690
assert.Nil(err)
67-
c, err := NewClient(func(h *http.Client) {
91+
c := NewClient(func(h *http.Client) {
6892
h.Transport = tr
6993
})
70-
assert.Nil(err)
7194
assert.NotNil(c)
7295
// uncomment the following if you have local socks 5 proxy running
7396
//_, err = c.Get("https://google.com")

requests/response.go

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,28 +2,27 @@ package requests
22

33
import (
44
"encoding/json"
5-
65
"net/http"
76

87
"github.com/pkg/errors"
98
)
109

1110
type Response struct {
12-
Res *http.Response
13-
Text []byte
11+
Res *http.Response
12+
StatusCode int
13+
Data []byte
1414
}
1515

1616
func (res *Response) JSON(data interface{}) error {
17-
// TODO: may change to decoder
18-
if err := json.Unmarshal(res.Text, &data); err != nil {
17+
if err := json.Unmarshal(res.Data, &data); err != nil {
1918
return errors.Wrap(err, "error unmarshal json using map[string]string")
2019
}
2120
return nil
2221
}
2322

2423
func (res *Response) JSONStringMap() (map[string]string, error) {
2524
var data map[string]string
26-
if err := json.Unmarshal(res.Text, &data); err != nil {
25+
if err := json.Unmarshal(res.Data, &data); err != nil {
2726
return data, errors.Wrap(err, "error unmarshal json using map[string]string")
2827
}
2928
return data, nil

0 commit comments

Comments
 (0)