217 lines
4.9 KiB
Plaintext
217 lines
4.9 KiB
Plaintext
|
|
// 适用于大量http(s)请求,连接复用
|
|||
|
|
package webUtil
|
|||
|
|
|
|||
|
|
import (
|
|||
|
|
"bytes"
|
|||
|
|
"context"
|
|||
|
|
"fmt"
|
|||
|
|
"io/ioutil"
|
|||
|
|
"net/http"
|
|||
|
|
"net/http/httptrace"
|
|||
|
|
"net/url"
|
|||
|
|
"time"
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
type Client struct {
|
|||
|
|
traceCtx context.Context
|
|||
|
|
client *http.Client
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
type TransportOPT struct {
|
|||
|
|
//超时时间
|
|||
|
|
Timeout time.Duration
|
|||
|
|
|
|||
|
|
//代理字符串,如"http://127.0.0.1:1080"
|
|||
|
|
ProxyString string
|
|||
|
|
|
|||
|
|
//最大保持连接数
|
|||
|
|
MaxIdleConns int
|
|||
|
|
|
|||
|
|
//每个主机的最大保持连接数
|
|||
|
|
MaxIdleConnsPerHost int
|
|||
|
|
|
|||
|
|
//单主机最大连接数
|
|||
|
|
MaxConnsPerHost int
|
|||
|
|
|
|||
|
|
//保持连接的超时时间
|
|||
|
|
IdleConnTimeout time.Duration
|
|||
|
|
|
|||
|
|
//禁止保持连接
|
|||
|
|
DisableKeepAlives bool
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// GET请求
|
|||
|
|
func (c *Client) Get(urlStr string, header map[string]string) (result []byte, err error) {
|
|||
|
|
req, err := http.NewRequestWithContext(c.traceCtx, http.MethodGet, urlStr, nil)
|
|||
|
|
if err != nil {
|
|||
|
|
//fmt.Println(err)
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 处理头部(包括默认头部,以及传入的头部集合)
|
|||
|
|
if header == nil {
|
|||
|
|
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
|
|||
|
|
} else {
|
|||
|
|
for k, v := range header {
|
|||
|
|
req.Header.Add(k, v)
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
res, err := c.client.Do(req)
|
|||
|
|
if err != nil {
|
|||
|
|
//fmt.Println(err)
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
defer res.Body.Close()
|
|||
|
|
|
|||
|
|
result, err = ioutil.ReadAll(res.Body)
|
|||
|
|
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// POST请求
|
|||
|
|
func (c *Client) PostWithMap(urlStr string, data map[string]string, header map[string]string) (result []byte, err error) {
|
|||
|
|
// 组装POST数据
|
|||
|
|
postValues := url.Values{}
|
|||
|
|
for key, value := range data {
|
|||
|
|
postValues.Set(key, value)
|
|||
|
|
}
|
|||
|
|
postDataStr := postValues.Encode()
|
|||
|
|
byteData := []byte(postDataStr)
|
|||
|
|
|
|||
|
|
var req *http.Request
|
|||
|
|
req, err = http.NewRequestWithContext(c.traceCtx, http.MethodPost, urlStr, bytes.NewReader(byteData))
|
|||
|
|
if err != nil {
|
|||
|
|
//fmt.Println(err)
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 处理头部(包括默认头部,以及传入的头部集合)
|
|||
|
|
if header == nil {
|
|||
|
|
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
|
|||
|
|
} else {
|
|||
|
|
for k, v := range header {
|
|||
|
|
req.Header.Add(k, v)
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var res *http.Response
|
|||
|
|
res, err = c.client.Do(req)
|
|||
|
|
if err != nil {
|
|||
|
|
fmt.Println(err)
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
defer res.Body.Close()
|
|||
|
|
|
|||
|
|
result, err = ioutil.ReadAll(res.Body)
|
|||
|
|
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// POST请求
|
|||
|
|
func (c *Client) PostWithByte(urlStr string, data []byte, header map[string]string) (result []byte, err error) {
|
|||
|
|
var req *http.Request
|
|||
|
|
req, err = http.NewRequestWithContext(c.traceCtx, http.MethodPost, urlStr, bytes.NewReader(data))
|
|||
|
|
if err != nil {
|
|||
|
|
//fmt.Println(err)
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 处理头部(包括默认头部,以及传入的头部集合)
|
|||
|
|
if header == nil {
|
|||
|
|
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
|
|||
|
|
} else {
|
|||
|
|
for k, v := range header {
|
|||
|
|
req.Header.Add(k, v)
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var res *http.Response
|
|||
|
|
res, err = c.client.Do(req)
|
|||
|
|
if err != nil {
|
|||
|
|
fmt.Println(err)
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
defer res.Body.Close()
|
|||
|
|
|
|||
|
|
result, err = ioutil.ReadAll(res.Body)
|
|||
|
|
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 新建Client对象
|
|||
|
|
// transportOPT参数说明
|
|||
|
|
//
|
|||
|
|
// Timeout - 连接绝对超时时间
|
|||
|
|
// ProxyString - 代理字符串
|
|||
|
|
// MaxIdleConns - 最大空闲连接数
|
|||
|
|
// MaxIdleConnsPerHost - 每个目标主机的最大空闲连接数
|
|||
|
|
// MaxConnsPerHost - 每个目标主机的最大连接数
|
|||
|
|
// IdleConnTimeout - 空闲连接超时时间
|
|||
|
|
// DisableKeepAlives - 禁用连接保持(要使用连接复用,此值不传入或传入false;否则连接可能不会复用)
|
|||
|
|
func NewClient(transportOPT *TransportOPT) (c *Client) {
|
|||
|
|
c = &Client{}
|
|||
|
|
|
|||
|
|
//代理
|
|||
|
|
getProxy := func() func(*http.Request) (*url.URL, error) {
|
|||
|
|
if (transportOPT != nil) && len(transportOPT.ProxyString) > 0 {
|
|||
|
|
uri, _ := url.Parse(transportOPT.ProxyString)
|
|||
|
|
return http.ProxyURL(uri)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 默认参数
|
|||
|
|
timeout := 30 * time.Second
|
|||
|
|
maxIdleConns := 60000
|
|||
|
|
maxIdleConnsPerHost := 30000
|
|||
|
|
maxConnsPerHost := 30000
|
|||
|
|
idleConnTimeout := time.Minute * 1
|
|||
|
|
disableKeepAlives := false
|
|||
|
|
|
|||
|
|
if transportOPT != nil {
|
|||
|
|
// 根据传入参数修改默认参数
|
|||
|
|
if transportOPT.Timeout > 0 {
|
|||
|
|
timeout = transportOPT.Timeout
|
|||
|
|
}
|
|||
|
|
if transportOPT.MaxIdleConns > 0 {
|
|||
|
|
maxIdleConns = transportOPT.MaxIdleConns
|
|||
|
|
}
|
|||
|
|
if transportOPT.MaxIdleConnsPerHost > 0 {
|
|||
|
|
maxIdleConnsPerHost = transportOPT.MaxIdleConnsPerHost
|
|||
|
|
}
|
|||
|
|
if transportOPT.MaxConnsPerHost > 0 {
|
|||
|
|
maxConnsPerHost = transportOPT.MaxConnsPerHost
|
|||
|
|
}
|
|||
|
|
if transportOPT.IdleConnTimeout > 0 {
|
|||
|
|
idleConnTimeout = transportOPT.IdleConnTimeout
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
disableKeepAlives = transportOPT.DisableKeepAlives
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
clientTrace := &httptrace.ClientTrace{
|
|||
|
|
//GotConn: func(gci httptrace.GotConnInfo) {
|
|||
|
|
// fmt.Printf("conn was reused: %t\n", gci.Reused)
|
|||
|
|
//},
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
c.traceCtx = httptrace.WithClientTrace(context.Background(), clientTrace)
|
|||
|
|
c.client = &http.Client{
|
|||
|
|
Timeout: timeout,
|
|||
|
|
|
|||
|
|
Transport: &http.Transport{
|
|||
|
|
Proxy: getProxy(),
|
|||
|
|
MaxIdleConns: maxIdleConns,
|
|||
|
|
MaxIdleConnsPerHost: maxIdleConnsPerHost,
|
|||
|
|
MaxConnsPerHost: maxConnsPerHost,
|
|||
|
|
IdleConnTimeout: idleConnTimeout,
|
|||
|
|
DisableKeepAlives: disableKeepAlives,
|
|||
|
|
// ForceAttemptHTTP2: true,
|
|||
|
|
},
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return
|
|||
|
|
}
|