From a6c5c579307a8b38b2121eab578547627a0206b3 Mon Sep 17 00:00:00 2001 From: yuhan6665 <1588741+yuhan6665@users.noreply.github.com> Date: Tue, 27 Jun 2023 04:04:09 -0400 Subject: [PATCH] Support regex matching with attr (#2258) * Support regex matching with attr * Add test case * Optimizing regex parsing at core start * simpliy --- app/router/condition.go | 11 ++++++----- app/router/condition_test.go | 13 +++++++++++++ app/router/config.go | 5 +++-- 3 files changed, 22 insertions(+), 7 deletions(-) diff --git a/app/router/condition.go b/app/router/condition.go index 326c13ff..29056555 100644 --- a/app/router/condition.go +++ b/app/router/condition.go @@ -1,6 +1,7 @@ package router import ( + "regexp" "strings" "github.com/xtls/xray-core/common/net" @@ -282,18 +283,18 @@ func (m *ProtocolMatcher) Apply(ctx routing.Context) bool { } type AttributeMatcher struct { - configuredKeys map[string]string + configuredKeys map[string]*regexp.Regexp } // Match implements attributes matching. func (m *AttributeMatcher) Match(attrs map[string]string) bool { - // headers are insensitive most likely. So we do a convert + // header keys are case insensitive most likely. So we do a convert httpHeaders := make(map[string]string) for key, value := range attrs { - httpHeaders[strings.ToLower(key)] = strings.ToLower(value) + httpHeaders[strings.ToLower(key)] = value } - for key, value := range m.configuredKeys { - if a, ok := httpHeaders[key]; !ok || !strings.Contains(a, value) { + for key, regex := range m.configuredKeys { + if a, ok := httpHeaders[key]; !ok || !regex.MatchString(a) { return false } } diff --git a/app/router/condition_test.go b/app/router/condition_test.go index 395a04c9..fd898417 100644 --- a/app/router/condition_test.go +++ b/app/router/condition_test.go @@ -319,6 +319,19 @@ func TestRoutingRule(t *testing.T) { }, }, }, + { + rule: &RoutingRule{ + Attributes: map[string]string{ + "Custom": "p([a-z]+)ch", + }, + }, + test: []ruleTest{ + { + input: withContent(&session.Content{Attributes: map[string]string{"custom": "peach"}}), + output: true, + }, + }, + }, } for _, test := range cases { diff --git a/app/router/config.go b/app/router/config.go index 3f4fd7c5..80b88781 100644 --- a/app/router/config.go +++ b/app/router/config.go @@ -1,6 +1,7 @@ package router import ( + "regexp" "strings" "github.com/xtls/xray-core/common/net" @@ -145,9 +146,9 @@ func (rr *RoutingRule) BuildCondition() (Condition, error) { } if len(rr.Attributes) > 0 { - configuredKeys := make(map[string]string) + configuredKeys := make(map[string]*regexp.Regexp) for key, value := range rr.Attributes { - configuredKeys[strings.ToLower(key)] = strings.ToLower(value) + configuredKeys[strings.ToLower(key)] = regexp.MustCompile(value) } conds.Add(&AttributeMatcher{configuredKeys}) }