Skip to content

Commit 8c5de70

Browse files
committed
feat: webhook in rules
1 parent e6207e3 commit 8c5de70

File tree

5 files changed

+363
-16
lines changed

5 files changed

+363
-16
lines changed

app/router/config.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ type Rule struct {
1818
RuleTag string
1919
Balancer *Balancer
2020
Condition Condition
21+
Webhook *WebhookNotifier
2122
}
2223

2324
func (r *Rule) GetTag() (string, error) {

app/router/config.proto

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,13 @@ message RoutingRule {
114114

115115
xray.common.net.PortList vless_route_list = 20;
116116
repeated string process = 21;
117+
WebhookConfig webhook = 22;
118+
}
119+
120+
message WebhookConfig {
121+
string url = 1;
122+
uint32 deduplication = 2;
123+
map<string, string> headers = 3;
117124
}
118125

119126
message BalancingRule {

app/router/router.go

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,17 +57,30 @@ func (r *Router) Init(ctx context.Context, config *Config, d dns.Client, ohm out
5757
for _, rule := range config.Rule {
5858
cond, err := rule.BuildCondition()
5959
if err != nil {
60+
r.closeWebhooks()
6061
return err
6162
}
6263
rr := &Rule{
6364
Condition: cond,
6465
Tag: rule.GetTag(),
6566
RuleTag: rule.GetRuleTag(),
6667
}
68+
if wh := rule.GetWebhook(); wh != nil {
69+
notifier, err := NewWebhookNotifier(wh)
70+
if err != nil {
71+
r.closeWebhooks()
72+
return err
73+
}
74+
rr.Webhook = notifier
75+
}
6776
btag := rule.GetBalancingTag()
6877
if len(btag) > 0 {
6978
brule, found := r.balancers[btag]
7079
if !found {
80+
if rr.Webhook != nil {
81+
rr.Webhook.Close()
82+
}
83+
r.closeWebhooks()
7184
return errors.New("balancer ", btag, " not found")
7285
}
7386
rr.Balancer = brule
@@ -80,6 +93,7 @@ func (r *Router) Init(ctx context.Context, config *Config, d dns.Client, ohm out
8093

8194
// PickRoute implements routing.Router.
8295
func (r *Router) PickRoute(ctx routing.Context) (routing.Route, error) {
96+
originalCtx := ctx
8397
rule, ctx, err := r.pickRouteInternal(ctx)
8498
if err != nil {
8599
return nil, err
@@ -88,6 +102,9 @@ func (r *Router) PickRoute(ctx routing.Context) (routing.Route, error) {
88102
if err != nil {
89103
return nil, err
90104
}
105+
if rule.Webhook != nil {
106+
rule.Webhook.Fire(originalCtx, tag)
107+
}
91108
return &Route{Context: ctx, outboundTag: tag, ruleTag: rule.RuleTag}, nil
92109
}
93110

@@ -109,6 +126,11 @@ func (r *Router) ReloadRules(config *Config, shouldAppend bool) error {
109126
defer r.mu.Unlock()
110127

111128
if !shouldAppend {
129+
for _, rule := range r.rules {
130+
if rule.Webhook != nil {
131+
rule.Webhook.Close()
132+
}
133+
}
112134
r.balancers = make(map[string]*Balancer, len(config.BalancingRule))
113135
r.rules = make([]*Rule, 0, len(config.Rule))
114136
}
@@ -125,23 +147,47 @@ func (r *Router) ReloadRules(config *Config, shouldAppend bool) error {
125147
r.balancers[rule.Tag] = balancer
126148
}
127149

150+
startIdx := len(r.rules)
151+
closeNewWebhooks := func() {
152+
for i := startIdx; i < len(r.rules); i++ {
153+
if r.rules[i].Webhook != nil {
154+
r.rules[i].Webhook.Close()
155+
}
156+
}
157+
r.rules = r.rules[:startIdx]
158+
}
159+
128160
for _, rule := range config.Rule {
129161
if r.RuleExists(rule.GetRuleTag()) {
162+
closeNewWebhooks()
130163
return errors.New("duplicate ruleTag ", rule.GetRuleTag())
131164
}
132165
cond, err := rule.BuildCondition()
133166
if err != nil {
167+
closeNewWebhooks()
134168
return err
135169
}
136170
rr := &Rule{
137171
Condition: cond,
138172
Tag: rule.GetTag(),
139173
RuleTag: rule.GetRuleTag(),
140174
}
175+
if wh := rule.GetWebhook(); wh != nil {
176+
notifier, err := NewWebhookNotifier(wh)
177+
if err != nil {
178+
closeNewWebhooks()
179+
return err
180+
}
181+
rr.Webhook = notifier
182+
}
141183
btag := rule.GetBalancingTag()
142184
if len(btag) > 0 {
143185
brule, found := r.balancers[btag]
144186
if !found {
187+
if rr.Webhook != nil {
188+
rr.Webhook.Close()
189+
}
190+
closeNewWebhooks()
145191
return errors.New("balancer ", btag, " not found")
146192
}
147193
rr.Balancer = brule
@@ -173,6 +219,8 @@ func (r *Router) RemoveRule(tag string) error {
173219
for _, rule := range r.rules {
174220
if rule.RuleTag != tag {
175221
newRules = append(newRules, rule)
222+
} else if rule.Webhook != nil {
223+
rule.Webhook.Close()
176224
}
177225
}
178226
r.rules = newRules
@@ -233,8 +281,20 @@ func (r *Router) Start() error {
233281
return nil
234282
}
235283

284+
// closeWebhooks closes all webhook notifiers in the current rule set.
285+
func (r *Router) closeWebhooks() {
286+
for _, rule := range r.rules {
287+
if rule.Webhook != nil {
288+
rule.Webhook.Close()
289+
}
290+
}
291+
}
292+
236293
// Close implements common.Closable.
237294
func (r *Router) Close() error {
295+
r.mu.Lock()
296+
defer r.mu.Unlock()
297+
r.closeWebhooks()
238298
return nil
239299
}
240300

0 commit comments

Comments
 (0)