feat(routing): add Network matcher for per-protocol node selection

Add Network() matcher to the routing DSL so nodes can be selected based on
connection network type (tcp/udp). Uses prefix matching so Network("tcp")
matches tcp, tcp4, tcp6 and Network("udp") matches udp, udp4, udp6.

- core/routing: add Network field to Request struct (core v0.4.3)
- x/routing/matcher: add network() matcher registered as "Network"
- x/hop: pass options.Network to routing.Request in Select()

Fixes go-gost/gost#703
This commit is contained in:
ginuerzh
2026-06-24 17:38:08 +08:00
parent c06ba17916
commit ec4791485c
6 changed files with 109 additions and 4 deletions
+13
View File
@@ -144,6 +144,7 @@ func (m *matchersTree) addRule(rule *rules.Tree, funcs matcherFuncs) error {
var httpFuncs = map[string]func(*matchersTree, ...string) error{
"ClientIP": expectNParameters(clientIP, 1),
"Network": expectNParameters(network, 1),
"Proto": expectNParameters(proto, 1),
"Host": expectNParameters(host, 1),
"HostRegexp": expectNParameters(hostRegexp, 1),
@@ -206,6 +207,18 @@ func proto(tree *matchersTree, protos ...string) error {
return nil
}
func network(tree *matchersTree, networks ...string) error {
network := strings.ToLower(networks[0])
tree.matcher = func(req *routing.Request) bool {
// Use prefix match so Network("tcp") matches "tcp", "tcp4", "tcp6"
// and Network("udp") matches "udp", "udp4", "udp6".
return strings.HasPrefix(req.Network, network)
}
return nil
}
func method(tree *matchersTree, methods ...string) error {
method := strings.ToUpper(methods[0])
+26
View File
@@ -140,6 +140,32 @@ func TestMatcherProto(t *testing.T) {
}
}
func TestMatcherNetwork(t *testing.T) {
m, err := NewMatcher(`Network("tcp")`)
require.NoError(t, err)
tests := []struct {
desc string
network string
want bool
}{
{"exact match", "tcp", true},
{"prefix match tcp4", "tcp4", true},
{"prefix match tcp6", "tcp6", true},
{"uppercase no match", "TCP", false},
{"wrong network udp", "udp", false},
{"wrong network udp4", "udp4", false},
{"empty", "", false},
}
for _, tc := range tests {
t.Run(tc.desc, func(t *testing.T) {
req := &routing.Request{Network: tc.network}
assert.Equal(t, tc.want, m.Match(req))
})
}
}
func TestMatcherMethod(t *testing.T) {
m, err := NewMatcher(`Method("GET")`)
require.NoError(t, err)