| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151 |
- // utils/http_client.go
- package utils
- import (
- "bytes"
- "context"
- "crypto/tls"
- "encoding/json"
- "fmt"
- "io"
- "net/http"
- "net/url"
- "strings"
- "time"
- )
- // 扩展 HTTPClient 接口
- type HTTPClient interface {
- RequestJSON(ctx context.Context, method string, reqURL string, body interface{}) ([]byte, error)
- RequestWithProxy(ctx context.Context, method string, reqURL string, body interface{}, proxyURL string) ([]byte, error)
- }
- // 修改 httpClient 结构体
- type httpClient struct {
- client *http.Client
- defaultProxy string // 新增默认代理配置
- skipSSLVerify bool
- }
- func NewHttpClient(timeout time.Duration, isSkipSSLVerify bool, defaultProxy string) HTTPClient {
- baseTransport := &http.Transport{
- TLSClientConfig: &tls.Config{
- InsecureSkipVerify: isSkipSSLVerify,
- },
- MaxIdleConns: 100,
- IdleConnTimeout: 90 * time.Second,
- DisableCompression: true,
- }
- return &httpClient{
- client: &http.Client{
- Timeout: timeout,
- Transport: baseTransport,
- },
- defaultProxy: defaultProxy,
- skipSSLVerify: isSkipSSLVerify,
- }
- }
- // 改进后的带代理请求方法
- func (c *httpClient) RequestWithProxy(ctx context.Context, method string, reqURL string, body interface{}, proxyURL string) ([]byte, error) {
- // 自动补充协议前缀(支持多种代理协议)
- if !strings.Contains(proxyURL, "://") {
- proxyURL = "http://" + proxyURL
- fmt.Printf("自动补充HTTP协议前缀: %s\n", proxyURL)
- }
- // 校验并解析代理URL
- parsedProxy, err := url.Parse(proxyURL)
- if err != nil {
- return nil, fmt.Errorf("代理地址格式错误(需要包含协议,示例:socks5://127.0.0.1:1080 或 http://proxy.com): %w", err)
- }
- // 配置代理传输
- proxyTransport := c.client.Transport.(*http.Transport).Clone()
- proxyTransport.Proxy = http.ProxyURL(parsedProxy)
- // 添加Transport配置验证
- if proxyTransport.Proxy == nil {
- return nil, fmt.Errorf("代理配置未正确应用到Transport")
- }
- // 创建带缓存的客户端
- proxyClient := &http.Client{
- Transport: proxyTransport,
- Timeout: c.client.Timeout,
- }
- // 执行请求并处理错误
- respData, err := c.doRequest(ctx, proxyClient, method, reqURL, body)
- if err != nil {
- return nil, fmt.Errorf("代理请求失败(%s): %w", proxyURL, err)
- }
- return respData, nil
- }
- // 修改方法签名
- func (c *httpClient) RequestJSON(ctx context.Context, method string, reqURL string, body interface{}) ([]byte, error) {
- return c.doRequest(ctx, c.client, method, reqURL, body)
- }
- // 重命名并修改doPostRequest
- func (c *httpClient) doRequest(ctx context.Context, client *http.Client, method string, reqURL string, body interface{}) ([]byte, error) {
- var reqBody []byte
- if body != nil && method != "GET" {
- var err error
- if byteBody, ok := body.([]byte); ok {
- reqBody = byteBody
- } else {
- if reqBody, err = json.Marshal(body); err != nil {
- return nil, fmt.Errorf("JSON序列化失败: %w", err)
- }
- }
- }
- if method == "GET" && body != nil {
- if params, ok := body.(map[string]string); ok {
- query := url.Values{}
- for k, v := range params {
- query.Add(k, v)
- }
- reqURL = fmt.Sprintf("%s?%s", reqURL, query.Encode())
- }
- }
- req, err := http.NewRequestWithContext(ctx, method, reqURL, bytes.NewReader(reqBody))
- if err != nil {
- return nil, fmt.Errorf("创建请求失败: %w", err)
- }
- req.Header.Set("Content-Type", "application/json; charset=utf-8")
- req.Header.Set("Accept", "application/json")
- // 原有脱敏日志
- // Logger.Printf("[HTTP请求] %s %s\nHeaders: %+v\nBody: %.100s",
- // method,
- // strings.ReplaceAll(reqURL, "access_token=[^\"]*", "access_token=***"),
- // req.Header,
- // string(reqBody))
- resp, err := client.Do(req)
- if resp != nil {
- // 记录响应日志(脱敏处理)
- bodyBytes, _ := io.ReadAll(resp.Body)
- resp.Body = io.NopCloser(bytes.NewBuffer(bodyBytes))
- // Logger.Printf("[HTTP响应] Status: %d\nHeaders: %+v\nBody: %.200s",
- // resp.StatusCode,
- // resp.Header,
- // string(bodyBytes))
- }
- if err != nil {
- return nil, fmt.Errorf("网络请求失败: %w", err)
- }
- defer resp.Body.Close()
- if resp.StatusCode < 200 || resp.StatusCode >= 300 {
- Logger.WithField("status", resp.StatusCode).Warn("非成功状态码")
- return nil, fmt.Errorf("非成功状态码: %d", resp.StatusCode)
- }
- return io.ReadAll(resp.Body)
- }
|