refactor(mcp-server): improve host matching logic using HostMatcher p… (#2890)

This commit is contained in:
澄潭
2025-09-09 16:14:33 +08:00
committed by GitHub
parent f7d80373f9
commit 5384481704

View File

@@ -13,6 +13,9 @@ type RuleType string
// UpstreamType defines the type of matching rule // UpstreamType defines the type of matching rule
type UpstreamType string type UpstreamType string
// HostMatchType defines the type of host matching
type HostMatchType int
const ( const (
ExactMatch RuleType = "exact" ExactMatch RuleType = "exact"
PrefixMatch RuleType = "prefix" PrefixMatch RuleType = "prefix"
@@ -23,8 +26,18 @@ const (
RestUpstream UpstreamType = "rest" RestUpstream UpstreamType = "rest"
SSEUpstream UpstreamType = "sse" SSEUpstream UpstreamType = "sse"
StreamableUpstream UpstreamType = "streamable" StreamableUpstream UpstreamType = "streamable"
HostExact HostMatchType = iota
HostPrefix
HostSuffix
) )
// HostMatcher defines the structure for host matching
type HostMatcher struct {
matchType HostMatchType
host string
}
// MatchRule defines the structure for a matching rule // MatchRule defines the structure for a matching rule
type MatchRule struct { type MatchRule struct {
MatchRuleDomain string `json:"match_rule_domain"` // Domain pattern, supports wildcards MatchRuleDomain string `json:"match_rule_domain"` // Domain pattern, supports wildcards
@@ -84,11 +97,38 @@ func ParseMatchList(matchListConfig []interface{}) []MatchRule {
return matchList return matchList
} }
// convertWildcardToRegex converts wildcard pattern to regex pattern // stripPortFromHost removes port from host string
func convertWildcardToRegex(pattern string) string { // Port removing code is inspired by
pattern = regexp.QuoteMeta(pattern) // https://github.com/envoyproxy/envoy/blob/v1.17.0/source/common/http/header_utility.cc#L219
pattern = "^" + strings.ReplaceAll(pattern, "\\*", ".*") + "$" func stripPortFromHost(reqHost string) string {
return pattern portStart := strings.LastIndexByte(reqHost, ':')
if portStart != -1 {
// According to RFC3986 v6 address is always enclosed in "[]".
// section 3.2.2.
v6EndIndex := strings.LastIndexByte(reqHost, ']')
if v6EndIndex == -1 || v6EndIndex < portStart {
if portStart+1 <= len(reqHost) {
return reqHost[:portStart]
}
}
}
return reqHost
}
// parseHostPattern parses a host pattern and returns a HostMatcher
func parseHostPattern(pattern string) HostMatcher {
var hostMatcher HostMatcher
if strings.HasPrefix(pattern, "*") {
hostMatcher.matchType = HostSuffix
hostMatcher.host = pattern[1:]
} else if strings.HasSuffix(pattern, "*") {
hostMatcher.matchType = HostPrefix
hostMatcher.host = pattern[:len(pattern)-1]
} else {
hostMatcher.matchType = HostExact
hostMatcher.host = pattern
}
return hostMatcher
} }
// matchPattern checks if the target matches the pattern based on rule type // matchPattern checks if the target matches the pattern based on rule type
@@ -117,15 +157,29 @@ func matchPattern(pattern string, target string, ruleType RuleType) bool {
} }
} }
// matchDomain checks if the domain matches the pattern // matchDomain checks if the domain matches the pattern using HostMatcher approach
func matchDomain(domain string, pattern string) bool { func matchDomain(domain string, pattern string) bool {
if pattern == "" || pattern == "*" { if pattern == "" || pattern == "*" {
return true return true
} }
// Convert wildcard pattern to regex pattern
regexPattern := convertWildcardToRegex(pattern) // Strip port from domain
matched, _ := regexp.MatchString(regexPattern, domain) domain = stripPortFromHost(domain)
return matched
// Parse the pattern into a HostMatcher
hostMatcher := parseHostPattern(pattern)
// Perform matching based on match type
switch hostMatcher.matchType {
case HostSuffix:
return strings.HasSuffix(domain, hostMatcher.host)
case HostPrefix:
return strings.HasPrefix(domain, hostMatcher.host)
case HostExact:
return domain == hostMatcher.host
default:
return false
}
} }
// matchDomainAndPath checks if both domain and path match the rule // matchDomainAndPath checks if both domain and path match the rule