|
|
package utils
|
|
|
|
|
|
import (
|
|
|
"bytes"
|
|
|
"context"
|
|
|
"encoding/json"
|
|
|
"io"
|
|
|
"net/http"
|
|
|
"net/url"
|
|
|
"strings"
|
|
|
"sync"
|
|
|
"time"
|
|
|
)
|
|
|
|
|
|
type HttpClient struct {
|
|
|
client *http.Client
|
|
|
}
|
|
|
|
|
|
// NewHttpClient 创建带超时的 HTTP 客户端
|
|
|
func NewHttpClient(timeout time.Duration) *HttpClient {
|
|
|
return &HttpClient{
|
|
|
client: &http.Client{
|
|
|
Timeout: timeout,
|
|
|
},
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// Get 发送 GET 请求
|
|
|
func (hc *HttpClient) Get(ctx context.Context, rawUrl string, headers map[string]string) ([]byte, int, error) {
|
|
|
req, err := http.NewRequestWithContext(ctx, http.MethodGet, rawUrl, nil)
|
|
|
if err != nil {
|
|
|
return nil, 0, err
|
|
|
}
|
|
|
for k, v := range headers {
|
|
|
req.Header.Set(k, v)
|
|
|
}
|
|
|
|
|
|
resp, err := hc.client.Do(req)
|
|
|
if err != nil {
|
|
|
return nil, 0, err
|
|
|
}
|
|
|
defer resp.Body.Close()
|
|
|
|
|
|
body, err := io.ReadAll(resp.Body)
|
|
|
return body, resp.StatusCode, err
|
|
|
}
|
|
|
|
|
|
// PostJSON 发送 POST 请求,Body 是 JSON
|
|
|
func (hc *HttpClient) PostJSON(ctx context.Context, rawUrl string, data interface{}, headers map[string]string) ([]byte, int, error) {
|
|
|
bodyBytes, err := json.Marshal(data)
|
|
|
if err != nil {
|
|
|
return nil, 0, err
|
|
|
}
|
|
|
|
|
|
req, err := http.NewRequestWithContext(ctx, http.MethodPost, rawUrl, bytes.NewReader(bodyBytes))
|
|
|
if err != nil {
|
|
|
return nil, 0, err
|
|
|
}
|
|
|
req.Header.Set("Content-Type", "application/json")
|
|
|
for k, v := range headers {
|
|
|
req.Header.Set(k, v)
|
|
|
}
|
|
|
|
|
|
resp, err := hc.client.Do(req)
|
|
|
if err != nil {
|
|
|
return nil, 0, err
|
|
|
}
|
|
|
defer resp.Body.Close()
|
|
|
|
|
|
body, err := io.ReadAll(resp.Body)
|
|
|
return body, resp.StatusCode, err
|
|
|
}
|
|
|
|
|
|
// PostForm 发送 POST 表单请求
|
|
|
func (hc *HttpClient) PostForm(ctx context.Context, rawUrl string, formData map[string]string, headers map[string]string) ([]byte, int, error) {
|
|
|
data := url.Values{}
|
|
|
for k, v := range formData {
|
|
|
data.Set(k, v)
|
|
|
}
|
|
|
|
|
|
req, err := http.NewRequestWithContext(ctx, http.MethodPost, rawUrl, strings.NewReader(data.Encode()))
|
|
|
if err != nil {
|
|
|
return nil, 0, err
|
|
|
}
|
|
|
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
|
|
for k, v := range headers {
|
|
|
req.Header.Set(k, v)
|
|
|
}
|
|
|
|
|
|
resp, err := hc.client.Do(req)
|
|
|
if err != nil {
|
|
|
return nil, 0, err
|
|
|
}
|
|
|
defer resp.Body.Close()
|
|
|
|
|
|
body, err := io.ReadAll(resp.Body)
|
|
|
return body, resp.StatusCode, err
|
|
|
}
|
|
|
|
|
|
var (
|
|
|
defaultClient *HttpClient
|
|
|
once sync.Once
|
|
|
)
|
|
|
|
|
|
func GetDefaultClient() *HttpClient {
|
|
|
once.Do(func() {
|
|
|
defaultClient = NewHttpClient(10 * time.Second)
|
|
|
})
|
|
|
return defaultClient
|
|
|
}
|