refactor: 优化 HTTP 请求处理逻辑
- 改进了对重定向的处理,确保在 CheckRedirect 返回 ErrUseLastResponse 时能够正确处理响应。 - 移除了不必要的空行以提升代码可读性。 - 增强了错误处理逻辑,确保在没有响应的情况下返回适当的错误信息。
This commit is contained in:
@@ -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)
|
||||||
|
|||||||
Reference in New Issue
Block a user