Files
gjs 10424d23d8
CI / changes (push) Successful in 1s
CI / docker-bff (push) Successful in 1s
CI / docker-product (push) Failing after 1s
add utils to pkg
2026-08-07 09:55:22 +08:00

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
}