-
Notifications
You must be signed in to change notification settings - Fork 1
/
beclient_public.go
341 lines (317 loc) · 11.5 KB
/
beclient_public.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
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
package beclient
import (
"errors"
"fmt"
"net/http"
"net/url"
"path/filepath"
"strings"
"time"
)
// New 创建一个基础客户端
// @params baseURL string 基础访问地址
// @params disabledBaseURLParse ...bool 是否禁用基础地址解析
// @return *BeClient 客户端指针
func New(baseURL string, disabledBaseURLParse ...bool) *BeClient {
// 新建客户端
c := new(BeClient)
// 初始化query参数
c.querys = make(url.Values)
// 初始化默认下载缓冲区
c.DownloadBufferSize(1024 * 1024 * 5)
// 配置多线程下载参数
c.DownloadMultiThread(20, 1024*1024*100)
// 初始化默认超时时间为15秒
c.TimeOut(time.Second * 15)
// 初始化默认资源类型
c.ContentType(ContentTypeJson)
// 是否禁用地址解析
if len(disabledBaseURLParse) > 0 && disabledBaseURLParse[0] {
c.disabledBaseURLParse = true
c.baseURL = baseURL
return c
}
// 解析基本网址
u, err := url.Parse(baseURL)
if err != nil {
c.errMsg = err
return c
}
// 截取协议,域名或IP,端口号三部分
c.baseURL = fmt.Sprintf("%s://%s", u.Scheme, u.Host)
// 判断是否需要赋值path
if len(u.Path) > 0 {
c.Path(u.Path)
}
// 判断是否需要处理URL参数
for key := range u.Query() {
c.Query(key, u.Query().Get(key))
}
// 返回创建的客户端
return c
}
// Path 路由地址
// @Desc 多次调用会拼接地址
// @params pathURL string 路由地址
// @return *BeClient 客户端指针
func (c *BeClient) Path(pathURL string) *BeClient {
// 禁用地址解析后该函数禁用
if c.disabledBaseURLParse {
c.errMsg = errors.New("disabled base url parse is open, Path function disabled")
return c
}
// 根据第一个问号分割字符串
index := strings.Index(pathURL, "?")
if index > -1 {
// 截取路径部分
c.pathURL += pathURL[:index]
// 判断是否需要处理参数部分
if len(pathURL[index:]) > 1 {
// 截取参数部分
query := pathURL[index+1:]
// 解析参数
values, err := url.ParseQuery(query)
if err != nil {
c.errMsg = err
return c
}
// 遍历赋值参数
for key := range values {
c.Query(key, values.Get(key))
}
}
} else {
// 不需要处理参数
c.pathURL += pathURL
}
return c
}
// Header 配置请求头
// @Desc 多次调用相同KEY的值会被覆盖
// @params key string 请求头名称
// @params val string 请求同内容
// @return *BeClient 客户端指针
func (c *BeClient) Header(key, val string) *BeClient {
c.headers.Store(key, val)
return c
}
// Cookie 配置请求Cookie
// @Desc 多次调用相同KEY的值会被覆盖
// @params key string Cookie名称
// @params val string Cookie内容
// @return *BeClient 客户端指针
func (c *BeClient) Cookie(key, val string) *BeClient {
c.cookies.Store(key, val)
return c
}
// Query 配置请求URL后参数
// @Desc 多次调用相同KEY的值会被覆盖
// @params key string 参数名称
// @params val string 参数内容
// @return *BeClient 客户端指针
func (c *BeClient) Query(key, val string) *BeClient {
c.querys.Set(key, val)
return c
}
// ContentType 配置资源类型
// @Desc 请求体将会被格式化为该资源类型
// @return *BeClient 客户端指针
func (c *BeClient) ContentType(contentType ContentTypeType) *BeClient {
c.contentType = contentType
return c
}
// Debug 开启Debug模式
// @Desc 打印的是JSON格式化后的数据
// @return *BeClient 客户端指针
func (c *BeClient) Debug() *BeClient {
c.debug = true
return c
}
// TimeOut 配置请求及响应的超时时间
// @params reqTimeOut time.Duration 请求超时时间
// @return *BeClient 客户端指针
func (c *BeClient) TimeOut(timeOut time.Duration) *BeClient {
c.timeOut = timeOut
return c
}
// Body 配置Body请求参数
// @Desc 会根据Content-Type来格式化数据
// @params data interface{} 请求参数
// @return *BeClient 客户端指针
func (c *BeClient) Body(reqBody interface{}) *BeClient {
c.data = reqBody
return c
}
// Download 标记当前请求为下载类型
// @Desc 使用该接口注册回调可实现下载进度功能
// @params savePath string 下载资源文件保存路径
// @params callback DownloadCallbackFuncType 下载进度回调函数(请勿在回调函数内处理过多业务,否则可能会造成响应超时)
// @return *BeClient 客户端指针
func (c *BeClient) Download(savePath string, callback DownloadCallbackFuncType) *BeClient {
c.isDownloadRequest = true
c.downloadSavePath = filepath.Join(strings.TrimSpace(savePath))
c.downloadCallFunc = callback
return c
}
// DownloadBufferSize 配置下载缓冲区大小
// @params size int64 下载缓冲区大小(单位:byte)(默认1024*1024*5byte[5MB],最小5byte[5B],最大1024*1024*1024byte[1GB])
// @return *BeClient 客户端指针
func (c *BeClient) DownloadBufferSize(size int64) *BeClient {
// 最低不能低于5byte
if size < 5 || size > 1024*1024*1024 {
return c
}
// 赋值全局
c.downloadBufferSize = size
return c
}
// DownloadMultiThread 配置多线程下载参数
// @params maxThreadNum int64 最大下载线程数量(默认20)
// @params maxDownloadSize int64 单个线程最大下载容量,仅在使用线程数低于最大线程数时有效(默认1024*1024*100byte[100MB],最小5byte[5B],最大1024*1024*1024*10byte[10GB])
// @return *BeClient 客户端指针
func (c *BeClient) DownloadMultiThread(maxThreadNum, maxDownloadSize int64) *BeClient {
// 至少要一个线程
if maxThreadNum < 1 {
maxThreadNum = c.downloadMaxThread
}
// 最低不能低于5byte并且不能大于10GB
if maxDownloadSize < 5 || maxDownloadSize > 1024*1024*1024*10 {
// 默认值
maxDownloadSize = c.downloadMaxSize
}
// 赋值到全局
c.downloadMaxThread = maxThreadNum
c.downloadMaxSize = maxDownloadSize
return c
}
// Get GET请求
// @Desc 第二个参数没有时,第一个参数必须为[]byte类型,将不对响应内容做转换处理
// @params resData interface{} 指定类型的变量指针
// @params resContentType ...ContentTypeType 规定的响应内容资源类型,将会根据该类型对响应内容做转换
// @return error 错误信息
func (c *BeClient) Get(resData interface{}, resContentType ...ContentTypeType) error {
// 赋值请求类型
c.method = MethodGet
// 发起请求
return c.send(resData, resContentType...)
}
// Head HEAD请求
// @Desc 第二个参数没有时,第一个参数必须为[]byte类型,将不对响应内容做转换处理
// @params resData interface{} 指定类型的变量指针
// @params resContentType ...ContentTypeType 规定的响应内容资源类型,将会根据该类型对响应内容做转换
// @return error 错误信息
func (c *BeClient) Head(resData interface{}, resContentType ...ContentTypeType) error {
// 赋值请求类型
c.method = MethodHead
// 发起请求
return c.send(resData, resContentType...)
}
// Post POST请求
// @Desc 第二个参数没有时,第一个参数必须为[]byte类型,将不对响应内容做转换处理
// @params resData interface{} 指定类型的变量指针
// @params resContentType ...ContentTypeType 规定的响应内容资源类型,将会根据该类型对响应内容做转换
// @return error 错误信息
func (c *BeClient) Post(resData interface{}, resContentType ...ContentTypeType) error {
// 赋值请求类型
c.method = MethodPost
// 发起请求
return c.send(resData, resContentType...)
}
// Put PUT请求
// @Desc 第二个参数没有时,第一个参数必须为[]byte类型,将不对响应内容做转换处理
// @params resData interface{} 指定类型的变量指针
// @params resContentType ...ContentTypeType 规定的响应内容资源类型,将会根据该类型对响应内容做转换
// @return error 错误信息
func (c *BeClient) Put(resData interface{}, resContentType ...ContentTypeType) error {
// 赋值请求类型
c.method = MethodPut
// 发起请求
return c.send(resData, resContentType...)
}
// Patch PATCH请求
// @Desc 第二个参数没有时,第一个参数必须为[]byte类型,将不对响应内容做转换处理
// @params resData interface{} 指定类型的变量指针
// @params resContentType ...ContentTypeType 规定的响应内容资源类型,将会根据该类型对响应内容做转换
// @return error 错误信息
func (c *BeClient) Patch(resData interface{}, resContentType ...ContentTypeType) error {
// 赋值请求类型
c.method = MethodPatch
// 发起请求
return c.send(resData, resContentType...)
}
// Delete DELETE请求
// @Desc 第二个参数没有时,第一个参数必须为[]byte类型,将不对响应内容做转换处理
// @params resData interface{} 指定类型的变量指针
// @params resContentType ...ContentTypeType 规定的响应内容资源类型,将会根据该类型对响应内容做转换
// @return error 错误信息
func (c *BeClient) Delete(resData interface{}, resContentType ...ContentTypeType) error {
// 赋值请求类型
c.method = MethodDelete
// 发起请求
return c.send(resData, resContentType...)
}
// Options OPTIONS请求
// @Desc 第二个参数没有时,第一个参数必须为[]byte类型,将不对响应内容做转换处理
// @params resData interface{} 指定类型的变量指针
// @params resContentType ...ContentTypeType 规定的响应内容资源类型,将会根据该类型对响应内容做转换
// @return error 错误信息
func (c *BeClient) Options(resData interface{}, resContentType ...ContentTypeType) error {
// 赋值请求类型
c.method = MethodOptions
// 发起请求
return c.send(resData, resContentType...)
}
// Trace Trace请求
// @Desc 第二个参数没有时,第一个参数必须为[]byte类型,将不对响应内容做转换处理
// @params resData interface{} 定类型的变量指针
// @params resContentType ...ContentTypeType 规定的响应内容资源类型,将会根据该类型对响应内容做转换
// @return error 错误信息
func (c *BeClient) Trace(resData interface{}, resContentType ...ContentTypeType) error {
// 赋值请求类型
c.method = MethodTrace
// 发起请求
return c.send(resData, resContentType...)
}
// GetHttpClient 获取HTTP客户端
// @return *http.Client HTTP客户端
// @return error 错误信息
func (c *BeClient) GetHttpClient() (*http.Client, error) {
// 判断是否已经构建
if c.client != nil {
return c.client, nil
}
// 执行构建
err := c.build()
if err != nil {
return nil, err
}
// 响应
return c.client, nil
}
// GetRequest 获取HTTP请求体
// @return *http.Request HTTP请求体
// @return error 错误信息
func (c *BeClient) GetRequest() (*http.Request, error) {
// 判断是否已经构建
if c.request != nil {
return c.request, nil
}
// 执行构建
err := c.build()
if err != nil {
return nil, err
}
// 响应
return c.request, nil
}
// GetResponse 获取HTTP响应体
// @return *http.Response HTTP响应体
// @return error 错误信息
func (c *BeClient) GetResponse() (*http.Response, error) {
// 判断响应体是否为空
if c.response == nil {
return nil, errors.New("please send an HTTP request first")
}
// 响应
return c.response, nil
}