feat(waf): 新增 UA 检查节点 ua_check

支持要求携带 UA、浏览器/OS 白名单 and-or 匹配,以及优先屏蔽爬虫与非正常 UA。
This commit is contained in:
ryan
2026-07-19 11:35:31 +08:00
parent 047ed6554d
commit 28eef0bbcd
22 changed files with 643 additions and 15 deletions
@@ -42,6 +42,39 @@ func TestCompileRuleGraph(t *testing.T) {
}
}
func TestCompileUACheckConfigNormalizesListsAndMatchMode(t *testing.T) {
graph := RuleGraph{SchemaVersion: RuleGraphSchemaVersion, Nodes: []RuleNode{
{ID: "start", Type: RuleNodeStart, Config: rawConfig(`{}`)},
{ID: "ua", Type: RuleNodeUACheck, Config: rawConfig(`{"browsers":["Safari","Chrome","Chrome"],"operating_systems":["iOS","Android"],"require_ua":true,"block_common_bots":true}`)},
{ID: "allow", Type: RuleNodeAllow, Config: rawConfig(`{}`)},
{ID: "block", Type: RuleNodeBlock, Config: rawConfig(`{"status_code":403}`)},
}, Edges: []RuleEdge{
{ID: "e1", Source: "start", SourceHandle: "next", Target: "ua"},
{ID: "e2", Source: "ua", SourceHandle: "true", Target: "allow"},
{ID: "e3", Source: "ua", SourceHandle: "false", Target: "block"},
}}
compiled, err := CompileRuleGraph(graph)
if err != nil {
t.Fatalf("CompileRuleGraph() error = %v", err)
}
cfg, ok := compiled.Nodes["ua"].Config.(UACheckConfig)
if !ok {
t.Fatalf("config type = %T", compiled.Nodes["ua"].Config)
}
if !reflect.DeepEqual(cfg.Browsers, []string{"Chrome", "Safari"}) {
t.Fatalf("browsers = %#v", cfg.Browsers)
}
if !reflect.DeepEqual(cfg.OperatingSystems, []string{"Android", "iOS"}) {
t.Fatalf("os = %#v", cfg.OperatingSystems)
}
if cfg.MatchMode != UACheckMatchModeOr {
t.Fatalf("match_mode = %q, want or", cfg.MatchMode)
}
if !cfg.RequireUA || !cfg.BlockCommonBots || cfg.BlockAbnormalUA {
t.Fatalf("flags = %#v", cfg)
}
}
func TestCompileRuleGraphIsDeterministicForNodeAndEdgeOrder(t *testing.T) {
first := RuleGraph{SchemaVersion: RuleGraphSchemaVersion, Nodes: []RuleNode{
{ID: "start", Type: RuleNodeStart, Config: rawConfig(`{}`)},