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