101 lines
2.4 KiB
Go
101 lines
2.4 KiB
Go
package core
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"httppp/common"
|
|
"httppp/global"
|
|
"io"
|
|
"net"
|
|
"net/http"
|
|
"net/url"
|
|
"regexp"
|
|
"time"
|
|
)
|
|
|
|
// CheckHttpsProxy 检测代理是否可用的函数
|
|
func CheckHttpsProxy(node *common.Node, targetURL string) (bool, string) {
|
|
proxyURL, err := Node2ProxyURL(node)
|
|
if err != nil {
|
|
return false, fmt.Sprintf("节点转换代理URL失败: %v", err)
|
|
}
|
|
|
|
proxy, err := url.Parse(proxyURL)
|
|
if err != nil {
|
|
return false, fmt.Sprintf("代理解析失败: %v", err)
|
|
}
|
|
|
|
client := createHTTPClient(proxy)
|
|
|
|
if global.Conf.Debug {
|
|
fmt.Printf("发送请求到: %s 使用代理: %s\n", targetURL, proxyURL)
|
|
}
|
|
|
|
// 记录请求开始时间
|
|
startTime := time.Now()
|
|
|
|
resp, err := client.Get(targetURL)
|
|
if err != nil {
|
|
return false, fmt.Sprintf("通过代理发送请求失败 %s: %v", proxyURL, err)
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
// 计算延迟(转换为毫秒)
|
|
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 {
|
|
printResponseDetails(resp)
|
|
fmt.Printf("网页标题: %s\n", title)
|
|
}
|
|
|
|
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: global.Conf.ProxyCheck.Timeout,
|
|
}
|
|
}
|
|
|
|
// 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)
|
|
}
|
|
}
|