初始化项目

This commit is contained in:
皮蛋13361098506
2025-01-06 16:01:02 +08:00
commit 1b77f62820
575 changed files with 69193 additions and 0 deletions

View File

@@ -0,0 +1,216 @@
// 适用于大量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
}

View File

@@ -0,0 +1,71 @@
package webUtil
import (
"testing"
"time"
)
func TestGet(t *testing.T) {
client := NewClient(nil)
result, err := client.Get("https://www.baidu.com", nil)
if err != nil {
t.Errorf("测试错误,返回的结果为:%s", err)
}
if len(result) == 0 {
t.Errorf("返回的数据为空,期望不为空")
}
//t.Log(string(result))
}
func TestGetTimeout(t *testing.T) {
transportOPT := &TransportOPT{
Timeout: 3 * time.Second,
}
opt := make(map[string]interface{})
opt["Timeout"] = 3 * time.Second
client := NewClient(transportOPT)
_, err := client.Get("https://www.google.com", nil)
if err != nil {
t.Log(err)
return
}
t.Errorf("测试异常")
}
func TestPostWithMap(t *testing.T) {
client := NewClient(nil)
data := make(map[string]string)
data["test1"] = "value1"
data["test2"] = "value2"
result, err := client.PostWithMap("http://www.baidu.com", data, nil)
if err != nil {
t.Errorf("测试错误,返回的结果为:%s", err)
}
if len(result) == 0 {
t.Errorf("返回的数据为空,期望不为空")
}
//t.Log(string(result))
}
func TestPostWithByte(t *testing.T) {
client := NewClient(nil)
result, err := client.PostWithByte("http://www.baidu.com", []byte("test=abc"), nil)
if err != nil {
t.Errorf("测试错误,返回的结果为:%s", err)
}
if len(result) == 0 {
t.Errorf("返回的数据为空,期望不为空")
}
//t.Log(string(result))
}

View File

@@ -0,0 +1,4 @@
/*
Web访问助手包
*/
package webUtil

182
trunk/goutil/webUtil/get.go Normal file
View File

@@ -0,0 +1,182 @@
package webUtil
import (
"fmt"
"io/ioutil"
"net/http"
"strings"
)
// GET数据
// weburl远程服务器地址
// header包头集合
// 返回值:
// 返回的字节
// 错误对象
func GetWebData(weburl string, header map[string]string) (result []byte, err error) {
// 构造请求对象
var request *http.Request
request, err = http.NewRequest("GET", weburl, nil)
if err != nil {
return
}
// 处理包头
if header != nil {
for k, v := range header {
request.Header.Add(k, v)
}
}
// 构造transport对象
transport := NewTransport()
transport.DisableKeepAlives = true
transport = GetTimeoutTransport(transport, 30)
// 构造httpClient对象
client := &http.Client{Transport: transport}
// 发送数据
var response *http.Response
response, err = client.Do(request)
if err != nil {
return
}
defer response.Body.Close()
// 读取数据
if response.StatusCode == http.StatusOK {
result, err = ioutil.ReadAll(response.Body)
if err != nil {
return
}
}
return
}
// GET数据新方法
// weburl:远程服务器地址
// data数据集合
// header:包头内容
// transport:transport对象
// 返回值
// http StatusCode
// 字节数组
// 错误对象
func GetWebData2(weburl string, data map[string]string, header map[string]string, transport *http.Transport) (statusCode int, result []byte, err error) {
// 处理data将data以key=value的形式拼接到weburl后形成一个完整的url
dataStr := ""
count := 0
for k, v := range data {
if count == len(data)-1 {
dataStr += fmt.Sprintf("%s=%s", k, v)
} else {
dataStr += fmt.Sprintf("%s=%s&", k, v)
}
count += 1
}
if dataStr != "" {
if strings.Contains(weburl, "?") {
weburl = fmt.Sprintf("%s&%s", weburl, dataStr)
} else {
weburl = fmt.Sprintf("%s?%s", weburl, dataStr)
}
}
// 构造请求对象
var request *http.Request
request, err = http.NewRequest("GET", weburl, nil)
if err != nil {
return
}
// 处理头部
if header != nil {
for k, v := range header {
request.Header.Add(k, v)
}
}
// 构造transport对象
if transport == nil {
transport = NewTransport()
transport.DisableKeepAlives = true
transport = GetTimeoutTransport(transport, 30)
}
// 构造httpClient对象
client := &http.Client{Transport: transport}
// 发送数据
var response *http.Response
response, err = client.Do(request)
if err != nil {
return
}
defer response.Body.Close()
// 获取返回值
statusCode = response.StatusCode
result, err = ioutil.ReadAll(response.Body)
return
}
// GET数据新方法
// weburl:远程服务器地址
// dataStr:参数字符串
// header:包头内容
// transport:transport对象
// 返回值
// http StatusCode
// 字节数组
// 错误对象
func GetWebData3(weburl string, dataStr string, header map[string]string, transport *http.Transport) (statusCode int, result []byte, err error) {
if dataStr != "" {
if strings.Contains(weburl, "?") {
weburl = fmt.Sprintf("%s&%s", weburl, dataStr)
} else {
weburl = fmt.Sprintf("%s?%s", weburl, dataStr)
}
}
// 构造请求对象
var request *http.Request
request, err = http.NewRequest("GET", weburl, nil)
if err != nil {
return
}
// 处理头部
if header != nil {
for k, v := range header {
request.Header.Add(k, v)
}
}
// 构造transport对象
if transport == nil {
transport = NewTransport()
transport.DisableKeepAlives = true
transport = GetTimeoutTransport(transport, 30)
}
// 构造httpClient对象
client := &http.Client{Transport: transport}
// 发送数据
var response *http.Response
response, err = client.Do(request)
if err != nil {
return
}
defer response.Body.Close()
// 获取返回值
statusCode = response.StatusCode
result, err = ioutil.ReadAll(response.Body)
return
}

View File

@@ -0,0 +1,41 @@
package webUtil
import (
"testing"
)
func TestGetWebData(t *testing.T) {
weburl := "http://www.baidu.com"
resp, err := GetWebData(weburl, nil)
if err != nil {
t.Errorf("测试错误,返回的结果为:%s", err)
}
if len(resp) == 0 {
t.Errorf("返回的数据为空,期望不为空")
}
}
func TestGetWebData2(t *testing.T) {
weburl := "http://www.baidu.com"
data := make(map[string]string)
status, resp, err := GetWebData2(weburl, data, nil, nil)
if status != 200 || err != nil {
t.Errorf("Test failed. status:%d, err:%s", status, err)
}
if len(resp) == 0 {
t.Errorf("The result is empty, but we expect not empty")
}
data["Name"] = "Jordan"
data["Age"] = "32"
status, resp, err = GetWebData2(weburl, data, nil, nil)
if status != 200 || err != nil {
t.Errorf("Test failed. status:%d, err:%s", status, err)
}
if len(resp) == 0 {
t.Errorf("The result is empty, but we expect not empty")
}
}

View File

@@ -0,0 +1,313 @@
package webUtil
import (
"bytes"
"crypto/tls"
"io/ioutil"
"net/http"
"net/url"
)
func GetFormHeader() map[string]string {
return map[string]string{"Content-Type": "application/x-www-form-urlencoded"}
}
func GetJsonHeader() map[string]string {
return map[string]string{"Content-Type": "application/json;charset=UTF-8"}
}
// POST数据
// weburl远程服务器地址
// datapost的数据集合
// header包头集合
// 返回值:
// 返回的字节
// 错误对象
func PostWebData(weburl 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)
// 调用发送Byte数组的方法
result, err = PostByteData(weburl, byteData, header)
return
}
// POST Byte数组
// weburl远程服务器地址
// datapost的Byte数组
// header包头集合
// 返回值:
// 返回的字节
// 错误对象
func PostByteData(weburl string, data []byte, header map[string]string) (result []byte, err error) {
// 组装POST数据
reader := bytes.NewReader(data)
// 构造请求对象
var request *http.Request
request, err = http.NewRequest("POST", weburl, reader)
if err != nil {
return
}
// 处理头部(包括默认头部,以及传入的头部集合)
if header == nil {
for k, v := range GetFormHeader() {
request.Header.Add(k, v)
}
} else {
for k, v := range header {
request.Header.Add(k, v)
}
}
// 构造transport对象
transport := NewTransport()
transport.DisableKeepAlives = true
transport = GetTimeoutTransport(transport, 30)
transport.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
// 构造httpClient对象
client := &http.Client{Transport: transport}
// 发送数据
var response *http.Response
response, err = client.Do(request)
if err != nil {
return
}
defer response.Body.Close()
// 读取数据
result, err = ioutil.ReadAll(response.Body)
return
}
// POST Byte数组
// weburl远程服务器地址
// datapost的Byte数组
// header包头集合
// transport: transport对象
// 返回值:
// 返回的字节
// 错误对象
func PostByteDataWithTransport(weburl string, data []byte, header map[string]string, transport *http.Transport) (result *[]byte, err error) {
// 组装POST数据
reader := bytes.NewReader(data)
// 构造请求对象
var request *http.Request
request, err = http.NewRequest("POST", weburl, reader)
if err != nil {
return
}
// 处理头部
if header != nil {
for k, v := range header {
request.Header.Add(k, v)
}
}
// 构造transport对象
if transport == nil {
transport = NewTransport()
transport.DisableKeepAlives = true
transport = GetTimeoutTransport(transport, 30)
transport.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
}
// 构造httpClient对象
client := &http.Client{Transport: transport}
// 发送数据
var response *http.Response
response, err = client.Do(request)
if err != nil {
return
}
defer response.Body.Close()
body, err1 := ioutil.ReadAll(response.Body)
if err1 != nil {
err = err1
return
}
result = &body
return
}
// POST map类型的数据
// weburl:远程服务器地址
// data:数据
// header:包头内容
// transport:transport对象
// 返回值
// http StatusCode
// 字节数组
// 错误对象
func PostMapData(weburl string, data map[string]string, header map[string]string, transport *http.Transport) (statusCode int, result []byte, err error) {
// 组装POST数据
postValues := url.Values{}
for key, value := range data {
postValues.Set(key, value)
}
postDataStr := postValues.Encode()
byteData := []byte(postDataStr)
statusCode, result, err = PostByteData2(weburl, byteData, header, transport)
return
}
// POST byte类型的数据新方法
// weburl:远程服务器地址
// data:数据
// header:包头内容
// transport:transport对象
// 返回值
// http StatusCode
// 字节数组
// 错误对象
func PostByteData2(weburl string, data []byte, header map[string]string, transport *http.Transport) (statusCode int, result []byte, err error) {
// 组装POST数据
reader := bytes.NewReader(data)
// 构造请求对象
var request *http.Request
request, err = http.NewRequest("POST", weburl, reader)
if err != nil {
return
}
// 处理头部
if header != nil {
for k, v := range header {
request.Header.Add(k, v)
}
}
// 构造transport对象
if transport == nil {
transport = NewTransport()
transport.DisableKeepAlives = true
transport = GetTimeoutTransport(transport, 30)
transport.TLSClientConfig = &tls.Config{InsecureSkipVerify: true} //关闭证书校验
}
// 构造httpClient对象
client := &http.Client{Transport: transport}
// 发送数据
var response *http.Response
response, err = client.Do(request)
if err != nil {
return
}
defer response.Body.Close()
// 获取返回值
statusCode = response.StatusCode
result, err = ioutil.ReadAll(response.Body)
return
}
// POST Byte数组
// weburl远程服务器地址
// datapost的Byte数组
// header包头集合
// 返回值:
// 返回的字节
// 错误对象
func PostByteData3(weburl string, data []byte, header map[string]string) (result []byte, err error) {
// 组装POST数据
reader := bytes.NewReader(data)
// 构造请求对象
var request *http.Request
request, err = http.NewRequest("POST", weburl, reader)
if err != nil {
return
}
request.Header.Set("Content-Type", "application/json;charset=UTF-8")
// 构造transport对象
transport := NewTransport()
transport.DisableKeepAlives = true
transport = GetTimeoutTransport(transport, 30)
transport.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
// 构造httpClient对象
client := &http.Client{Transport: transport}
// 发送数据
var response *http.Response
response, err = client.Do(request)
if err != nil {
return
}
defer response.Body.Close()
// 读取数据
result, err = ioutil.ReadAll(response.Body)
return
}
// POST Byte数组
// weburl远程服务器地址
// datapost的Byte数组
// header包头集合
// timeout:超时时间
// 返回值:
// 返回的字节
// 错误对象
func PostByteData4(weburl string, data []byte, header map[string]string, timeout int) (result []byte, err error) {
// 组装POST数据
reader := bytes.NewReader(data)
// 构造请求对象
var request *http.Request
request, err = http.NewRequest("POST", weburl, reader)
if err != nil {
return
}
request.Header.Set("Content-Type", "application/json;charset=UTF-8")
// 构造transport对象
if timeout <= 0 {
timeout = 30
}
transport := NewTransport()
transport.DisableKeepAlives = true
transport = GetTimeoutTransport(transport, timeout)
transport.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
// 构造httpClient对象
client := &http.Client{Transport: transport}
// 发送数据
var response *http.Response
response, err = client.Do(request)
if err != nil {
return
}
defer response.Body.Close()
// 读取数据
result, err = ioutil.ReadAll(response.Body)
return
}

View File

@@ -0,0 +1,26 @@
package webUtil
import (
"goutil/zlibUtil"
"testing"
)
func TestPostWebData(t *testing.T) {
weburl := "https://managecenterapitest-sd3.7qule.com/API/ServerActivate.ashx"
postDict := make(map[string]string, 0)
postDict["ServerGroupID"] = "20002"
resp, err := PostWebData(weburl, postDict, nil)
if err != nil {
t.Errorf("测试错误,返回的结果为:%s", err)
}
if len(resp) == 0 {
t.Errorf("返回的数据为空,期望不为空")
}
// 将收到的数据进行zlib解压缩
_, err = zlibUtil.Decompress(resp)
if err != nil {
t.Errorf("Error:%s", err)
}
}

104
trunk/goutil/webUtil/web.go Normal file
View File

@@ -0,0 +1,104 @@
package webUtil
import (
"crypto/tls"
"fmt"
"net"
"net/http"
"sort"
"time"
"goutil/netUtil"
)
// 获取请求的IP(obsolete, 直接调用netUtil.GetHttpAddr)
// 返回值:
// 请求的IP
func GetRequestIP(r *http.Request) string {
/*
http中调用JoinHostPort来给RemoteAddr赋值它的规则如下
JoinHostPort combines host and port into a network address of the
form "host:port" or, if host contains a colon or a percent sign,
"[host]:port".
所以现在要将RemoteAddr解析成host和port则需要找到最后一个:前面的部分则是host
如果host包含[],则需要去除
*/
return netUtil.GetHttpAddr(r).Host
}
func NewTransport() *http.Transport {
return &http.Transport{}
}
// timeout 超时时间
func GetTimeoutTransport(transport *http.Transport, timeout int) *http.Transport {
transport.Dial = func(netw, addr string) (net.Conn, error) {
deadline := time.Now().Add(time.Duration(timeout) * time.Second)
c, err := net.DialTimeout(netw, addr, time.Second*time.Duration(timeout))
if err != nil {
return nil, err
}
c.SetDeadline(deadline)
return c, nil
}
return transport
}
// b 表示是否需要验证http证书
func GetTLSTransport(transport *http.Transport, b bool) *http.Transport {
transport.TLSClientConfig = &tls.Config{InsecureSkipVerify: b}
return transport
}
// 组装请求字符串
// requestMap:请求数据集合
func AssembleRequestParam(requestMap map[string]string) (dataStr string) {
count := 0
for k, v := range requestMap {
if count == len(requestMap)-1 {
dataStr += fmt.Sprintf("%s=%s", k, v)
} else {
dataStr += fmt.Sprintf("%s=%s&", k, v)
}
count += 1
}
return
}
// 按照参数名称升序组装请求字符串
// requestMap:请求数据集合
// asc:是否升序
func AssembleRequestParamSort(requestMap map[string]string, asc bool) (dataStr string) {
finalKeys := make([]string, 0, len(requestMap))
// 按key进行排序
sortKeys := make([]string, 0, len(requestMap))
for k, _ := range requestMap {
sortKeys = append(sortKeys, k)
}
sort.Strings(sortKeys)
// 排序是升序还是降序
if asc {
finalKeys = sortKeys
} else {
for i := len(sortKeys) - 1; i >= 0; i-- {
finalKeys = append(finalKeys, sortKeys[i])
}
}
for index, key := range finalKeys {
if index == len(finalKeys)-1 {
dataStr += fmt.Sprintf("%s=%s", key, requestMap[key])
} else {
dataStr += fmt.Sprintf("%s=%s&", key, requestMap[key])
}
}
return
}