refactor: 优化 HTTP 请求处理逻辑

- 改进了对重定向的处理,确保在 CheckRedirect 返回 ErrUseLastResponse 时能够正确处理响应。
- 移除了不必要的空行以提升代码可读性。
- 增强了错误处理逻辑,确保在没有响应的情况下返回适当的错误信息。
This commit is contained in:
2025-12-17 20:08:31 +08:00
parent 4a2532a83b
commit f01547df35

View File

@@ -44,12 +44,12 @@ func (t *timingTransport) RoundTrip(req *http.Request) (*http.Response, error) {
port = "80" port = "80"
} }
} }
// DNS查询时间 // DNS查询时间
dnsStart := time.Now() dnsStart := time.Now()
ips, err := net.LookupIP(host) ips, err := net.LookupIP(host)
dnsTime := time.Since(dnsStart) dnsTime := time.Since(dnsStart)
t.mu.Lock() t.mu.Lock()
t.nameLookup = dnsTime t.nameLookup = dnsTime
if len(ips) > 0 { if len(ips) > 0 {
@@ -65,11 +65,11 @@ func (t *timingTransport) RoundTrip(req *http.Request) (*http.Response, error) {
} }
} }
t.mu.Unlock() t.mu.Unlock()
if err != nil { if err != nil {
return nil, err return nil, err
} }
// TCP连接时间如果已知IP // TCP连接时间如果已知IP
var connectTime time.Duration var connectTime time.Duration
if t.primaryIP != "" { if t.primaryIP != "" {
@@ -80,13 +80,13 @@ func (t *timingTransport) RoundTrip(req *http.Request) (*http.Response, error) {
conn.Close() conn.Close()
} }
} }
// 执行HTTP请求 // 执行HTTP请求
httpStart := time.Now() httpStart := time.Now()
resp, err := t.transport.RoundTrip(req) resp, err := t.transport.RoundTrip(req)
httpTime := time.Since(httpStart) httpTime := time.Since(httpStart)
totalTime := time.Since(start) totalTime := time.Since(start)
t.mu.Lock() t.mu.Lock()
if connectTime > 0 { if connectTime > 0 {
t.connect = connectTime t.connect = connectTime
@@ -103,7 +103,7 @@ func (t *timingTransport) RoundTrip(req *http.Request) (*http.Response, error) {
} }
} }
t.mu.Unlock() t.mu.Unlock()
return resp, err return resp, err
} }
@@ -139,17 +139,14 @@ func handleGet(c *gin.Context, urlStr string, params map[string]interface{}) {
// 创建自定义Transport用于时间跟踪 // 创建自定义Transport用于时间跟踪
timingTransport := newTimingTransport() timingTransport := newTimingTransport()
// 创建HTTP客户端 // 创建HTTP客户端
client := &http.Client{ client := &http.Client{
Transport: timingTransport, Transport: timingTransport,
Timeout: 15 * time.Second, Timeout: 15 * time.Second,
CheckRedirect: func(req *http.Request, via []*http.Request) error { CheckRedirect: func(req *http.Request, via []*http.Request) error {
// 跟随重定向,最多20次 // 跟随重定向,返回第一个状态码和 header
if len(via) >= 20 { return http.ErrUseLastResponse
return fmt.Errorf("重定向次数过多")
}
return nil
}, },
} }
@@ -181,8 +178,11 @@ func handleGet(c *gin.Context, urlStr string, params map[string]interface{}) {
// 执行请求 // 执行请求
startTime := time.Now() startTime := time.Now()
resp, err := client.Do(req) resp, err := client.Do(req)
if err != nil {
// 错误处理 // 处理重定向错误:当 CheckRedirect 返回 ErrUseLastResponse 时,
// client.Do 会返回响应和错误,但响应仍然有效(包含重定向状态码和 header
if err != nil && resp == nil {
// 真正的错误,没有响应
errMsg := err.Error() errMsg := err.Error()
if strings.Contains(errMsg, "no such host") { if strings.Contains(errMsg, "no such host") {
result["ip"] = "域名无法解析" result["ip"] = "域名无法解析"
@@ -204,7 +204,24 @@ func handleGet(c *gin.Context, urlStr string, params map[string]interface{}) {
c.JSON(200, result) c.JSON(200, result)
return return
} }
defer resp.Body.Close()
// 如果有响应(包括重定向响应),继续处理
if resp != nil {
defer resp.Body.Close()
} else {
// 没有响应也没有错误,不应该发生
result["error"] = "未知错误"
result["ip"] = "访问失败"
result["totaltime"] = "*"
result["downtime"] = "*"
result["downsize"] = "*"
result["downspeed"] = "*"
result["firstbytetime"] = "*"
result["conntime"] = "*"
result["size"] = "*"
c.JSON(200, result)
return
}
// 获取时间信息 // 获取时间信息
timingTransport.mu.Lock() timingTransport.mu.Lock()
@@ -237,19 +254,19 @@ func handleGet(c *gin.Context, urlStr string, params map[string]interface{}) {
bodyReader := io.LimitReader(resp.Body, 1024*1024) // 限制1MB bodyReader := io.LimitReader(resp.Body, 1024*1024) // 限制1MB
bodyStartTime := time.Now() bodyStartTime := time.Now()
body, err := io.ReadAll(bodyReader) body, err := io.ReadAll(bodyReader)
bodyReadTime := time.Now().Sub(bodyStartTime) bodyReadTime := time.Since(bodyStartTime)
if err != nil && err != io.EOF { if err != nil && err != io.EOF {
result["error"] = err.Error() result["error"] = err.Error()
} }
downloadSize := int64(len(body)) downloadSize := int64(len(body))
statusCode := resp.StatusCode statusCode := resp.StatusCode
// 如果首字节时间为0使用连接时间 // 如果首字节时间为0使用连接时间
if firstByteTime == 0 { if firstByteTime == 0 {
firstByteTime = connectTime firstByteTime = connectTime
} }
// 总时间 = 实际请求时间 // 总时间 = 实际请求时间
if totalTime == 0 { if totalTime == 0 {
totalTime = time.Since(startTime) totalTime = time.Since(startTime)
@@ -327,16 +344,14 @@ func handlePost(c *gin.Context, urlStr string, params map[string]interface{}) {
// 创建自定义Transport用于时间跟踪 // 创建自定义Transport用于时间跟踪
timingTransport := newTimingTransport() timingTransport := newTimingTransport()
// 创建HTTP客户端 // 创建HTTP客户端
client := &http.Client{ client := &http.Client{
Transport: timingTransport, Transport: timingTransport,
Timeout: 15 * time.Second, Timeout: 15 * time.Second,
CheckRedirect: func(req *http.Request, via []*http.Request) error { CheckRedirect: func(req *http.Request, via []*http.Request) error {
if len(via) >= 20 { // 不跟随重定向,返回第一个状态码和 header
return fmt.Errorf("重定向次数过多") return http.ErrUseLastResponse
}
return nil
}, },
} }
@@ -363,7 +378,11 @@ func handlePost(c *gin.Context, urlStr string, params map[string]interface{}) {
// 执行请求 // 执行请求
startTime := time.Now() startTime := time.Now()
resp, err := client.Do(req) resp, err := client.Do(req)
if err != nil {
// 处理重定向错误:当 CheckRedirect 返回 ErrUseLastResponse 时,
// client.Do 会返回响应和错误,但响应仍然有效(包含重定向状态码和 header
if err != nil && resp == nil {
// 真正的错误,没有响应
errMsg := err.Error() errMsg := err.Error()
if strings.Contains(errMsg, "no such host") { if strings.Contains(errMsg, "no such host") {
result["ip"] = "域名无法解析" result["ip"] = "域名无法解析"
@@ -385,7 +404,24 @@ func handlePost(c *gin.Context, urlStr string, params map[string]interface{}) {
c.JSON(200, result) c.JSON(200, result)
return return
} }
defer resp.Body.Close()
// 如果有响应(包括重定向响应),继续处理
if resp != nil {
defer resp.Body.Close()
} else {
// 没有响应也没有错误,不应该发生
result["error"] = "未知错误"
result["ip"] = "访问失败"
result["totaltime"] = "*"
result["downtime"] = "*"
result["downsize"] = "*"
result["downspeed"] = "*"
result["firstbytetime"] = "*"
result["conntime"] = "*"
result["size"] = "*"
c.JSON(200, result)
return
}
// 获取时间信息 // 获取时间信息
timingTransport.mu.Lock() timingTransport.mu.Lock()
@@ -425,12 +461,12 @@ func handlePost(c *gin.Context, urlStr string, params map[string]interface{}) {
downloadSize := int64(len(body)) downloadSize := int64(len(body))
statusCode := resp.StatusCode statusCode := resp.StatusCode
// 如果首字节时间为0使用连接时间 // 如果首字节时间为0使用连接时间
if firstByteTime == 0 { if firstByteTime == 0 {
firstByteTime = connectTime firstByteTime = connectTime
} }
// 总时间 = 实际请求时间 // 总时间 = 实际请求时间
if totalTime == 0 { if totalTime == 0 {
totalTime = time.Since(startTime) totalTime = time.Since(startTime)