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跳转
|
// 检查是否需要进行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跳转,直接返回,不继续处理
|
// 如果进行了302跳转,直接返回,不继续处理
|
||||||
collector.RecordRequest(r.URL.Path, http.StatusFound, time.Since(start), 0, utils.GetClientIP(r), r)
|
collector.RecordRequest(r.URL.Path, http.StatusFound, time.Since(start), 0, utils.GetClientIP(r), r)
|
||||||
return
|
return
|
||||||
|
@ -19,9 +19,9 @@ func NewRedirectHandler() *RedirectHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// HandleRedirect 处理302跳转请求
|
// 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跳转
|
// 检查是否需要进行302跳转
|
||||||
shouldRedirect, targetURL := rh.shouldRedirect(r, pathConfig, targetPath)
|
shouldRedirect, targetURL := rh.shouldRedirect(r, pathConfig, targetPath, client)
|
||||||
|
|
||||||
if !shouldRedirect {
|
if !shouldRedirect {
|
||||||
return false
|
return false
|
||||||
@ -33,17 +33,26 @@ func (rh *RedirectHandler) HandleRedirect(w http.ResponseWriter, r *http.Request
|
|||||||
}
|
}
|
||||||
|
|
||||||
// shouldRedirect 判断是否应该进行302跳转,并返回目标URL
|
// 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))
|
ext := strings.ToLower(filepath.Ext(targetPath))
|
||||||
if ext != "" {
|
if ext != "" {
|
||||||
ext = ext[1:] // 去掉点号
|
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 {
|
if rule, found := pathConfig.GetProcessedExtRule(ext); found && rule.RedirectMode {
|
||||||
// 使用扩展名规则的目标URL进行302跳转
|
// 使用扩展名规则的目标URL进行302跳转
|
||||||
targetURL := rh.buildTargetURL(rule.Target, targetPath, r.URL.RawQuery)
|
targetURL := rh.buildTargetURL(rule.Target, targetPath, r.URL.RawQuery)
|
||||||
|
log.Printf("[Redirect] %s -> 使用扩展名规则进行302跳转: %s", targetPath, targetURL)
|
||||||
return true, 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 {
|
if rule, found := pathConfig.GetProcessedExtRule("*"); found && rule.RedirectMode {
|
||||||
// 使用通配符规则的目标URL进行302跳转
|
// 使用通配符规则的目标URL进行302跳转
|
||||||
targetURL := rh.buildTargetURL(rule.Target, targetPath, r.URL.RawQuery)
|
targetURL := rh.buildTargetURL(rule.Target, targetPath, r.URL.RawQuery)
|
||||||
|
log.Printf("[Redirect] %s -> 使用通配符规则进行302跳转: %s", targetPath, targetURL)
|
||||||
return true, targetURL
|
return true, targetURL
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -58,6 +68,7 @@ func (rh *RedirectHandler) shouldRedirect(r *http.Request, pathConfig config.Pat
|
|||||||
if pathConfig.RedirectMode {
|
if pathConfig.RedirectMode {
|
||||||
// 使用默认目标URL进行302跳转
|
// 使用默认目标URL进行302跳转
|
||||||
targetURL := rh.buildTargetURL(pathConfig.DefaultTarget, targetPath, r.URL.RawQuery)
|
targetURL := rh.buildTargetURL(pathConfig.DefaultTarget, targetPath, r.URL.RawQuery)
|
||||||
|
log.Printf("[Redirect] %s -> 使用默认目标进行302跳转: %s", targetPath, targetURL)
|
||||||
return true, targetURL
|
return true, targetURL
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -183,12 +183,9 @@ func GetFileSize(client *http.Client, url string) (int64, error) {
|
|||||||
return resp.ContentLength, nil
|
return resp.ContentLength, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetTargetURL 根据路径和配置决定目标URL
|
// SelectBestRule 根据文件大小和扩展名选择最合适的规则
|
||||||
func GetTargetURL(client *http.Client, r *http.Request, pathConfig config.PathConfig, path string) (string, bool) {
|
// 返回值: (选中的规则, 是否找到匹配的规则, 是否使用了备用目标)
|
||||||
// 默认使用默认目标
|
func SelectBestRule(client *http.Client, pathConfig config.PathConfig, path string) (*config.ExtensionRule, bool, bool) {
|
||||||
targetBase := pathConfig.DefaultTarget
|
|
||||||
usedAltTarget := false
|
|
||||||
|
|
||||||
// 获取文件扩展名(使用优化的字符串处理)
|
// 获取文件扩展名(使用优化的字符串处理)
|
||||||
ext := ""
|
ext := ""
|
||||||
lastDotIndex := strings.LastIndex(path, ".")
|
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:])
|
ext = strings.ToLower(path[lastDotIndex+1:])
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果没有扩展名规则,直接返回默认目标
|
// 如果没有扩展名规则,返回nil
|
||||||
if len(pathConfig.ExtRules) == 0 {
|
if len(pathConfig.ExtRules) == 0 {
|
||||||
if ext == "" {
|
return nil, false, false
|
||||||
log.Printf("[Route] %s -> %s (无扩展名)", path, targetBase)
|
|
||||||
}
|
|
||||||
return targetBase, false
|
|
||||||
}
|
|
||||||
|
|
||||||
// 确保有扩展名规则
|
|
||||||
if ext == "" {
|
|
||||||
log.Printf("[Route] %s -> %s (无扩展名)", path, targetBase)
|
|
||||||
// 即使没有扩展名,也要尝试匹配 * 通配符规则
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取文件大小
|
// 获取文件大小
|
||||||
contentLength, err := GetFileSize(client, targetBase+path)
|
contentLength, err := GetFileSize(client, pathConfig.DefaultTarget+path)
|
||||||
if err != nil {
|
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 {
|
for _, rule := range pathConfig.ExtRules {
|
||||||
usedAltTarget = true
|
// 检查具体扩展名匹配
|
||||||
targetBase = altTarget
|
for _, e := range rule.Extensions {
|
||||||
log.Printf("[Route] %s -> %s (基于扩展名直接匹配)", path, targetBase)
|
if e == ext {
|
||||||
} else if altTarget, exists := pathConfig.GetProcessedExtTarget("*"); exists {
|
log.Printf("[SelectRule] %s -> 基于扩展名直接匹配规则", path)
|
||||||
// 尝试使用通配符
|
return &rule, true, true
|
||||||
usedAltTarget = true
|
}
|
||||||
targetBase = altTarget
|
}
|
||||||
log.Printf("[Route] %s -> %s (基于通配符匹配)", path, targetBase)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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(matchingRules) == 0 {
|
||||||
if len(wildcardRules) > 0 {
|
if len(wildcardRules) > 0 {
|
||||||
log.Printf("[Route] %s -> 使用通配符规则", path)
|
log.Printf("[SelectRule] %s -> 使用通配符规则", path)
|
||||||
matchingRules = wildcardRules
|
matchingRules = wildcardRules
|
||||||
} else {
|
} 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 {
|
if contentLength >= rule.SizeThreshold && contentLength <= rule.MaxSize {
|
||||||
// 找到匹配的规则
|
// 找到匹配的规则
|
||||||
log.Printf("[Route] %s -> %s (文件大小: %s, 在区间 %s 到 %s 之间)",
|
log.Printf("[SelectRule] %s -> 选中规则 (文件大小: %s, 在区间 %s 到 %s 之间)",
|
||||||
path, rule.Target, FormatBytes(contentLength),
|
path, FormatBytes(contentLength),
|
||||||
FormatBytes(rule.SizeThreshold), FormatBytes(rule.MaxSize))
|
FormatBytes(rule.SizeThreshold), FormatBytes(rule.MaxSize))
|
||||||
|
|
||||||
// 检查目标是否可访问(使用带缓存的检查)
|
// 检查目标是否可访问(使用带缓存的检查)
|
||||||
if isTargetAccessible(client, rule.Target+path) {
|
if isTargetAccessible(client, rule.Target+path) {
|
||||||
targetBase = rule.Target
|
return rule, true, true
|
||||||
usedAltTarget = true
|
|
||||||
} else {
|
} else {
|
||||||
log.Printf("[Route] %s -> %s (回退: 备用目标不可访问)",
|
log.Printf("[SelectRule] %s -> 规则目标不可访问,继续查找", path)
|
||||||
path, targetBase)
|
// 继续查找下一个匹配的规则
|
||||||
|
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