package responseheaders import ( "net/http" "testing" "github.com/user-management-system/internal/config" ) func TestFilterHeadersDisabledUsesDefaultAllowlist(t *testing.T) { src := http.Header{} src.Add("Content-Type", "application/json") src.Add("X-Request-Id", "req-123") src.Add("X-Test", "ok") src.Add("Connection", "keep-alive") src.Add("Content-Length", "123") cfg := config.ResponseHeaderConfig{ Enabled: false, ForceRemove: []string{"x-request-id"}, } filtered := FilterHeaders(src, CompileHeaderFilter(cfg)) if filtered.Get("Content-Type") != "application/json" { t.Fatalf("expected Content-Type passthrough, got %q", filtered.Get("Content-Type")) } if filtered.Get("X-Request-Id") != "req-123" { t.Fatalf("expected X-Request-Id allowed, got %q", filtered.Get("X-Request-Id")) } if filtered.Get("X-Test") != "" { t.Fatalf("expected X-Test removed, got %q", filtered.Get("X-Test")) } if filtered.Get("Connection") != "" { t.Fatalf("expected Connection to be removed, got %q", filtered.Get("Connection")) } if filtered.Get("Content-Length") != "" { t.Fatalf("expected Content-Length to be removed, got %q", filtered.Get("Content-Length")) } } func TestFilterHeadersEnabledUsesAllowlist(t *testing.T) { src := http.Header{} src.Add("Content-Type", "application/json") src.Add("X-Extra", "ok") src.Add("X-Remove", "nope") src.Add("X-Blocked", "nope") cfg := config.ResponseHeaderConfig{ Enabled: true, AdditionalAllowed: []string{"x-extra"}, ForceRemove: []string{"x-remove"}, } filtered := FilterHeaders(src, CompileHeaderFilter(cfg)) if filtered.Get("Content-Type") != "application/json" { t.Fatalf("expected Content-Type allowed, got %q", filtered.Get("Content-Type")) } if filtered.Get("X-Extra") != "ok" { t.Fatalf("expected X-Extra allowed, got %q", filtered.Get("X-Extra")) } if filtered.Get("X-Remove") != "" { t.Fatalf("expected X-Remove removed, got %q", filtered.Get("X-Remove")) } if filtered.Get("X-Blocked") != "" { t.Fatalf("expected X-Blocked removed, got %q", filtered.Get("X-Blocked")) } } func TestFilterHeadersNilFilter(t *testing.T) { src := http.Header{} src.Add("Content-Type", "application/json") src.Add("X-Request-Id", "req-123") src.Add("X-Unknown", "unknown") // nil filter should use default compiled filter filtered := FilterHeaders(src, nil) if filtered.Get("Content-Type") != "application/json" { t.Fatalf("expected Content-Type allowed, got %q", filtered.Get("Content-Type")) } if filtered.Get("X-Request-Id") != "req-123" { t.Fatalf("expected X-Request-Id allowed, got %q", filtered.Get("X-Request-Id")) } if filtered.Get("X-Unknown") != "" { t.Fatalf("expected X-Unknown removed, got %q", filtered.Get("X-Unknown")) } } func TestCompileHeaderFilterEmptyStrings(t *testing.T) { cfg := config.ResponseHeaderConfig{ Enabled: true, AdditionalAllowed: []string{"", " ", "valid"}, ForceRemove: []string{"", " "}, } filter := CompileHeaderFilter(cfg) if filter == nil { t.Fatal("expected filter to be created") } // Empty strings should be filtered out src := http.Header{} src.Add("Valid", "value") filtered := FilterHeaders(src, filter) if filtered.Get("Valid") != "value" { t.Fatalf("expected Valid header to pass through") } } func TestWriteFilteredHeaders(t *testing.T) { src := http.Header{} src.Add("Content-Type", "application/json") src.Add("X-Custom", "custom") dst := http.Header{} WriteFilteredHeaders(dst, src, nil) if dst.Get("Content-Type") != "application/json" { t.Fatalf("expected Content-Type written to dst") } if dst.Get("X-Custom") != "" { t.Fatalf("expected X-Custom filtered out") } } func TestFilterHeadersMultipleValues(t *testing.T) { src := http.Header{} src.Add("Content-Type", "application/json") src.Add("Vary", "Accept") src.Add("Vary", "Accept-Encoding") filtered := FilterHeaders(src, nil) varyValues := filtered["Vary"] if len(varyValues) != 2 { t.Fatalf("expected 2 Vary values, got %d", len(varyValues)) } }