mirror of
https://github.com/woodchen-ink/proxy-go.git
synced 2025-07-19 08:51:55 +08:00
更新302跳转处理逻辑,添加客户端参数以优化规则选择,增强扩展名匹配和文件大小判断,确保代理请求的准确性和稳定性。
This commit is contained in:
parent
f229455db9
commit
4447e690db
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user