mirror of
https://github.com/putyy/res-downloader.git
synced 2026-01-12 06:04:55 +08:00
feat: add domain rule configuration
This commit is contained in:
@@ -37,6 +37,7 @@ var (
|
||||
systemOnce *SystemSetup
|
||||
proxyOnce *Proxy
|
||||
httpServerOnce *HttpServer
|
||||
ruleOnce *RuleSet
|
||||
)
|
||||
|
||||
func GetApp(assets embed.FS, wjs string) *App {
|
||||
@@ -120,6 +121,7 @@ ILKEQKmPPzKs7kp/7Nz+2cT3
|
||||
initResource()
|
||||
initHttpServer()
|
||||
initSystem()
|
||||
initRule()
|
||||
}
|
||||
return appOnce
|
||||
}
|
||||
|
||||
@@ -37,6 +37,7 @@ type Config struct {
|
||||
UseHeaders string `json:"UseHeaders"`
|
||||
InsertTail bool `json:"InsertTail"`
|
||||
MimeMap map[string]MimeInfo `json:"MimeMap"`
|
||||
Rule string `json:"Rule"`
|
||||
}
|
||||
|
||||
var (
|
||||
@@ -68,6 +69,7 @@ func initConfig() *Config {
|
||||
UseHeaders: "User-Agent,Referer,Authorization,Cookie",
|
||||
InsertTail: true,
|
||||
MimeMap: getDefaultMimeMap(),
|
||||
Rule: "*",
|
||||
}
|
||||
|
||||
rawDefaults, err := json.Marshal(defaultConfig)
|
||||
@@ -207,6 +209,7 @@ func getDefaultDownloadDir() string {
|
||||
func (c *Config) setConfig(config Config) {
|
||||
oldProxy := c.UpstreamProxy
|
||||
openProxy := c.OpenProxy
|
||||
oldRule := c.Rule
|
||||
c.Host = config.Host
|
||||
c.Port = config.Port
|
||||
c.Theme = config.Theme
|
||||
@@ -225,10 +228,18 @@ func (c *Config) setConfig(config Config) {
|
||||
c.WxAction = config.WxAction
|
||||
c.UseHeaders = config.UseHeaders
|
||||
c.InsertTail = config.InsertTail
|
||||
c.Rule = config.Rule
|
||||
if oldProxy != c.UpstreamProxy || openProxy != c.OpenProxy {
|
||||
proxyOnce.setTransport()
|
||||
}
|
||||
|
||||
if oldRule != c.Rule {
|
||||
err := ruleOnce.Load(c.Rule)
|
||||
if err != nil {
|
||||
globalLogger.Esg(err, "set rule failed")
|
||||
}
|
||||
}
|
||||
|
||||
mimeMux.Lock()
|
||||
c.MimeMap = config.MimeMap
|
||||
mimeMux.Unlock()
|
||||
@@ -281,6 +292,8 @@ func (c *Config) getConfig(key string) interface{} {
|
||||
mimeMux.RLock()
|
||||
defer mimeMux.RUnlock()
|
||||
return c.MimeMap
|
||||
case "Rule":
|
||||
return c.Rule
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -80,7 +80,14 @@ func (p *Proxy) Startup() {
|
||||
//p.Proxy.KeepDestinationHeaders = true
|
||||
//p.Proxy.Verbose = false
|
||||
p.setTransport()
|
||||
p.Proxy.OnRequest().HandleConnect(goproxy.AlwaysMitm)
|
||||
//p.Proxy.OnRequest().HandleConnect(goproxy.AlwaysMitm)
|
||||
p.Proxy.OnRequest().HandleConnectFunc(func(host string, ctx *goproxy.ProxyCtx) (*goproxy.ConnectAction, string) {
|
||||
if ruleOnce.shouldMitm(host) {
|
||||
return goproxy.MitmConnect, host
|
||||
}
|
||||
return goproxy.OkConnect, host
|
||||
})
|
||||
|
||||
p.Proxy.OnRequest().DoFunc(p.httpRequestEvent)
|
||||
p.Proxy.OnResponse().DoFunc(p.httpResponseEvent)
|
||||
}
|
||||
|
||||
118
core/rule.go
Normal file
118
core/rule.go
Normal file
@@ -0,0 +1,118 @@
|
||||
package core
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"net"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type Rule struct {
|
||||
raw string
|
||||
isNeg bool // 是否否定规则(以 ! 开头)
|
||||
isWildcard bool // 是否为 *.domain 形式
|
||||
domain string // 域名部分,不含 "*."
|
||||
}
|
||||
|
||||
type RuleSet struct {
|
||||
mu sync.RWMutex
|
||||
rules []Rule
|
||||
}
|
||||
|
||||
func initRule() *RuleSet {
|
||||
if ruleOnce == nil {
|
||||
ruleOnce = &RuleSet{}
|
||||
err := ruleOnce.Load(globalConfig.Rule)
|
||||
if err != nil {
|
||||
globalLogger.Esg(err, "init rule failed")
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return ruleOnce
|
||||
}
|
||||
|
||||
func (r *RuleSet) Load(rs string) error {
|
||||
reader := strings.NewReader(rs)
|
||||
scanner := bufio.NewScanner(reader)
|
||||
|
||||
var rules []Rule
|
||||
for scanner.Scan() {
|
||||
line := strings.TrimSpace(scanner.Text())
|
||||
if line == "" || strings.HasPrefix(line, "#") {
|
||||
continue
|
||||
}
|
||||
|
||||
isNeg := false
|
||||
if strings.HasPrefix(line, "!") {
|
||||
isNeg = true
|
||||
line = strings.TrimSpace(line[1:])
|
||||
if line == "" {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
isWildcard := false
|
||||
domain := line
|
||||
if strings.HasPrefix(line, "*.") {
|
||||
isWildcard = true
|
||||
domain = line[2:]
|
||||
}
|
||||
|
||||
rules = append(rules, Rule{
|
||||
raw: line,
|
||||
isNeg: isNeg,
|
||||
isWildcard: isWildcard,
|
||||
domain: strings.ToLower(domain),
|
||||
})
|
||||
}
|
||||
|
||||
if err := scanner.Err(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
r.mu.Lock()
|
||||
r.rules = rules
|
||||
r.mu.Unlock()
|
||||
return nil
|
||||
}
|
||||
|
||||
// shouldMitm: 根据当前规则集判断是否对 host 做 MITM
|
||||
// host 可能带端口(example.com:443),函数会只匹配 hostname 部分
|
||||
// 返回 true => MITM(解密),false => 透传
|
||||
func (r *RuleSet) shouldMitm(host string) bool {
|
||||
h := host
|
||||
if strings.HasPrefix(h, "[") {
|
||||
if hostSplitIdx := strings.LastIndex(h, "]"); hostSplitIdx != -1 {
|
||||
h = h[:hostSplitIdx+1]
|
||||
}
|
||||
}
|
||||
if hp, _, err := net.SplitHostPort(host); err == nil {
|
||||
h = hp
|
||||
}
|
||||
h = strings.ToLower(strings.Trim(h, "[]"))
|
||||
|
||||
r.mu.RLock()
|
||||
defer r.mu.RUnlock()
|
||||
|
||||
action := false
|
||||
for _, rule := range r.rules {
|
||||
if rule.isWildcard {
|
||||
if h == rule.domain || strings.HasSuffix(h, "."+rule.domain) {
|
||||
if rule.isNeg {
|
||||
action = false
|
||||
} else {
|
||||
action = true
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if h == rule.domain {
|
||||
if rule.isNeg {
|
||||
action = false
|
||||
} else {
|
||||
action = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return action
|
||||
}
|
||||
Reference in New Issue
Block a user