package rules import ( "net/http" "testing" ) func TestHasBodyRules(t *testing.T) { tests := []struct { name string rs []Rule want bool }{ {"empty", nil, false}, {"header rule only", []Rule{{Enabled: true, Part: "header"}}, false}, {"body rule enabled", []Rule{{Enabled: true, Part: "body"}}, true}, {"body rule disabled", []Rule{{Enabled: false, Part: "body"}}, false}, {"mixed, one enabled body rule", []Rule{ {Enabled: true, Part: "header"}, {Enabled: true, Part: "body"}, }, true}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if got := HasBodyRules(tt.rs); got != tt.want { t.Errorf("HasBodyRules(%+v) = %v, want %v", tt.rs, got, tt.want) } }) } } func TestApplyBodyLiteral(t *testing.T) { body := []byte(`{"admin":false,"user":"bob"}`) rs := []Rule{{Enabled: true, Part: "body", Match: `"admin":false`, Replace: `"admin":true`}} got := ApplyBody(body, rs) want := `{"admin":true,"user":"bob"}` if string(got) != want { t.Errorf("ApplyBody = %q, want %q", got, want) } } func TestApplyBodyRegex(t *testing.T) { body := []byte(`user_id=12345&session=abc`) rs := []Rule{{Enabled: true, Part: "body", Match: `user_id=\d+`, Replace: "user_id=1", IsRegex: true}} got := ApplyBody(body, rs) want := `user_id=1&session=abc` if string(got) != want { t.Errorf("ApplyBody = %q, want %q", got, want) } } func TestApplyBodySkipsDisabledAndHeaderRules(t *testing.T) { body := []byte("hello world") rs := []Rule{ {Enabled: false, Part: "body", Match: "hello", Replace: "bye"}, {Enabled: true, Part: "header", Match: "world", Replace: "planet"}, } got := ApplyBody(body, rs) if string(got) != "hello world" { t.Errorf("ApplyBody = %q, want unchanged %q", got, "hello world") } } func TestApplyBodyRespectsPositionOrder(t *testing.T) { body := []byte("aaa") rs := []Rule{ {Enabled: true, Part: "body", Match: "a", Replace: "b", Position: 1}, {Enabled: true, Part: "body", Match: "b", Replace: "c", Position: 0}, } // Position 0 runs first: "aaa" -[b->c, no match]-> "aaa" -[a->b]-> "bbb" got := ApplyBody(body, rs) if string(got) != "bbb" { t.Errorf("ApplyBody = %q, want %q", got, "bbb") } } func TestApplyHeadersAddsRemovesHeader(t *testing.T) { h := http.Header{"Host": []string{"example.com"}} rs := []Rule{{Enabled: true, Part: "header", Match: "Host: example.com", Replace: "Host: example.com\r\nX-Injected: 1"}} got := ApplyHeaders(h, rs) if got.Get("X-Injected") != "1" { t.Errorf("expected X-Injected header to be added, got %+v", got) } } func TestApplyHeadersInvalidRegexLeavesUnchanged(t *testing.T) { h := http.Header{"Host": []string{"example.com"}} rs := []Rule{{Enabled: true, Part: "header", Match: "(unclosed", Replace: "x", IsRegex: true}} got := ApplyHeaders(h, rs) if got.Get("Host") != "example.com" { t.Errorf("expected headers unchanged on invalid regex, got %+v", got) } }