193 lines
4.5 KiB
Go
193 lines
4.5 KiB
Go
package common
|
|
|
|
import (
|
|
"bytes"
|
|
"compress/zlib"
|
|
"crypto/tls"
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
"os"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
// HTTPClient HTTP客户端
|
|
type HTTPClient struct {
|
|
client *http.Client
|
|
logger *Logger
|
|
}
|
|
|
|
// NewHTTPClient 创建新的HTTP客户端
|
|
func NewHTTPClient() *HTTPClient {
|
|
return &HTTPClient{
|
|
client: &http.Client{
|
|
Timeout: 30 * time.Second,
|
|
},
|
|
logger: NewLogger("http_utils", "INFO", ""),
|
|
}
|
|
}
|
|
|
|
// ClientResponse 客户端响应
|
|
type ClientResponse struct {
|
|
Status int
|
|
Content []byte
|
|
Headers http.Header
|
|
Cookies []*http.Cookie
|
|
Text string
|
|
}
|
|
|
|
// GetHeader 获取响应头(兼容方法)
|
|
func (r *ClientResponse) GetHeader(key string) string {
|
|
return r.Headers.Get(key)
|
|
}
|
|
|
|
// JSON 解析JSON响应
|
|
func (r *ClientResponse) JSON() (map[string]interface{}, error) {
|
|
var result map[string]interface{}
|
|
err := json.Unmarshal(r.Content, &result)
|
|
return result, err
|
|
}
|
|
|
|
// Request HTTP请求
|
|
func (h *HTTPClient) Request(url string, options map[string]interface{}) (*ClientResponse, error) {
|
|
// 获取请求方法
|
|
method := "GET"
|
|
if m, ok := options["method"].(string); ok {
|
|
method = strings.ToUpper(m)
|
|
}
|
|
|
|
// 获取请求头
|
|
headers := make(map[string]string)
|
|
if h, ok := options["headers"].(map[string]string); ok {
|
|
headers = h
|
|
}
|
|
|
|
// 设置默认User-Agent
|
|
if _, ok := headers["User-Agent"]; !ok {
|
|
headers["User-Agent"] = "okhttp/4.12.0"
|
|
}
|
|
|
|
// 获取请求体
|
|
var body io.Reader
|
|
if method == "POST" || method == "PUT" {
|
|
if b, ok := options["body"].(string); ok {
|
|
body = strings.NewReader(b)
|
|
} else if b, ok := options["body"].([]byte); ok {
|
|
body = bytes.NewReader(b)
|
|
} else if data, ok := options["data"].(string); ok {
|
|
body = strings.NewReader(data)
|
|
} else if data, ok := options["data"].([]byte); ok {
|
|
body = bytes.NewReader(data)
|
|
}
|
|
}
|
|
|
|
// 创建请求
|
|
req, err := http.NewRequest(method, url, body)
|
|
if err != nil {
|
|
h.logger.Error(fmt.Sprintf("Failed to create request: %v", err))
|
|
return nil, err
|
|
}
|
|
|
|
// 设置请求头
|
|
for k, v := range headers {
|
|
req.Header.Set(k, v)
|
|
}
|
|
|
|
// 打印请求信息
|
|
// h.logger.Info(fmt.Sprintf("=== HTTP 请求 ==="))
|
|
// h.logger.Info(fmt.Sprintf("方法: %s", method))
|
|
// h.logger.Info(fmt.Sprintf("URL: %s", url))
|
|
// h.logger.Info(fmt.Sprintf("请求头:"))
|
|
// for k, v := range req.Header {
|
|
// h.logger.Info(fmt.Sprintf(" %s: %s", k, strings.Join(v, ", ")))
|
|
// }
|
|
|
|
// 检查是否跳过SSL验证
|
|
skipSSL := os.Getenv("FQWEB_SKIP_SSL_VERIFY")
|
|
if skipSSL != "" && h.client.Transport == nil {
|
|
// 配置跳过SSL验证
|
|
transport := &http.Transport{
|
|
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
|
}
|
|
h.client.Transport = transport
|
|
h.logger.Warning("已启用SSL验证跳过模式")
|
|
}
|
|
|
|
// 发送请求
|
|
resp, err := h.client.Do(req)
|
|
if err != nil {
|
|
h.logger.Error(fmt.Sprintf("HTTP Request error: %v", err))
|
|
return nil, err
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
// 读取响应体
|
|
content, err := io.ReadAll(resp.Body)
|
|
if err != nil {
|
|
h.logger.Error(fmt.Sprintf("Failed to read response: %v", err))
|
|
return nil, err
|
|
}
|
|
|
|
// 处理zlib压缩
|
|
if len(content) > 2 && (content[0] == 0x78 && (content[1] == 0x9C || content[1] == 0x01)) {
|
|
reader, err := zlib.NewReader(bytes.NewReader(content))
|
|
if err == nil {
|
|
decompressed, err := io.ReadAll(reader)
|
|
reader.Close()
|
|
if err == nil {
|
|
content = decompressed
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
response := &ClientResponse{
|
|
Status: resp.StatusCode,
|
|
Content: content,
|
|
Headers: resp.Header,
|
|
Cookies: resp.Cookies(),
|
|
Text: string(content),
|
|
}
|
|
|
|
return response, nil
|
|
}
|
|
|
|
// Get GET请求
|
|
func (h *HTTPClient) Get(url string, headers map[string]string) (*ClientResponse, error) {
|
|
options := map[string]interface{}{
|
|
"method": "GET",
|
|
"headers": headers,
|
|
}
|
|
return h.Request(url, options)
|
|
}
|
|
|
|
// Post POST请求
|
|
func (h *HTTPClient) Post(url string, data interface{}, headers map[string]string) (*ClientResponse, error) {
|
|
options := map[string]interface{}{
|
|
"method": "POST",
|
|
"headers": headers,
|
|
"body": data,
|
|
}
|
|
return h.Request(url, options)
|
|
}
|
|
|
|
// ConvertDictToFormString 将字典转换为表单字符串
|
|
func ConvertDictToFormString(dict map[string]string) string {
|
|
parts := make([]string, 0, len(dict))
|
|
for k, v := range dict {
|
|
parts = append(parts, fmt.Sprintf("%s=%s", k, v))
|
|
}
|
|
return strings.Join(parts, "&")
|
|
}
|
|
|
|
// DefaultHTTPClient 默认HTTP客户端
|
|
var DefaultHTTPClient = NewHTTPClient()
|
|
|
|
// Request 全局请求函数
|
|
func Request(url string, options map[string]interface{}) (*ClientResponse, error) {
|
|
return DefaultHTTPClient.Request(url, options)
|
|
}
|
|
|