forked from duolabmeng6/goefun
/
ehttp.go
396 lines (350 loc) · 9.72 KB
/
ehttp.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
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
// ehttp
// 简单易用的http客户端
package ehttp
import (
"bytes"
"crypto/tls"
"errors"
"io"
"io/ioutil"
"mime/multipart"
"net"
"net/http"
"net/url"
"os"
"strings"
"time"
. "github.com/599070001/goefun/core"
. "github.com/599070001/goefun/coreUtil"
"github.com/599070001/goefun/src/cookiejar"
)
type Ehttp struct {
client *http.Client
transport *http.Transport
Headers http.Header
Timeout int
Response *http.Response
Cookies *cookiejar.Jar
状态码 int
cookieFilePath string
//E重定向方式 重定向 1,不允许重定向。2,自动重定向
E重定向方式 int
//重定向地址
Location string
//E代理方式 0 使用全局代理ip访问 1 不使用代理ip访问
E代理方式 int
//代理ip
Proxy string
//全局头信息
全局头信息 string
//默认头信息
默认头信息 string
//超时时间
TimeOut int
}
func (this *Ehttp) E设置本次不使用代理() *Ehttp {
this.E代理方式 = 1
return this
}
func (this *Ehttp) E设置超时时间(超时时间 int) *Ehttp {
this.TimeOut = 超时时间
return this
}
func (this *Ehttp) reset() *Ehttp {
this.TimeOut = 15
this.E重定向方式 = 2
this.E代理方式 = 0
return this
}
func (this *Ehttp) Get(url string, v ...interface{}) (string, bool) {
var 附加头信息 string
if len(v) > 1 {
附加头信息 = E到文本(v[0])
}
body, _ := this.E访问(
url,
"GET",
"",
附加头信息,
)
return string(body), this.E访问失败()
}
func (this *Ehttp) GetByte(url string, v ...interface{}) ([]byte, bool) {
var 附加头信息 string
if len(v) > 1 {
附加头信息 = E到文本(v[0])
}
body, _ := this.E访问(
url,
"GET",
"",
附加头信息,
)
return body, this.E访问失败()
}
// token=token&name=1.txt&file=@file:文件的绝对路径
func (this *Ehttp) PostByte(url string, s string, v ...interface{}) ([]byte, bool) {
var 附加头信息 string
if len(v) > 1 {
附加头信息 = E到文本(v[0])
}
body, _ := this.E访问(
url,
"POST",
s,
附加头信息,
)
return body, this.E访问失败()
}
// token=token&name=1.txt&file=@file:文件的绝对路径
func (this *Ehttp) Post(url string, s string, v ...interface{}) (string, bool) {
var 附加头信息 string
if len(v) > 1 {
附加头信息 = E到文本(v[0])
}
body, _ := this.E访问(
url,
"POST",
s,
附加头信息,
)
return string(body), this.E访问失败()
}
func (this *Ehttp) E访问(url string, 访问方法 string, 发送文本 string, 附加头信息 string) ([]byte, error) {
this.setObj()
t := New时间统计类()
var req *http.Request
var err error
var 文件上传头信息 string
文件上传头信息 = ""
if 访问方法 == "GET" {
req, err = http.NewRequest("GET", url, nil)
} else {
if strings.Contains(发送文本, "@file:") {
// File uploading request.
buffer := new(bytes.Buffer)
writer := multipart.NewWriter(buffer)
for _, item := range E分割文本(发送文本, "&") {
array := E分割文本(item, "=")
if len(array[1]) > 6 && array[1][0:6] == "@file:" {
path := array[1][6:]
if !E文件是否存在(path) {
E调试输出格式化("%s %s error:%s Time:%s ms \n", 访问方法, url, E格式化文本(`"%s" 没有找到文件`, path), t.E取毫秒())
return nil, errors.New(E格式化文本(`"%s" 没有找到文件`, path))
}
name := E文件_取文件名(path)
if file, err := writer.CreateFormFile(array[0], name); err == nil {
if f, err := os.Open(path); err == nil {
defer f.Close()
if _, err = io.Copy(file, f); err != nil {
return nil, err
}
} else {
return nil, err
}
} else {
return nil, err
}
} else {
writer.WriteField(array[0], array[1])
}
}
writer.Close()
if req, err = http.NewRequest("POST", url, buffer); err != nil {
return nil, err
} else {
文件上传头信息 = "Content-Type:" + writer.FormDataContentType()
}
} else {
req, err = http.NewRequest("POST", url, strings.NewReader(发送文本))
}
}
if err != nil {
return []byte{}, err
}
填充来源地址 := "Referer:" + url
_整理头信息 := this.默认头信息 + "\r\n" +
填充来源地址 + "\r\n" +
this.全局头信息 + "\r\n" +
附加头信息 +
文件上传头信息
arr := E分割文本(_整理头信息, "\n")
for _, v := range arr {
kk := E删首尾空(StrCut(v, "$:"))
vv := E删首尾空(StrCut(v, ":$"))
if kk == "" {
continue
}
req.Header.Set(kk, vv)
}
//让程序自动处理gzip
req.Header.Del("Accept-Encoding")
//client := &http.Client{}
resp, err := this.client.Do(req)
if err != nil {
E调试输出格式化("%s %s error:%s Time:%s ms \n", 访问方法, url, err.Error(), t.E取毫秒())
return []byte{}, err
}
this.状态码 = resp.StatusCode
//E调试输出(this)
defer resp.Body.Close()
content, err := ioutil.ReadAll(resp.Body)
//E调试输出(E到文本(content))
this.Response = resp
//重定向的操作
if this.E重定向方式 != 0 && (resp.StatusCode == 302 || resp.StatusCode == 301) {
this.Location = resp.Header.Get("Location")
E调试输出格式化("%s %s StatusCode:%d Time:%s ms \nLocation: %s\n", 访问方法, url, resp.StatusCode, t.E取毫秒(), this.Location)
//自动处理重定向消息
if this.E重定向方式 == 2 {
return this.E访问(this.Location, "GET", 发送文本, 附加头信息)
}
} else {
E调试输出格式化("%s %s StatusCode:%d Time:%s ms \n", 访问方法, url, resp.StatusCode, t.E取毫秒())
}
//if E判断文本(resp.Header.Get("Content-Type"),"UTF-8") {
//
//}else{
// content = E到字节集(E文本编码转换(content, "", "utf-8"))
//}
this.cookie_save()
this.reset()
return content, err
}
// 访问失败 返回真 成功 返回假
func (this *Ehttp) E访问失败() bool {
if this.状态码 == 200 {
return false
} else {
if this.状态码 == 302 {
return false
}
}
return true
}
func (this *Ehttp) E取状态码() int {
return this.状态码
}
func (this *Ehttp) GetLcation() string {
return this.Response.Header.Get("Location")
}
func (this *Ehttp) E取头信息(s string) string {
return this.Response.Header.Get(s)
}
func (this *Ehttp) E取所有头信息() string {
str := ""
for k, v := range this.Response.Header {
//E调试输出P(k,v)
str = str + E格式化文本("%v: %v\r\n", k, v[0])
}
return str
}
func NewHttp() *Ehttp {
ehttp := new(Ehttp)
ehttp.client = &http.Client{}
ehttp.transport = &http.Transport{}
ehttp.Cookies, _ = cookiejar.New(nil)
ehttp.默认头信息 = `
Accept : */*
Accept-Language: zh-cn,
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36,
Content-Type: application/x-www-form-urlencoded,
`
return ehttp
}
func (this *Ehttp) setObj() *Ehttp {
trans := &http.Transport{
DialContext: (&net.Dialer{
Timeout: time.Duration(this.TimeOut) * time.Second,
KeepAlive: time.Duration(this.TimeOut) * time.Second,
}).DialContext,
MaxIdleConns: 0,
MaxIdleConnsPerHost: 100,
MaxConnsPerHost: 2,
IdleConnTimeout: 90 * time.Second,
//TLSHandshakeTimeout指定等待TLS握手完成的最长时间。零值表示不设置超时。
TLSHandshakeTimeout: time.Duration(this.TimeOut) * time.Second,
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
ExpectContinueTimeout: 1 * time.Second,
//ResponseHeaderTimeout指定在发送完请求(包括其可能的主体)之后,
//等待接收服务端的回复的头域的最大时间。零值表示不设置超时。
ResponseHeaderTimeout: time.Duration(this.TimeOut) * time.Second,
Proxy: nil,
//如果DisableKeepAlives为真,会禁止不同HTTP请求之间TCP连接的重用。
DisableKeepAlives: true,
DisableCompression: false,
}
//this.Proxy = "http://127.0.0.1:8888"
if this.E代理方式 == 1 || this.Proxy == "" {
trans.Proxy = nil
} else {
trans.Proxy = func(_ *http.Request) (*url.URL, error) {
return url.Parse(this.Proxy)
}
}
client := &http.Client{
Transport: trans,
CheckRedirect: func(req *http.Request, via []*http.Request) error {
return http.ErrUseLastResponse
},
Jar: this.Cookies,
Timeout: time.Duration(this.TimeOut) * time.Second,
}
this.client = client
this.transport = trans
return this
}
// SetProxy 设置代理访问
//
// SetProxy("http://127.0.0.1:8888")
func (this *Ehttp) SetProxy(proxy string) *Ehttp {
this.Proxy = proxy
return this
}
func (this *Ehttp) E设置全局HTTP代理(proxy string) *Ehttp {
return this.SetProxy(proxy)
}
func (this *Ehttp) SetTimeOut超时时间(超时时间 int) *Ehttp {
this.TimeOut = 超时时间
return this
}
func (this *Ehttp) E取伪造代理ip头信息() string {
return "X-Forwarded-For: " + E取随机ip()
}
func (this *Ehttp) SetGlobalHeaders(str string) *Ehttp {
this.全局头信息 = str
return this
}
func (this *Ehttp) E设置全局头信息(s string) *Ehttp {
return this.SetGlobalHeaders(s)
}
func (this *Ehttp) E设置自动管理cookie(cookie文件路径 string) *Ehttp {
return this.SetAutoSaveCookie(cookie文件路径)
}
// 设置自动保存cookie文件
func (this *Ehttp) SetAutoSaveCookie(filepath string) *Ehttp {
this.cookieFilePath = filepath
this.cookie_load()
return this
}
// cookie_load 从文件中加载cookie
func (this *Ehttp) cookie_load() *Ehttp {
if this.cookieFilePath == "" {
return this
}
cdata := E读入文件(this.cookieFilePath)
this.Cookies.JsonDeserialize(cdata)
return this
}
// cookie_save 保存cookie到文件
func (this *Ehttp) cookie_save() *Ehttp {
if this.cookieFilePath == "" {
return this
}
cdata, _ := this.Cookies.JsonSerialize()
if len(cdata) == 2 {
return this
}
E写到文件(this.cookieFilePath, cdata)
return this
}