176 lines
3.4 KiB
Go
176 lines
3.4 KiB
Go
package utils
|
|
|
|
import (
|
|
"errors"
|
|
"io"
|
|
"net/http"
|
|
"net/url"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
type curl struct {
|
|
data map[string]string
|
|
method string
|
|
uri string
|
|
baseUrl string
|
|
header map[string]string
|
|
cookie map[string]string
|
|
contentType string
|
|
}
|
|
|
|
func Curl(baseUrl string) *curl {
|
|
return &curl{baseUrl: baseUrl}
|
|
}
|
|
|
|
func (c *curl) SetCookie(cookie map[string]string) *curl {
|
|
c.cookie = cookie
|
|
return c
|
|
}
|
|
|
|
func (c *curl) SetHeader(header map[string]string) *curl {
|
|
c.header = header
|
|
return c
|
|
}
|
|
|
|
func (c *curl) SetData(data map[string]string) *curl {
|
|
c.data = data
|
|
return c
|
|
}
|
|
|
|
func (c *curl) SerUrl(url string) *curl {
|
|
c.baseUrl = url
|
|
return c
|
|
}
|
|
|
|
// SetType 类型,json还是form
|
|
// Type = "json" or "form" , 默认form
|
|
func (c *curl) SetType(Type string) *curl {
|
|
c.contentType = Type
|
|
return c
|
|
}
|
|
|
|
func (c *curl) Get(uri string) (string, error) {
|
|
url := c.getGetUrl(uri)
|
|
|
|
// 1. 临时构造带超时client,不改动原有curl成员
|
|
client := &http.Client{Timeout: 10 * time.Second}
|
|
resp, err := client.Get(url)
|
|
// 请求失败直接返回,resp是nil,不能执行Body.Close
|
|
if err != nil {
|
|
Logger.Error(url, err)
|
|
return "", err
|
|
}
|
|
|
|
// 安全defer关闭,单独捕获关闭错误,不污染外层err
|
|
defer func() {
|
|
closeErr := resp.Body.Close()
|
|
if closeErr != nil {
|
|
Logger.Error(url, "resp body close err:", closeErr)
|
|
}
|
|
}()
|
|
|
|
if resp.StatusCode != http.StatusOK {
|
|
Logger.Error(url, resp.StatusCode)
|
|
return "", errors.New("http status not 200, is " + strconv.Itoa(resp.StatusCode))
|
|
}
|
|
|
|
// 不再忽略读取错误
|
|
body, readErr := io.ReadAll(resp.Body)
|
|
if readErr != nil {
|
|
Logger.Error(url, "read body err:", readErr)
|
|
return "", readErr
|
|
}
|
|
|
|
return string(body), nil
|
|
}
|
|
|
|
func (c *curl) Run(uri, method string) (string, error) {
|
|
client := &http.Client{}
|
|
targetUrl := c.getUrl(uri)
|
|
|
|
data := c.getData()
|
|
if strings.ToUpper(method) == http.MethodGet {
|
|
data = nil
|
|
targetUrl = c.getGetUrl(uri)
|
|
}
|
|
|
|
req, err := http.NewRequest(http.MethodPost, targetUrl, strings.NewReader(data.Encode()))
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
Type := "application/x-www-form-urlencoded"
|
|
if strings.ToLower(c.contentType) == "json" {
|
|
Type = "application/json"
|
|
}
|
|
|
|
//设置请求头
|
|
req.Header.Set("content-type", Type)
|
|
req.Header.Set("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36")
|
|
|
|
if len(c.header) > 0 {
|
|
for k, v := range c.header {
|
|
req.Header.Add(k, v)
|
|
}
|
|
}
|
|
|
|
if len(c.cookie) > 0 {
|
|
for k, v := range c.header {
|
|
cookie := &http.Cookie{Name: k, Value: v}
|
|
req.AddCookie(cookie)
|
|
}
|
|
}
|
|
resp, err := client.Do(req)
|
|
if resp == nil { // 👈 必须加这个判断!
|
|
return "", err
|
|
}
|
|
defer func(Body io.ReadCloser) {
|
|
err := Body.Close()
|
|
if err != nil {
|
|
Logger.Error(err)
|
|
}
|
|
}(resp.Body)
|
|
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
body, _ := io.ReadAll(resp.Body)
|
|
|
|
return string(body), nil
|
|
}
|
|
|
|
func (c *curl) getData() url.Values {
|
|
data := url.Values{}
|
|
if len(c.data) > 0 {
|
|
for k, v := range c.data {
|
|
data.Add(k, v)
|
|
}
|
|
}
|
|
|
|
return data
|
|
}
|
|
|
|
func (c *curl) getUrl(uri string) string {
|
|
return c.baseUrl + uri
|
|
}
|
|
|
|
func (c *curl) getGetUrl(uri string) string {
|
|
targetUrl := c.getUrl(uri)
|
|
|
|
if len(c.data) > 0 {
|
|
u, _ := url.ParseRequestURI(targetUrl)
|
|
|
|
// URL param
|
|
data := c.getData()
|
|
|
|
u.RawQuery = data.Encode() // URL encode
|
|
|
|
return u.String()
|
|
}
|
|
|
|
return targetUrl
|
|
}
|