更新302跳转处理逻辑,添加客户端参数以优化规则选择,增强扩展名匹配和文件大小判断,确保代理请求的准确性和稳定性。

This commit is contained in:
wood chen 2025-06-02 06:12:36 +08:00
parent f229455db9
commit 4447e690db
3 changed files with 101 additions and 44 deletions

View File

@ -239,7 +239,7 @@ func (h *ProxyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
}
// 检查是否需要进行302跳转
if h.redirectHandler != nil && h.redirectHandler.HandleRedirect(w, r, pathConfig, decodedPath) {
if h.redirectHandler != nil && h.redirectHandler.HandleRedirect(w, r, pathConfig, decodedPath, h.client) {
// 如果进行了302跳转直接返回不继续处理
collector.RecordRequest(r.URL.Path, http.StatusFound, time.Since(start), 0, utils.GetClientIP(r), r)
return

View File

@ -19,9 +19,9 @@ func NewRedirectHandler() *RedirectHandler {
}
// HandleRedirect 处理302跳转请求
func (rh *RedirectHandler) HandleRedirect(w http.ResponseWriter, r *http.Request, pathConfig config.PathConfig, targetPath string) bool {
func (rh *RedirectHandler) HandleRedirect(w http.ResponseWriter, r *http.Request, pathConfig config.PathConfig, targetPath string, client *http.Client) bool {
// 检查是否需要进行302跳转
shouldRedirect, targetURL := rh.shouldRedirect(r, pathConfig, targetPath)
shouldRedirect, targetURL := rh.shouldRedirect(r, pathConfig, targetPath, client)
if !shouldRedirect {
return false
@ -33,17 +33,26 @@ func (rh *RedirectHandler) HandleRedirect(w http.ResponseWriter, r *http.Request
}
// shouldRedirect 判断是否应该进行302跳转并返回目标URL
func (rh *RedirectHandler) shouldRedirect(r *http.Request, pathConfig config.PathConfig, targetPath string) (bool, string) {
func (rh *RedirectHandler) shouldRedirect(r *http.Request, pathConfig config.PathConfig, targetPath string, client *http.Client) (bool, string) {
// 获取文件扩展名
ext := strings.ToLower(filepath.Ext(targetPath))
if ext != "" {
ext = ext[1:] // 去掉点号
}
// 首先检查扩展名规则是否有302跳转配置
// 使用统一的规则选择逻辑,考虑文件大小
if rule, found, _ := utils.SelectBestRule(client, pathConfig, targetPath); found && rule != nil && rule.RedirectMode {
// 使用选中规则的目标URL进行302跳转
targetURL := rh.buildTargetURL(rule.Target, targetPath, r.URL.RawQuery)
log.Printf("[Redirect] %s -> 使用选中规则进行302跳转: %s", targetPath, targetURL)
return true, targetURL
}
// 如果没有找到合适的规则,检查是否有简单的扩展名匹配(向后兼容)
if rule, found := pathConfig.GetProcessedExtRule(ext); found && rule.RedirectMode {
// 使用扩展名规则的目标URL进行302跳转
targetURL := rh.buildTargetURL(rule.Target, targetPath, r.URL.RawQuery)
log.Printf("[Redirect] %s -> 使用扩展名规则进行302跳转: %s", targetPath, targetURL)
return true, targetURL
}
@ -51,6 +60,7 @@ func (rh *RedirectHandler) shouldRedirect(r *http.Request, pathConfig config.Pat
if rule, found := pathConfig.GetProcessedExtRule("*"); found && rule.RedirectMode {
// 使用通配符规则的目标URL进行302跳转
targetURL := rh.buildTargetURL(rule.Target, targetPath, r.URL.RawQuery)
log.Printf("[Redirect] %s -> 使用通配符规则进行302跳转: %s", targetPath, targetURL)
return true, targetURL
}
@ -58,6 +68,7 @@ func (rh *RedirectHandler) shouldRedirect(r *http.Request, pathConfig config.Pat
if pathConfig.RedirectMode {
// 使用默认目标URL进行302跳转
targetURL := rh.buildTargetURL(pathConfig.DefaultTarget, targetPath, r.URL.RawQuery)
log.Printf("[Redirect] %s -> 使用默认目标进行302跳转: %s", targetPath, targetURL)
return true, targetURL
}

View File

@ -183,12 +183,9 @@ func GetFileSize(client *http.Client, url string) (int64, error) {
return resp.ContentLength, nil
}
// GetTargetURL 根据路径和配置决定目标URL
func GetTargetURL(client *http.Client, r *http.Request, pathConfig config.PathConfig, path string) (string, bool) {
// 默认使用默认目标
targetBase := pathConfig.DefaultTarget
usedAltTarget := false
// SelectBestRule 根据文件大小和扩展名选择最合适的规则
// 返回值: (选中的规则, 是否找到匹配的规则, 是否使用了备用目标)
func SelectBestRule(client *http.Client, pathConfig config.PathConfig, path string) (*config.ExtensionRule, bool, bool) {
// 获取文件扩展名(使用优化的字符串处理)
ext := ""
lastDotIndex := strings.LastIndex(path, ".")
@ -196,38 +193,38 @@ func GetTargetURL(client *http.Client, r *http.Request, pathConfig config.PathCo
ext = strings.ToLower(path[lastDotIndex+1:])
}
// 如果没有扩展名规则,直接返回默认目标
// 如果没有扩展名规则,返回nil
if len(pathConfig.ExtRules) == 0 {
if ext == "" {
log.Printf("[Route] %s -> %s (无扩展名)", path, targetBase)
}
return targetBase, false
}
// 确保有扩展名规则
if ext == "" {
log.Printf("[Route] %s -> %s (无扩展名)", path, targetBase)
// 即使没有扩展名,也要尝试匹配 * 通配符规则
return nil, false, false
}
// 获取文件大小
contentLength, err := GetFileSize(client, targetBase+path)
contentLength, err := GetFileSize(client, pathConfig.DefaultTarget+path)
if err != nil {
log.Printf("[Route] %s -> %s (获取文件大小出错: %v)", path, targetBase, err)
log.Printf("[SelectRule] %s -> 获取文件大小出错: %v", path, err)
// 如果无法获取文件大小,尝试使用扩展名直接匹配(优化点)
if altTarget, exists := pathConfig.GetProcessedExtTarget(ext); exists {
usedAltTarget = true
targetBase = altTarget
log.Printf("[Route] %s -> %s (基于扩展名直接匹配)", path, targetBase)
} else if altTarget, exists := pathConfig.GetProcessedExtTarget("*"); exists {
// 尝试使用通配符
usedAltTarget = true
targetBase = altTarget
log.Printf("[Route] %s -> %s (基于通配符匹配)", path, targetBase)
// 如果无法获取文件大小,尝试使用扩展名直接匹配
for _, rule := range pathConfig.ExtRules {
// 检查具体扩展名匹配
for _, e := range rule.Extensions {
if e == ext {
log.Printf("[SelectRule] %s -> 基于扩展名直接匹配规则", path)
return &rule, true, true
}
}
}
return targetBase, usedAltTarget
// 尝试使用通配符规则
for _, rule := range pathConfig.ExtRules {
for _, e := range rule.Extensions {
if e == "*" {
log.Printf("[SelectRule] %s -> 基于通配符匹配规则", path)
return &rule, true, true
}
}
}
return nil, false, false
}
// 获取匹配的扩展名规则
@ -265,10 +262,10 @@ func GetTargetURL(client *http.Client, r *http.Request, pathConfig config.PathCo
// 如果没有找到匹配的具体扩展名规则,使用通配符规则
if len(matchingRules) == 0 {
if len(wildcardRules) > 0 {
log.Printf("[Route] %s -> 使用通配符规则", path)
log.Printf("[SelectRule] %s -> 使用通配符规则", path)
matchingRules = wildcardRules
} else {
return targetBase, false
return nil, false, false
}
}
@ -287,20 +284,69 @@ func GetTargetURL(client *http.Client, r *http.Request, pathConfig config.PathCo
// 检查文件大小是否在阈值范围内
if contentLength >= rule.SizeThreshold && contentLength <= rule.MaxSize {
// 找到匹配的规则
log.Printf("[Route] %s -> %s (文件大小: %s, 在区间 %s 到 %s 之间)",
path, rule.Target, FormatBytes(contentLength),
log.Printf("[SelectRule] %s -> 选中规则 (文件大小: %s, 在区间 %s 到 %s 之间)",
path, FormatBytes(contentLength),
FormatBytes(rule.SizeThreshold), FormatBytes(rule.MaxSize))
// 检查目标是否可访问(使用带缓存的检查)
if isTargetAccessible(client, rule.Target+path) {
targetBase = rule.Target
usedAltTarget = true
return rule, true, true
} else {
log.Printf("[Route] %s -> %s (回退: 备用目标不可访问)",
path, targetBase)
log.Printf("[SelectRule] %s -> 规则目标不可访问,继续查找", path)
// 继续查找下一个匹配的规则
continue
}
}
}
break
// 没有找到合适的规则
return nil, false, false
}
// GetTargetURL 根据路径和配置决定目标URL
func GetTargetURL(client *http.Client, r *http.Request, pathConfig config.PathConfig, path string) (string, bool) {
// 默认使用默认目标
targetBase := pathConfig.DefaultTarget
usedAltTarget := false
// 获取文件扩展名(使用优化的字符串处理)
ext := ""
lastDotIndex := strings.LastIndex(path, ".")
if lastDotIndex > 0 && lastDotIndex < len(path)-1 {
ext = strings.ToLower(path[lastDotIndex+1:])
}
// 如果没有扩展名规则,直接返回默认目标
if len(pathConfig.ExtRules) == 0 {
if ext == "" {
log.Printf("[Route] %s -> %s (无扩展名)", path, targetBase)
}
return targetBase, false
}
// 确保有扩展名规则
if ext == "" {
log.Printf("[Route] %s -> %s (无扩展名)", path, targetBase)
// 即使没有扩展名,也要尝试匹配 * 通配符规则
}
// 使用新的统一规则选择逻辑
rule, found, usedAlt := SelectBestRule(client, pathConfig, path)
if found && rule != nil {
targetBase = rule.Target
usedAltTarget = usedAlt
log.Printf("[Route] %s -> %s (使用选中的规则)", path, targetBase)
} else {
// 如果无法获取文件大小,尝试使用扩展名直接匹配(优化点)
if altTarget, exists := pathConfig.GetProcessedExtTarget(ext); exists {
usedAltTarget = true
targetBase = altTarget
log.Printf("[Route] %s -> %s (基于扩展名直接匹配)", path, targetBase)
} else if altTarget, exists := pathConfig.GetProcessedExtTarget("*"); exists {
// 尝试使用通配符
usedAltTarget = true
targetBase = altTarget
log.Printf("[Route] %s -> %s (基于通配符匹配)", path, targetBase)
}
}