171 lines
5.3 KiB
Go
171 lines
5.3 KiB
Go
package main
|
||
|
||
import (
|
||
"bytes"
|
||
"context"
|
||
"encoding/json"
|
||
"fmt"
|
||
"io/ioutil"
|
||
"net/http"
|
||
"strings"
|
||
"time"
|
||
)
|
||
|
||
// HTTPClient HTTP客户端结构体,用于替代原来的IPC客户端
|
||
type HTTPClient struct {
|
||
httpClient *http.Client
|
||
serverURL string
|
||
ctx context.Context
|
||
}
|
||
|
||
// NewHTTPClient 创建一个新的HTTP客户端
|
||
func NewHTTPClient(ctx context.Context, port int) *HTTPClient {
|
||
return &HTTPClient{
|
||
httpClient: &http.Client{
|
||
Timeout: 30 * time.Second, // 设置请求超时时间
|
||
},
|
||
serverURL: fmt.Sprintf("http://localhost:%d", port),
|
||
ctx: ctx,
|
||
}
|
||
}
|
||
|
||
// SendWxWorkData 向辅助程序的HTTP服务发送企业微信数据
|
||
func (c *HTTPClient) SendWxWorkData(clientId string, jsonData string) (bool, error) {
|
||
// 解析JSON数据以获取消息类型
|
||
var message map[string]interface{}
|
||
timestamp1 := time.Now().Format("2006-01-02 15:04:05.000")
|
||
globalLogger.Info("[进入HTTP SendWxWorkData请求] 时间: %s", timestamp1)
|
||
|
||
messageTypeValue := -1
|
||
if err := json.Unmarshal([]byte(jsonData), &message); err != nil {
|
||
globalLogger.Warn("解析JSON数据失败: %v, 原始数据: %s", err, jsonData)
|
||
} else {
|
||
// 获取消息类型
|
||
messageType, typeExists := message["type"]
|
||
if typeExists {
|
||
typeValue, ok := messageType.(float64) // JSON解析数字默认为float64
|
||
if ok {
|
||
messageTypeValue = int(typeValue)
|
||
}
|
||
}
|
||
}
|
||
|
||
// 记录所有请求的日志
|
||
timestamp := time.Now().Format("2006-01-02 15:04:05.000")
|
||
globalLogger.Info("[HTTPSendWxWorkData请求] 时间: %s, 客户端ID: %s, 消息类型: %d, 数据: %s",
|
||
timestamp, clientId, messageTypeValue, jsonData)
|
||
|
||
// 创建请求体
|
||
requestBody := map[string]interface{}{
|
||
"clientId": clientId,
|
||
"data": jsonData,
|
||
}
|
||
|
||
// 序列化请求体
|
||
jsonBytes, err := json.Marshal(requestBody)
|
||
if err != nil {
|
||
globalLogger.Error("序列化请求体失败: %v", err)
|
||
return false, err
|
||
}
|
||
|
||
// 创建HTTP请求
|
||
url := fmt.Sprintf("%s/api/send-wxwork-data", c.serverURL)
|
||
req, err := http.NewRequestWithContext(c.ctx, "POST", url, bytes.NewBuffer(jsonBytes))
|
||
if err != nil {
|
||
globalLogger.Error("创建HTTP请求失败: %v", err)
|
||
return false, err
|
||
}
|
||
|
||
// 设置请求头
|
||
req.Header.Set("Content-Type", "application/json")
|
||
|
||
// 发送请求 - 添加重试机制
|
||
timestamp2 := time.Now().Format("2006-01-02 15:04:05.000")
|
||
globalLogger.Info("[发送HTTP请求] 时间: %s, URL: %s", timestamp2, url)
|
||
|
||
// 设置重试参数
|
||
maxRetries := 3
|
||
retryInterval := 1 * time.Second
|
||
var lastErr error
|
||
|
||
for i := 0; i < maxRetries; i++ {
|
||
resp, err := c.httpClient.Do(req)
|
||
if err == nil {
|
||
defer resp.Body.Close()
|
||
return handleHTTPResponse(resp, messageTypeValue, clientId)
|
||
}
|
||
|
||
lastErr = err
|
||
globalLogger.Error("HTTP请求失败 (尝试 %d/%d): %v, URL: %s", i+1, maxRetries, err, url)
|
||
|
||
// 如果是连接被拒绝的错误,可能是辅助程序刚启动还未准备好,尝试重启辅助程序
|
||
errMsg := err.Error()
|
||
if strings.Contains(errMsg, "connectex: No connection could be made") ||
|
||
strings.Contains(errMsg, "connection refused") {
|
||
globalLogger.Info("尝试重新启动辅助程序...")
|
||
// 调用外部的startHelperProgram函数
|
||
// 注意:这里需要在main.go中将startHelperProgram声明为可导出的函数
|
||
// 或者通过其他方式实现辅助程序的重启
|
||
}
|
||
|
||
// 如果不是最后一次尝试,等待一段时间后重试
|
||
if i < maxRetries-1 {
|
||
globalLogger.Info("%d秒后重试...", retryInterval/time.Second)
|
||
time.Sleep(retryInterval)
|
||
}
|
||
}
|
||
|
||
// 所有重试都失败
|
||
globalLogger.Error("HTTP请求失败,已尝试所有重试: %v", lastErr)
|
||
return false, lastErr
|
||
}
|
||
|
||
// handleHTTPResponse 处理HTTP响应
|
||
func handleHTTPResponse(resp *http.Response, messageTypeValue int, clientId string) (bool, error) {
|
||
timestamp := time.Now().Format("2006-01-02 15:04:05.000")
|
||
globalLogger.Info("[HTTP响应接收] 时间: %s, 客户端ID: %s, 状态码: %d", timestamp, clientId, resp.StatusCode)
|
||
|
||
// 读取响应体
|
||
body, err := ioutil.ReadAll(resp.Body)
|
||
if err != nil {
|
||
globalLogger.Error("读取HTTP响应体失败: %v", err)
|
||
return false, err
|
||
}
|
||
|
||
globalLogger.Info("[HTTP响应内容] 长度: %d 字节, 内容: %s", len(body), string(body))
|
||
|
||
// 解析响应体
|
||
var result map[string]interface{}
|
||
if err := json.Unmarshal(body, &result); err != nil {
|
||
globalLogger.Error("解析HTTP响应体失败: %v, 响应内容: %s", err, string(body))
|
||
return false, err
|
||
}
|
||
|
||
globalLogger.Info("[HTTP响应解析] 成功, 解析结果: %v", result)
|
||
|
||
// 获取success字段
|
||
successValue, successExists := result["success"]
|
||
if !successExists {
|
||
globalLogger.Error("HTTP响应中缺少success字段")
|
||
return false, fmt.Errorf("返回结果格式错误")
|
||
}
|
||
|
||
success, ok := successValue.(bool)
|
||
if !ok {
|
||
globalLogger.Error("HTTP响应的success字段类型错误: %T", successValue)
|
||
return false, fmt.Errorf("返回结果字段类型错误")
|
||
}
|
||
|
||
// 检查是否包含data字段
|
||
if data, exists := result["data"]; exists {
|
||
globalLogger.Info("[HTTP响应数据] 客户端ID: %s, 数据: %v", clientId, data)
|
||
}
|
||
|
||
// 记录返回日志(如果是特定类型的消息)
|
||
timestampReturn := time.Now().Format("2006-01-02 15:04:05.000")
|
||
globalLogger.Info("[HTTPSendWxWorkData返回] 时间: %s, 客户端ID: %s, 消息类型: %d, 成功: %v",
|
||
timestampReturn, clientId, messageTypeValue, success)
|
||
|
||
return success, nil
|
||
}
|