- 添加 convertToReverseConfig 函数,将 config.Config 转换为 reverse.Config - 修正配置字段映射关系: - EnableHTTPS -> DecryptHTTPS - EnableWebSocket -> SupportWebSocketUpgrade - 保持其他配置字段映射不变 - 优化代码格式和注释 BREAKING CHANGE: 反向代理配置结构发生变化,需要更新相关配置
188 lines
4.1 KiB
Go
188 lines
4.1 KiB
Go
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
|
||
}
|