78 lines
1.9 KiB
Go
78 lines
1.9 KiB
Go
package proxyutil
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"net/http"
|
|
"net/url"
|
|
"time"
|
|
)
|
|
|
|
// ProxyTestResult 代理测试结果
|
|
type ProxyTestResult struct {
|
|
Success bool `json:"success"`
|
|
Location string `json:"location"`
|
|
IP string `json:"ip"`
|
|
Error string `json:"error,omitempty"`
|
|
}
|
|
|
|
// IPApiResponse ip-api.com 响应结构
|
|
type IPApiResponse struct {
|
|
Status string `json:"status"`
|
|
Country string `json:"country"`
|
|
CountryCode string `json:"countryCode"`
|
|
Region string `json:"region"`
|
|
RegionName string `json:"regionName"`
|
|
City string `json:"city"`
|
|
Query string `json:"query"`
|
|
Message string `json:"message"`
|
|
}
|
|
|
|
// TestProxy 测试代理连通性并获取归属地
|
|
func TestProxy(proxyURL string) (*ProxyTestResult, error) {
|
|
normalized, err := Normalize(proxyURL)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("代理地址格式错误: %w", err)
|
|
}
|
|
|
|
// 解析代理 URL
|
|
parsedProxy, err := url.Parse(normalized)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("解析代理错误: %w", err)
|
|
}
|
|
|
|
// 创建带代理的客户端
|
|
client := &http.Client{
|
|
Transport: &http.Transport{
|
|
Proxy: http.ProxyURL(parsedProxy),
|
|
},
|
|
Timeout: 15 * time.Second,
|
|
}
|
|
|
|
// 请求 IP 查询接口
|
|
resp, err := client.Get("http://ip-api.com/json/")
|
|
if err != nil {
|
|
return &ProxyTestResult{Success: false, Error: err.Error()}, nil
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
if resp.StatusCode != http.StatusOK {
|
|
return &ProxyTestResult{Success: false, Error: fmt.Sprintf("HTTP %d", resp.StatusCode)}, nil
|
|
}
|
|
|
|
var ipInfo IPApiResponse
|
|
if err := json.NewDecoder(resp.Body).Decode(&ipInfo); err != nil {
|
|
return &ProxyTestResult{Success: false, Error: "解析响应失败: " + err.Error()}, nil
|
|
}
|
|
|
|
if ipInfo.Status != "success" {
|
|
return &ProxyTestResult{Success: false, Error: "查询失败: " + ipInfo.Message}, nil
|
|
}
|
|
|
|
return &ProxyTestResult{
|
|
Success: true,
|
|
Location: ipInfo.CountryCode,
|
|
IP: ipInfo.Query,
|
|
}, nil
|
|
}
|