From 429664b598c11bcf4d73f5cb93c1d8d730746a5d Mon Sep 17 00:00:00 2001 From: wood chen Date: Mon, 17 Feb 2025 17:28:25 +0800 Subject: [PATCH] feat(routing): Add target URL accessibility check for extension mapping - Implement `isTargetAccessible` function to validate alternative target URLs - Add fallback mechanism when alternative target is not reachable - Enhance routing logic to prevent potential broken redirects - Log detailed information about routing decisions and accessibility checks --- internal/middleware/fixed_path_proxy.go | 11 ++++---- internal/utils/utils.go | 35 ++++++++++++++++++++++--- 2 files changed, 38 insertions(+), 8 deletions(-) diff --git a/internal/middleware/fixed_path_proxy.go b/internal/middleware/fixed_path_proxy.go index 3054041..a649e19 100644 --- a/internal/middleware/fixed_path_proxy.go +++ b/internal/middleware/fixed_path_proxy.go @@ -119,14 +119,15 @@ func FixedPathProxyMiddleware(configs []config.FixedPathConfig) func(http.Handle } } else { written, err = io.Copy(w, resp.Body) + if err != nil && !isConnectionClosed(err) { + log.Printf("[Fixed] ERR %s %s -> write error (%s) from %s", r.Method, r.URL.Path, utils.GetClientIP(r), utils.GetRequestSource(r)) + } } } else { written, err = io.Copy(w, resp.Body) - } - - // 写入响应错误处理 - if err != nil && !isConnectionClosed(err) { - log.Printf("[Fixed] ERR %s %s -> write error (%s) from %s", r.Method, r.URL.Path, utils.GetClientIP(r), utils.GetRequestSource(r)) + if err != nil && !isConnectionClosed(err) { + log.Printf("[Fixed] ERR %s %s -> write error (%s) from %s", r.Method, r.URL.Path, utils.GetClientIP(r), utils.GetRequestSource(r)) + } } // 记录统计信息 diff --git a/internal/utils/utils.go b/internal/utils/utils.go index d0fecf8..895cca0 100644 --- a/internal/utils/utils.go +++ b/internal/utils/utils.go @@ -205,9 +205,15 @@ func GetTargetURL(client *http.Client, r *http.Request, pathConfig config.PathCo // 只有当文件大于阈值时才使用扩展名映射的目标 if contentLength > threshold { - log.Printf("[Route] %s -> %s (size: %s > %s)", - path, altTarget, FormatBytes(contentLength), FormatBytes(threshold)) - targetBase = altTarget + // 检查扩展名映射的目标是否可访问 + if isTargetAccessible(client, altTarget+path) { + log.Printf("[Route] %s -> %s (size: %s > %s)", + path, altTarget, FormatBytes(contentLength), FormatBytes(threshold)) + targetBase = altTarget + } else { + log.Printf("[Route] %s -> %s (fallback: alternative target not accessible)", + path, targetBase) + } } else { log.Printf("[Route] %s -> %s (size: %s <= %s)", path, targetBase, FormatBytes(contentLength), FormatBytes(threshold)) @@ -228,6 +234,29 @@ func GetTargetURL(client *http.Client, r *http.Request, pathConfig config.PathCo return targetBase } +// isTargetAccessible 检查目标URL是否可访问 +func isTargetAccessible(client *http.Client, url string) bool { + req, err := http.NewRequest("HEAD", url, nil) + if err != nil { + log.Printf("[Check] Failed to create request for %s: %v", url, err) + return false + } + + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + req = req.WithContext(ctx) + + resp, err := client.Do(req) + if err != nil { + log.Printf("[Check] Failed to access %s: %v", url, err) + return false + } + defer resp.Body.Close() + + // 检查状态码是否表示成功 + return resp.StatusCode >= 200 && resp.StatusCode < 400 +} + // 检查是否命中缓存 func isCacheHit(url string) bool { if cache, ok := sizeCache.Load(url); ok {