Files
goproxy/internal/rule/rule_impl.go
DarkiT 35f492b1c5 refactor(proxy): 重构反向代理配置转换逻辑
- 添加 convertToReverseConfig 函数,将 config.Config 转换为 reverse.Config
- 修正配置字段映射关系:
  - EnableHTTPS -> DecryptHTTPS
  - EnableWebSocket -> SupportWebSocketUpgrade
- 保持其他配置字段映射不变
- 优化代码格式和注释

BREAKING CHANGE: 反向代理配置结构发生变化,需要更新相关配置
2025-03-13 22:02:30 +08:00

188 lines
4.1 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package rule
import (
"fmt"
"net"
"net/http"
"regexp"
"strings"
)
// Match DNS规则匹配
func (r *DNSRule) Match(req *http.Request) bool {
host := req.Host
if strings.Contains(host, ":") {
host, _, _ = net.SplitHostPort(host)
}
switch r.MatchType {
case MatchTypeExact:
return host == r.Pattern
case MatchTypeWildcard:
return matchWildcard(host, r.Pattern)
case MatchTypeRegex:
if re, err := regexp.Compile(r.Pattern); err == nil {
return re.MatchString(host)
}
}
return false
}
// Apply DNS规则应用
func (r *DNSRule) Apply(req *http.Request) error {
if !r.Enabled {
return nil
}
// DNS规则的应用在DNS解析阶段处理这里不需要修改请求
return nil
}
// Validate DNS规则验证
func (r *DNSRule) Validate() error {
if r.ID == "" {
return fmt.Errorf("规则ID不能为空")
}
if len(r.Targets) == 0 {
return fmt.Errorf("DNS规则必须包含至少一个目标")
}
for _, target := range r.Targets {
if net.ParseIP(target.IP) == nil {
return fmt.Errorf("无效的IP地址: %s", target.IP)
}
if target.Port < 0 || target.Port > 65535 {
return fmt.Errorf("无效的端口号: %d", target.Port)
}
}
return nil
}
// Match URL重写规则匹配
func (r *RewriteRule) Match(req *http.Request) bool {
switch r.MatchType {
case MatchTypeExact:
return req.URL.Path == r.Pattern
case MatchTypePath:
return strings.HasPrefix(req.URL.Path, r.Pattern)
case MatchTypeRegex:
if re, err := regexp.Compile(r.Pattern); err == nil {
return re.MatchString(req.URL.Path)
}
}
return false
}
// Apply URL重写规则应用
func (r *RewriteRule) Apply(req *http.Request) error {
if !r.Enabled {
return nil
}
switch r.MatchType {
case MatchTypeExact, MatchTypePath:
req.URL.Path = strings.Replace(req.URL.Path, r.Pattern, r.Replacement, 1)
case MatchTypeRegex:
if re, err := regexp.Compile(r.Pattern); err == nil {
req.URL.Path = re.ReplaceAllString(req.URL.Path, r.Replacement)
} else {
return fmt.Errorf("正则表达式编译失败: %v", err)
}
}
return nil
}
// Validate URL重写规则验证
func (r *RewriteRule) Validate() error {
if r.ID == "" {
return fmt.Errorf("规则ID不能为空")
}
if r.Pattern == "" {
return fmt.Errorf("重写规则必须包含匹配模式")
}
if r.MatchType == MatchTypeRegex {
if _, err := regexp.Compile(r.Pattern); err != nil {
return fmt.Errorf("无效的正则表达式: %v", err)
}
}
return nil
}
// Match 路由规则匹配
func (r *RouteRule) Match(req *http.Request) bool {
switch r.MatchType {
case MatchTypeExact:
return req.URL.Path == r.Pattern
case MatchTypePath:
return strings.HasPrefix(req.URL.Path, r.Pattern)
case MatchTypeRegex:
if re, err := regexp.Compile(r.Pattern); err == nil {
return re.MatchString(req.URL.Path)
}
}
return false
}
// Apply 路由规则应用
func (r *RouteRule) Apply(req *http.Request) error {
if !r.Enabled {
return nil
}
// 修改请求头
for key, value := range r.HeaderModifier {
// 支持变量替换
switch value {
case "${client_ip}":
clientIP := req.RemoteAddr
if ip, _, err := net.SplitHostPort(clientIP); err == nil {
req.Header.Set(key, ip)
} else {
req.Header.Set(key, clientIP)
}
default:
req.Header.Set(key, value)
}
}
return nil
}
// Validate 路由规则验证
func (r *RouteRule) Validate() error {
if r.ID == "" {
return fmt.Errorf("规则ID不能为空")
}
if r.Pattern == "" {
return fmt.Errorf("路由规则必须包含匹配模式")
}
if r.Target == "" {
return fmt.Errorf("路由规则必须包含目标地址")
}
if r.MatchType == MatchTypeRegex {
if _, err := regexp.Compile(r.Pattern); err != nil {
return fmt.Errorf("无效的正则表达式: %v", err)
}
}
return nil
}
// 辅助函数:通配符匹配
func matchWildcard(host, pattern string) bool {
if !strings.Contains(pattern, "*") {
return host == pattern
}
parts := strings.Split(pattern, ".")
hostParts := strings.Split(host, ".")
if len(parts) != len(hostParts) {
return false
}
for i := 0; i < len(parts); i++ {
if parts[i] != "*" && parts[i] != hostParts[i] {
return false
}
}
return true
}