This repository has been archived by the owner on Jun 2, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 11
/
client.go
282 lines (251 loc) · 6.96 KB
/
client.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
package wego
import (
"context"
"crypto/tls"
"github.com/godcong/wego/util"
"golang.org/x/xerrors"
"io"
"io/ioutil"
"math"
"net"
"net/http"
"time"
)
const defaultCa = `
-----BEGIN CERTIFICATE-----
MIIDIDCCAomgAwIBAgIENd70zzANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJV
UzEQMA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2Vy
dGlmaWNhdGUgQXV0aG9yaXR5MB4XDTk4MDgyMjE2NDE1MVoXDTE4MDgyMjE2NDE1
MVowTjELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0VxdWlmYXgxLTArBgNVBAsTJEVx
dWlmYXggU2VjdXJlIENlcnRpZmljYXRlIEF1dGhvcml0eTCBnzANBgkqhkiG9w0B
AQEFAAOBjQAwgYkCgYEAwV2xWGcIYu6gmi0fCG2RFGiYCh7+2gRvE4RiIcPRfM6f
BeC4AfBONOziipUEZKzxa1NfBbPLZ4C/QgKO/t0BCezhABRP/PvwDN1Dulsr4R+A
cJkVV5MW8Q+XarfCaCMczE1ZMKxRHjuvK9buY0V7xdlfUNLjUA86iOe/FP3gx7kC
AwEAAaOCAQkwggEFMHAGA1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEQ
MA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2VydGlm
aWNhdGUgQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMBoGA1UdEAQTMBGBDzIwMTgw
ODIyMTY0MTUxWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUSOZo+SvSspXXR9gj
IBBPM5iQn9QwHQYDVR0OBBYEFEjmaPkr0rKV10fYIyAQTzOYkJ/UMAwGA1UdEwQF
MAMBAf8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUA
A4GBAFjOKer89961zgK5F7WF0bnj4JXMJTENAKaSbn+2kmOeUJXRmm/kEd5jhW6Y
7qj/WsjTVbJmcVfewCHrPSqnI0kBBIZCe/zuf6IWUrVnZ9NA2zsmWLIodz2uFHdh
1voqZiegDfqnc1zqcPGUIWVEX/r87yloqaKHee9570+sB3c4
-----END CERTIFICATE-----`
// RequestContent ...
type RequestContent struct {
Method string
URL string
Query util.Map
Body *RequestBody
}
// Client ...
type Client struct {
context context.Context
TLSConfig *tls.Config
BodyType BodyType
//useSafe bool
//safeCert *SafeCertProperty
accessToken *AccessToken
//timeout int64
//keepAlive int64
}
// UseSafe ...
func (obj *Client) UseSafe() bool {
return obj.TLSConfig != nil
}
// Context ...
func (obj *Client) Context() context.Context {
if obj.context == nil {
i, _ := Context()
return i
}
return obj.context
}
// NewClient ...
func NewClient(options ...ClientOption) *Client {
client := &Client{
BodyType: BodyTypeXML,
}
client.parse(options...)
return client
}
func (obj *Client) parse(options ...ClientOption) {
if options == nil {
return
}
for _, o := range options {
o(obj)
}
}
// GetToken ...
func (obj *Client) GetToken() (util.Map, error) {
if obj.accessToken != nil {
return obj.accessToken.KeyMap(), nil
}
return nil, xerrors.New("nil accessToken")
}
// MustToken ...
func (obj *Client) MustToken() (token util.Map) {
token, err := obj.GetToken()
if err != nil {
panic(err)
}
return token
}
// Post ...
func (obj *Client) Post(ctx context.Context, url string, query util.Map, body interface{}) Responder {
log.Debug("post ", url, body)
return obj.do(ctx, &RequestContent{
Method: POST,
URL: url,
Query: util.CombineMaps(query, obj.MustToken()),
Body: buildBody(body, obj.BodyType),
})
}
// Get ...
func (obj *Client) Get(ctx context.Context, url string, query util.Map) Responder {
log.Debug("get ", url)
return obj.do(ctx, &RequestContent{
Method: POST,
URL: url,
Query: util.CombineMaps(query, obj.MustToken()),
Body: buildBody(nil, obj.BodyType),
})
}
// HTTPClient ...
func (obj *Client) HTTPClient() (*http.Client, error) {
return buildHTTPClient(obj, obj.UseSafe())
}
// do ...
func (obj *Client) do(ctx context.Context, content *RequestContent) Responder {
client, e := obj.HTTPClient()
if e != nil {
return ErrResponder(xerrors.Errorf("client build err:%+v", e))
}
request, e := content.BuildRequest()
if e != nil {
return ErrResponder(xerrors.Errorf("request build err:%+v", e))
}
response, e := client.Do(request.WithContext(ctx))
if e != nil {
return ErrResponder(xerrors.Errorf("response get err:%+v", e))
}
return BuildResponder(response)
}
// PostForm post form request
func PostForm(url string, query util.Map, form interface{}) Responder {
log.Debug("post form:", url, query, form)
client := &Client{
BodyType: BodyTypeForm,
}
return client.Post(context.Background(), url, query, form)
}
// PostJSON json post请求
func PostJSON(url string, query util.Map, json interface{}) Responder {
log.Debug("post json:", url, query, json)
client := &Client{
BodyType: BodyTypeJSON,
}
return client.Post(context.Background(), url, query, json)
}
// PostXML xml post请求
func PostXML(url string, query util.Map, xml interface{}) Responder {
log.Debug("post xml:", url, query, xml)
client := &Client{
BodyType: BodyTypeXML,
}
return client.Post(context.Background(), url, query, xml)
}
// Upload upload请求
func Upload(url string, query, multi util.Map) Responder {
client := &Client{
BodyType: BodyTypeMultipart,
}
return client.Post(context.Background(), url, query, multi)
}
// Get get请求
func Get(url string, query util.Map) Responder {
log.Println("get request:", url, query)
client := NewClient()
return client.Get(context.Background(), url, query)
}
// Context ...
func Context() (context.Context, context.CancelFunc) {
return context.WithTimeout(context.Background(), 30*time.Second)
}
func buildTransport(client *Client) (*http.Transport, error) {
return &http.Transport{
Proxy: nil,
DialContext: (&net.Dialer{
//Timeout: client.TimeOut(),
//KeepAlive: client.KeepAlive(),
}).DialContext,
//Dial: nil,
//DialTLS: nil,
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
},
//TLSHandshakeTimeout: 0,
//DisableKeepAlives: false,
//DisableCompression: false,
//MaxIdleConns: 0,
//MaxIdleConnsPerHost: 0,
//MaxConnsPerHost: 0,
//IdleConnTimeout: 0,
//ResponseHeaderTimeout: 0,
//ExpectContinueTimeout: 0,
//TLSNextProto: nil,
//ProxyConnectHeader: nil,
//MaxResponseHeaderBytes: 0,
}, nil
}
func buildSafeTransport(client *Client) (*http.Transport, error) {
return &http.Transport{
DialContext: (&net.Dialer{
//Timeout: client.TimeOut(),
//KeepAlive: client.KeepAlive(),
//DualStack: true,
}).DialContext,
TLSClientConfig: client.TLSConfig,
Proxy: nil,
//TLSHandshakeTimeout: 10 * time.Second,
//ResponseHeaderTimeout: 10 * time.Second,
//ExpectContinueTimeout: 1 * time.Second,
}, nil
}
func buildHTTPClient(client *Client, isSafe bool) (cli *http.Client, e error) {
cli = new(http.Client)
//判断能否创建safe client
fun := buildTransport
if isSafe {
fun = buildSafeTransport
}
cli.Transport, e = fun(client)
return
}
// BodyReader ...
type BodyReader interface {
ToMap() util.Map
Bytes() []byte
Error() error
Unmarshal(v interface{}) error
Result() (util.Map, error)
}
/*readBody get response data */
func readBody(r io.ReadCloser) ([]byte, error) {
return ioutil.ReadAll(io.LimitReader(r, math.MaxUint32))
}
// BuildRequest ...
func (c *RequestContent) BuildRequest() (*http.Request, error) {
if c.Body == nil {
return http.NewRequest(c.Method, c.URLQuery(), nil)
}
return c.Body.RequestBuilder(c.Method, c.URLQuery(), c.Body.BodyInstance)
}
// URLQuery ...
func (c *RequestContent) URLQuery() string {
if c.Query == nil {
return c.URL
}
return c.URL + "?" + c.Query.URLEncode()
}