Skip to content

Commit fcc5ce8

Browse files
committed
Add validation for case insensitive header name repetition in filters
1 parent b3cbf26 commit fcc5ce8

File tree

2 files changed

+70
-0
lines changed

2 files changed

+70
-0
lines changed

internal/mode/static/state/graph/httproute.go

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -836,6 +836,20 @@ func validateFilterHeaderModifierFields(
836836
) field.ErrorList {
837837
var allErrs field.ErrorList
838838

839+
// Ensure that the header names are case-insensitive unique
840+
allErrs = append(allErrs, validateRequestHeadersCaseInsensitiveUnique(
841+
headerModifier.Add,
842+
headerModifierPath.Child("add"))...,
843+
)
844+
allErrs = append(allErrs, validateRequestHeadersCaseInsensitiveUnique(
845+
headerModifier.Set,
846+
headerModifierPath.Child("set"))...,
847+
)
848+
allErrs = append(allErrs, validateRequestHeaderStringCaseInsensitiveUnique(
849+
headerModifier.Remove,
850+
headerModifierPath.Child("remove"))...,
851+
)
852+
839853
for _, h := range headerModifier.Add {
840854
if err := validator.ValidateRequestHeaderName(string(h.Name)); err != nil {
841855
valErr := field.Invalid(headerModifierPath.Child("add"), h, err.Error())
@@ -865,3 +879,40 @@ func validateFilterHeaderModifierFields(
865879

866880
return allErrs
867881
}
882+
883+
func validateRequestHeadersCaseInsensitiveUnique(
884+
headers []v1.HTTPHeader,
885+
path *field.Path,
886+
) field.ErrorList {
887+
var allErrs field.ErrorList
888+
889+
seen := make(map[string]struct{})
890+
891+
for _, h := range headers {
892+
name := strings.ToLower(string(h.Name))
893+
if _, exists := seen[name]; exists {
894+
valErr := field.Invalid(path, h, "header name is not unique")
895+
allErrs = append(allErrs, valErr)
896+
}
897+
seen[name] = struct{}{}
898+
}
899+
900+
return allErrs
901+
}
902+
903+
func validateRequestHeaderStringCaseInsensitiveUnique(headers []string, path *field.Path) field.ErrorList {
904+
var allErrs field.ErrorList
905+
906+
seen := make(map[string]struct{})
907+
908+
for _, h := range headers {
909+
name := strings.ToLower(h)
910+
if _, exists := seen[name]; exists {
911+
valErr := field.Invalid(path, h, "header name is not unique")
912+
allErrs = append(allErrs, valErr)
913+
}
914+
seen[name] = struct{}{}
915+
}
916+
917+
return allErrs
918+
}

internal/mode/static/state/graph/httproute_test.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2388,6 +2388,25 @@ func TestValidateFilterRequestHeaderModifier(t *testing.T) {
23882388
expectErrCount: 7,
23892389
name: "request header modifier filter all fields invalid",
23902390
},
2391+
{
2392+
validator: createAllValidValidator(),
2393+
filter: gatewayv1.HTTPRouteFilter{
2394+
Type: gatewayv1.HTTPRouteFilterRequestHeaderModifier,
2395+
RequestHeaderModifier: &gatewayv1.HTTPHeaderFilter{
2396+
Set: []gatewayv1.HTTPHeader{
2397+
{Name: "MyBespokeHeader", Value: "my-value"},
2398+
{Name: "mYbespokeHEader", Value: "duplicate"},
2399+
},
2400+
Add: []gatewayv1.HTTPHeader{
2401+
{Name: "Accept-Encoding", Value: "gzip"},
2402+
{Name: "accept-encodING", Value: "gzip"},
2403+
},
2404+
Remove: []string{"Cache-Control", "cache-control"},
2405+
},
2406+
},
2407+
expectErrCount: 3,
2408+
name: "request header modifier filter not unique names",
2409+
},
23912410
}
23922411

23932412
filterPath := field.NewPath("test")

0 commit comments

Comments
 (0)