fix: 修复可能存在的重复请求问题

This commit is contained in:
spiritlhl 2025-04-11 14:07:13 +00:00
parent 2adf709e63
commit 0c7727e3dc

View File

@ -1,6 +1,7 @@
package backtrace package backtrace
import ( import (
"encoding/json"
"fmt" "fmt"
"io" "io"
"strings" "strings"
@ -8,7 +9,6 @@ import (
"github.com/imroc/req/v3" "github.com/imroc/req/v3"
"github.com/oneclickvirt/backtrace/model" "github.com/oneclickvirt/backtrace/model"
. "github.com/oneclickvirt/defaultset" . "github.com/oneclickvirt/defaultset"
) )
@ -17,6 +17,19 @@ type Result struct {
s string s string
} }
// IcmpTarget 定义ICMP目标的JSON结构
type IcmpTarget struct {
Province string `json:"province"`
ISP string `json:"isp"`
IPVersion string `json:"ip_version"`
IPs string `json:"ips"` // IP列表以逗号分隔
}
// 用于缓存ICMP数据的全局变量
var cachedIcmpData string
var cachedIcmpDataFetchTime time.Time
var parsedIcmpTargets []IcmpTarget
func removeDuplicates(elements []string) []string { func removeDuplicates(elements []string) []string {
encountered := map[string]bool{} // 用于存储已经遇到的元素 encountered := map[string]bool{} // 用于存储已经遇到的元素
result := []string{} // 存储去重后的结果 result := []string{} // 存储去重后的结果
@ -34,7 +47,7 @@ func removeDuplicates(elements []string) []string {
// getData 获取目标地址的文本内容 // getData 获取目标地址的文本内容
func getData(endpoint string) string { func getData(endpoint string) string {
client := req.C() client := req.C()
client.SetTimeout(10 * time.Second) client.SetTimeout(6 * time.Second)
client.R(). client.R().
SetRetryCount(2). SetRetryCount(2).
SetRetryBackoffInterval(1*time.Second, 5*time.Second). SetRetryBackoffInterval(1*time.Second, 5*time.Second).
@ -66,15 +79,42 @@ func getData(endpoint string) string {
return "" return ""
} }
// tryAlternativeIPs 从IcmpTargets获取备选IP地址 // parseIcmpTargets 解析ICMP目标数据
func tryAlternativeIPs(targetName string, ipVersion string) []string { func parseIcmpTargets(jsonData string) []IcmpTarget {
jsonData := getData(model.IcmpTargets) // 确保JSON数据格式正确如果返回的是数组需要添加[和]
if jsonData == "" { if !strings.HasPrefix(jsonData, "[") {
jsonData = "[" + jsonData + "]"
}
// 如果JSON数据中的对象没有正确用逗号分隔修复它
jsonData = strings.ReplaceAll(jsonData, "}{", "},{")
var targets []IcmpTarget
err := json.Unmarshal([]byte(jsonData), &targets)
if err != nil {
if model.EnableLoger {
Logger.Error(fmt.Sprintf("Failed to parse ICMP targets: %v", err))
}
return nil
}
return targets
}
// tryAlternativeIPs 从IcmpTargets获取备选IP地址
func tryAlternativeIPs(targetName string, ipVersion string) []string {
if cachedIcmpData == "" || parsedIcmpTargets == nil || time.Since(cachedIcmpDataFetchTime) > time.Hour {
cachedIcmpData = getData(model.IcmpTargets)
cachedIcmpDataFetchTime = time.Now()
if cachedIcmpData != "" {
parsedIcmpTargets = parseIcmpTargets(cachedIcmpData)
}
if model.EnableLoger {
Logger.Info("Fetched new ICMP targets data")
}
}
if parsedIcmpTargets == nil || len(parsedIcmpTargets) == 0 {
return nil return nil
} }
// 简单解析JSON提取省份和ISP信息
var targetProvince, targetISP string
// 从目标名称中提取省份和ISP信息 // 从目标名称中提取省份和ISP信息
var targetProvince, targetISP string
if strings.Contains(targetName, "北京") { if strings.Contains(targetName, "北京") {
targetProvince = "北京" targetProvince = "北京"
} else if strings.Contains(targetName, "上海") { } else if strings.Contains(targetName, "上海") {
@ -95,30 +135,28 @@ func tryAlternativeIPs(targetName string, ipVersion string) []string {
if targetProvince == "" || targetISP == "" { if targetProvince == "" || targetISP == "" {
return nil return nil
} }
// 解析JSON数据寻找匹配的记录 // 查找匹配条件的目标
var result []string var result []string
for _, line := range strings.Split(jsonData, "},{") { for _, target := range parsedIcmpTargets {
if strings.Contains(line, "\"province\":\""+targetProvince+"省\"") && // 检查省份是否匹配(可能带有"省"字或不带)
strings.Contains(line, "\"isp\":\""+targetISP+"\"") && provinceMatch := (target.Province == targetProvince) || (target.Province == targetProvince+"省")
strings.Contains(line, "\"ip_version\":\""+ipVersion+"\"") { // 检查ISP和IP版本是否匹配
// 提取IP列表 if provinceMatch && target.ISP == targetISP && target.IPVersion == ipVersion {
ipsStart := strings.Index(line, "\"ips\":\"") + 7 // 解析IP列表
if ipsStart > 7 { if target.IPs != "" {
ipsEnd := strings.Index(line[ipsStart:], "\"") ips := strings.Split(target.IPs, ",")
if ipsEnd > 0 { // 最多返回3个IP地址
ipsList := line[ipsStart : ipsStart+ipsEnd] count := 0
ips := strings.Split(ipsList, ",") for _, ip := range ips {
// 最多返回3个不重复的IP地址 if ip != "" {
count := 0 result = append(result, strings.TrimSpace(ip))
for _, ip := range ips { count++
if ip != "" { if count >= 3 {
result = append(result, ip) break
count++
if count >= 3 {
break
}
} }
} }
}
if len(result) > 0 {
return result return result
} }
} }