Skip to content

Commit 20683af

Browse files
authored
Merge pull request #1171 from robscott/validate-path-modifier
Adding validation to ensure prefix path match exists for path modifier
2 parents c5bca72 + 65271b1 commit 20683af

File tree

2 files changed

+72
-7
lines changed

2 files changed

+72
-7
lines changed

apis/v1alpha2/validation/httproute.go

+24-6
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,9 @@ func ValidateHTTPRoute(route *gatewayv1a2.HTTPRoute) field.ErrorList {
4848
func validateHTTPRouteSpec(spec *gatewayv1a2.HTTPRouteSpec, path *field.Path) field.ErrorList {
4949
var errs field.ErrorList
5050
for i, rule := range spec.Rules {
51-
errs = append(errs, validateHTTPRouteFilters(rule.Filters, path.Child("rules").Index(i))...)
51+
errs = append(errs, validateHTTPRouteFilters(rule.Filters, rule.Matches, path.Child("rules").Index(i))...)
5252
for j, backendRef := range rule.BackendRefs {
53-
errs = append(errs, validateHTTPRouteFilters(backendRef.Filters, path.Child("rules").Index(i).Child("backendsrefs").Index(j))...)
53+
errs = append(errs, validateHTTPRouteFilters(backendRef.Filters, rule.Matches, path.Child("rules").Index(i).Child("backendsrefs").Index(j))...)
5454
}
5555
for j, m := range rule.Matches {
5656
if m.Path != nil {
@@ -90,17 +90,17 @@ func validateHTTPRouteBackendServicePorts(rules []gatewayv1a2.HTTPRouteRule, pat
9090

9191
// validateHTTPRouteFilters validates that a list of core and extended filters
9292
// is used at most once and that the filter type matches its value
93-
func validateHTTPRouteFilters(filters []gatewayv1a2.HTTPRouteFilter, path *field.Path) field.ErrorList {
93+
func validateHTTPRouteFilters(filters []gatewayv1a2.HTTPRouteFilter, matches []gatewayv1a2.HTTPRouteMatch, path *field.Path) field.ErrorList {
9494
var errs field.ErrorList
9595
counts := map[gatewayv1a2.HTTPRouteFilterType]int{}
9696

9797
for i, filter := range filters {
9898
counts[filter.Type]++
9999
if filter.RequestRedirect != nil && filter.RequestRedirect.Path != nil {
100-
errs = append(errs, validateHTTPPathModifier(*filter.RequestRedirect.Path, path.Index(i).Child("requestRedirect", "path"))...)
100+
errs = append(errs, validateHTTPPathModifier(*filter.RequestRedirect.Path, matches, path.Index(i).Child("requestRedirect", "path"))...)
101101
}
102102
if filter.URLRewrite != nil && filter.URLRewrite.Path != nil {
103-
errs = append(errs, validateHTTPPathModifier(*filter.URLRewrite.Path, path.Index(i).Child("urlRewrite", "path"))...)
103+
errs = append(errs, validateHTTPPathModifier(*filter.URLRewrite.Path, matches, path.Index(i).Child("urlRewrite", "path"))...)
104104
}
105105
errs = append(errs, validateHTTPRouteFilterTypeMatchesValue(filter, path.Index(i))...)
106106
}
@@ -198,7 +198,7 @@ func validateHTTPRouteFilterTypeMatchesValue(filter gatewayv1a2.HTTPRouteFilter,
198198

199199
// validateHTTPPathModifier validates that only the expected fields are set in a
200200
// path modifier.
201-
func validateHTTPPathModifier(modifier gatewayv1a2.HTTPPathModifier, path *field.Path) field.ErrorList {
201+
func validateHTTPPathModifier(modifier gatewayv1a2.HTTPPathModifier, matches []gatewayv1a2.HTTPRouteMatch, path *field.Path) field.ErrorList {
202202
var errs field.ErrorList
203203
if modifier.ReplaceFullPath != nil && modifier.Type != gatewayv1a2.FullPathHTTPPathModifier {
204204
errs = append(errs, field.Invalid(path, modifier.ReplaceFullPath, "must be nil if the HTTPRouteFilter.Type is not ReplaceFullPath"))
@@ -212,5 +212,23 @@ func validateHTTPPathModifier(modifier gatewayv1a2.HTTPPathModifier, path *field
212212
if modifier.ReplacePrefixMatch == nil && modifier.Type == gatewayv1a2.PrefixMatchHTTPPathModifier {
213213
errs = append(errs, field.Invalid(path, modifier.ReplacePrefixMatch, "must not be nil if the HTTPRouteFilter.Type is ReplacePrefixMatch"))
214214
}
215+
216+
if modifier.Type == gatewayv1a2.PrefixMatchHTTPPathModifier && modifier.ReplacePrefixMatch != nil {
217+
if !hasExactlyOnePrefixMatch(matches) {
218+
errs = append(errs, field.Invalid(path, modifier.ReplacePrefixMatch, "exactly one PathPrefix match must be specified to use this path modifier"))
219+
}
220+
}
215221
return errs
216222
}
223+
224+
func hasExactlyOnePrefixMatch(matches []gatewayv1a2.HTTPRouteMatch) bool {
225+
if len(matches) != 1 || matches[0].Path == nil {
226+
return false
227+
}
228+
pathMatchType := matches[0].Path.Type
229+
if *pathMatchType != gatewayv1a2.PathMatchPathPrefix {
230+
return false
231+
}
232+
233+
return true
234+
}

apis/v1alpha2/validation/httproute_test.go

+48-1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ import (
3030
func TestValidateHTTPRoute(t *testing.T) {
3131
testService := gatewayv1a2.ObjectName("test-service")
3232
specialService := gatewayv1a2.ObjectName("special-service")
33+
pathPrefixMatchType := gatewayv1a2.PathMatchPathPrefix
34+
3335
tests := []struct {
3436
name string
3537
rules []gatewayv1a2.HTTPRouteRule
@@ -329,6 +331,51 @@ func TestValidateHTTPRoute(t *testing.T) {
329331
name: "valid rewrite path modifier",
330332
errCount: 0,
331333
rules: []gatewayv1a2.HTTPRouteRule{{
334+
Matches: []gatewayv1a2.HTTPRouteMatch{{
335+
Path: &gatewayv1a2.HTTPPathMatch{
336+
Type: &pathPrefixMatchType,
337+
Value: utilpointer.String("/bar"),
338+
},
339+
}},
340+
Filters: []gatewayv1a2.HTTPRouteFilter{{
341+
Type: gatewayv1a2.HTTPRouteFilterURLRewrite,
342+
URLRewrite: &gatewayv1a2.HTTPURLRewriteFilter{
343+
Path: &gatewayv1a2.HTTPPathModifier{
344+
Type: gatewayv1a2.PrefixMatchHTTPPathModifier,
345+
ReplacePrefixMatch: utilpointer.String("foo"),
346+
},
347+
},
348+
}},
349+
}},
350+
}, {
351+
name: "rewrite path modifier missing path match",
352+
errCount: 1,
353+
rules: []gatewayv1a2.HTTPRouteRule{{
354+
Filters: []gatewayv1a2.HTTPRouteFilter{{
355+
Type: gatewayv1a2.HTTPRouteFilterURLRewrite,
356+
URLRewrite: &gatewayv1a2.HTTPURLRewriteFilter{
357+
Path: &gatewayv1a2.HTTPPathModifier{
358+
Type: gatewayv1a2.PrefixMatchHTTPPathModifier,
359+
ReplacePrefixMatch: utilpointer.String("foo"),
360+
},
361+
},
362+
}},
363+
}},
364+
}, {
365+
name: "rewrite path too many matches",
366+
errCount: 1,
367+
rules: []gatewayv1a2.HTTPRouteRule{{
368+
Matches: []gatewayv1a2.HTTPRouteMatch{{
369+
Path: &gatewayv1a2.HTTPPathMatch{
370+
Type: &pathPrefixMatchType,
371+
Value: utilpointer.String("/foo"),
372+
},
373+
}, {
374+
Path: &gatewayv1a2.HTTPPathMatch{
375+
Type: &pathPrefixMatchType,
376+
Value: utilpointer.String("/bar"),
377+
},
378+
}},
332379
Filters: []gatewayv1a2.HTTPRouteFilter{{
333380
Type: gatewayv1a2.HTTPRouteFilterURLRewrite,
334381
URLRewrite: &gatewayv1a2.HTTPURLRewriteFilter{
@@ -355,7 +402,7 @@ func TestValidateHTTPRoute(t *testing.T) {
355402
}},
356403
}, {
357404
name: "rewrite and redirect filters combined (invalid)",
358-
errCount: 1,
405+
errCount: 3,
359406
rules: []gatewayv1a2.HTTPRouteRule{{
360407
Filters: []gatewayv1a2.HTTPRouteFilter{{
361408
Type: gatewayv1a2.HTTPRouteFilterURLRewrite,

0 commit comments

Comments
 (0)