github.com/inazumav/sing-box@v0.0.0-20230926072359-ab51429a14f1/route/rule_item_domain_regex.go (about)

     1  package route
     2  
     3  import (
     4  	"regexp"
     5  	"strings"
     6  
     7  	"github.com/inazumav/sing-box/adapter"
     8  	E "github.com/sagernet/sing/common/exceptions"
     9  	F "github.com/sagernet/sing/common/format"
    10  )
    11  
    12  var _ RuleItem = (*DomainRegexItem)(nil)
    13  
    14  type DomainRegexItem struct {
    15  	matchers    []*regexp.Regexp
    16  	description string
    17  }
    18  
    19  func NewDomainRegexItem(expressions []string) (*DomainRegexItem, error) {
    20  	matchers := make([]*regexp.Regexp, 0, len(expressions))
    21  	for i, regex := range expressions {
    22  		matcher, err := regexp.Compile(regex)
    23  		if err != nil {
    24  			return nil, E.Cause(err, "parse expression ", i)
    25  		}
    26  		matchers = append(matchers, matcher)
    27  	}
    28  	description := "domain_regex="
    29  	eLen := len(expressions)
    30  	if eLen == 1 {
    31  		description += expressions[0]
    32  	} else if eLen > 3 {
    33  		description += F.ToString("[", strings.Join(expressions[:3], " "), "]")
    34  	} else {
    35  		description += F.ToString("[", strings.Join(expressions, " "), "]")
    36  	}
    37  	return &DomainRegexItem{matchers, description}, nil
    38  }
    39  
    40  func (r *DomainRegexItem) Match(metadata *adapter.InboundContext) bool {
    41  	var domainHost string
    42  	if metadata.Domain != "" {
    43  		domainHost = metadata.Domain
    44  	} else {
    45  		domainHost = metadata.Destination.Fqdn
    46  	}
    47  	if domainHost == "" {
    48  		return false
    49  	}
    50  	domainHost = strings.ToLower(domainHost)
    51  	for _, matcher := range r.matchers {
    52  		if matcher.MatchString(domainHost) {
    53  			return true
    54  		}
    55  	}
    56  	return false
    57  }
    58  
    59  func (r *DomainRegexItem) String() string {
    60  	return r.description
    61  }