测试代理是否可用
This commit is contained in:
148
core/check.go
148
core/check.go
@@ -9,116 +9,92 @@ import (
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"regexp"
|
||||
"time"
|
||||
)
|
||||
|
||||
//for _, node := range global.Conf.Nodes {
|
||||
//for _, port := range node.Ports {
|
||||
//node.Port = port
|
||||
//success, message := core.CheckHttpsProxy(&node, global.Conf.TargetURL)
|
||||
//if success {
|
||||
//fmt.Printf("代理 %s 端口 %d 可用.\n", node.Addr, node.Port)
|
||||
//} else {
|
||||
//fmt.Printf("代理 %s 端口 %d 不可用: %s\n", node.Addr, node.Port, message)
|
||||
//}
|
||||
//}
|
||||
//}
|
||||
|
||||
// CheckHttpsProxy 检测代理是否可用的函数
|
||||
func CheckHttpsProxy(node *common.Node, targetURL string) (bool, string) {
|
||||
proxyURL, err := Node2ProxyURL(node)
|
||||
if err != nil {
|
||||
fmt.Printf("节点转换代理URL失败: %v\n", err)
|
||||
return false, err.Error()
|
||||
return false, fmt.Sprintf("节点转换代理URL失败: %v", err)
|
||||
}
|
||||
// 解析代理 URL
|
||||
|
||||
proxy, err := url.Parse(proxyURL)
|
||||
if err != nil {
|
||||
fmt.Printf("代理解析失败: %v\n", err)
|
||||
return false, err.Error()
|
||||
return false, fmt.Sprintf("代理解析失败: %v", err)
|
||||
}
|
||||
|
||||
// 创建自定义 Transport,用于调试代理信息
|
||||
transport := &http.Transport{
|
||||
Proxy: http.ProxyURL(proxy), // 设置代理
|
||||
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||
if global.Conf.Debug {
|
||||
fmt.Printf("网络拨号: %s, 地址: %s\n", network, addr)
|
||||
}
|
||||
conn, err := net.Dial(network, addr)
|
||||
if err != nil {
|
||||
fmt.Printf("网络拨号失败: %v\n", err)
|
||||
}
|
||||
return conn, err
|
||||
},
|
||||
}
|
||||
|
||||
// 创建 HTTP 客户端并使用自定义 Transport
|
||||
client := &http.Client{
|
||||
Transport: transport,
|
||||
Timeout: 30 * time.Second, // 设置超时时间
|
||||
}
|
||||
client := createHTTPClient(proxy)
|
||||
|
||||
if global.Conf.Debug {
|
||||
fmt.Printf("发送请求到: %s 使用代理: %s\n", targetURL, proxyURL)
|
||||
}
|
||||
// 发起 GET 请求
|
||||
|
||||
// 记录请求开始时间
|
||||
startTime := time.Now()
|
||||
|
||||
resp, err := client.Get(targetURL)
|
||||
if err != nil {
|
||||
fmt.Printf("通过代理发送请求失败 %s: %v\n", proxyURL, err)
|
||||
return false, err.Error()
|
||||
return false, fmt.Sprintf("通过代理发送请求失败 %s: %v", proxyURL, err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if global.Conf.Debug {
|
||||
// 打印响应状态
|
||||
fmt.Printf("Response 状态码: %s\n", resp.Status)
|
||||
// 打印响应头
|
||||
fmt.Printf("Response 响应头: \n")
|
||||
for key, value := range resp.Header {
|
||||
fmt.Printf("\t%s: %s\n", key, value)
|
||||
}
|
||||
// 计算延迟(转换为毫秒)
|
||||
latencyMs := time.Since(startTime).Milliseconds()
|
||||
|
||||
// 读取响应体
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return false, fmt.Sprintf("读取响应失败: %v", err)
|
||||
}
|
||||
|
||||
// 检查网页标题
|
||||
title := extractTitle(string(body))
|
||||
if title == "" {
|
||||
return false, "未找到网页标题"
|
||||
}
|
||||
|
||||
if global.Conf.Debug {
|
||||
// 创建一个缓冲区,用于分块读取响应体
|
||||
buffer := make([]byte, 4096) // 4KB 缓冲区
|
||||
fmt.Printf("分块读取响应正文:\n")
|
||||
// 分块读取响应体
|
||||
for {
|
||||
n, err := resp.Body.Read(buffer)
|
||||
if err == io.EOF {
|
||||
fmt.Println("响应正文读取完毕.")
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
fmt.Printf("响应正文读取错误: %v\n", err)
|
||||
return false, err.Error()
|
||||
}
|
||||
// 打印每次读取的内容
|
||||
fmt.Printf("%s\n", string(buffer[:n])) // 不打印内容,只检测可用性
|
||||
}
|
||||
printResponseDetails(resp)
|
||||
fmt.Printf("网页标题: %s\n", title)
|
||||
}
|
||||
|
||||
// 检查是否发生了重定向
|
||||
if resp.StatusCode == 301 || resp.StatusCode == 302 {
|
||||
redirectURL := resp.Header.Get("Location")
|
||||
if global.Conf.Debug {
|
||||
fmt.Printf("重定向到: %s\n", redirectURL)
|
||||
}
|
||||
// 如果需要处理重定向,可以发起新的请求
|
||||
newResp, err := client.Get(redirectURL)
|
||||
if err != nil {
|
||||
fmt.Printf("重定向失败: %v\n", err)
|
||||
return false, err.Error()
|
||||
}
|
||||
defer newResp.Body.Close()
|
||||
|
||||
// 打印重定向后的响应状态
|
||||
if global.Conf.Debug {
|
||||
fmt.Printf("重定向响应状态: %s\n", newResp.Status)
|
||||
}
|
||||
}
|
||||
|
||||
return true, "代理可用"
|
||||
return true, fmt.Sprintf("标题: %s, 延迟: %dms", title, latencyMs)
|
||||
}
|
||||
|
||||
// extractTitle 从HTML内容中提取标题
|
||||
func extractTitle(html string) string {
|
||||
// 匹配 <title> 标签内容,支持多行匹配
|
||||
titleRegex := regexp.MustCompile(`(?i)<title.*?>(.*?)</title>`)
|
||||
matches := titleRegex.FindStringSubmatch(html)
|
||||
if len(matches) > 1 {
|
||||
return matches[1]
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// createHTTPClient 创建一个带有代理设置的 HTTP 客户端
|
||||
func createHTTPClient(proxy *url.URL) *http.Client {
|
||||
return &http.Client{
|
||||
Transport: &http.Transport{
|
||||
Proxy: http.ProxyURL(proxy),
|
||||
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||
if global.Conf.Debug {
|
||||
fmt.Printf("网络拨号: %s, 地址: %s\n", network, addr)
|
||||
}
|
||||
return net.Dial(network, addr)
|
||||
},
|
||||
},
|
||||
Timeout: 30 * time.Second,
|
||||
}
|
||||
}
|
||||
|
||||
// printResponseDetails 打印响应的详细信息
|
||||
func printResponseDetails(resp *http.Response) {
|
||||
fmt.Printf("Response 状态码: %s\n", resp.Status)
|
||||
fmt.Printf("Response 响应头: \n")
|
||||
for key, value := range resp.Header {
|
||||
fmt.Printf("\t%s: %s\n", key, value)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user