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
This commit is contained in:
wood chen 2025-02-17 17:28:25 +08:00
parent 00f4605e1c
commit 429664b598
2 changed files with 38 additions and 8 deletions

View File

@ -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))
}
}
// 记录统计信息

View File

@ -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 {