Skip to content

Commit 63c06fe

Browse files
committed
Add regex for path matching
1 parent 8118a83 commit 63c06fe

File tree

3 files changed

+284
-45
lines changed

3 files changed

+284
-45
lines changed

internal/controller/nginx/config/servers.go

Lines changed: 39 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -458,23 +458,22 @@ func updateLocation(
458458
mirrorPercentage *float64,
459459
) http.Location {
460460
filters := matchRule.Filters
461-
path := pathRule.Path
462461
grpc := pathRule.GRPC
463462

464463
if filters.InvalidFilter != nil {
465464
location.Return = &http.Return{Code: http.StatusInternalServerError}
466465
return location
467466
}
468467

469-
location = updateLocationMirrorRoute(location, path, grpc)
468+
location = updateLocationMirrorRoute(location, pathRule.Path, grpc)
470469
location.Includes = append(location.Includes, createIncludesFromLocationSnippetsFilters(filters.SnippetsFilters)...)
471470

472471
if filters.RequestRedirect != nil {
473-
return updateLocationRedirectFilter(location, filters.RequestRedirect, listenerPort, path)
472+
return updateLocationRedirectFilter(location, filters.RequestRedirect, listenerPort, pathRule)
474473
}
475474

476-
location = updateLocationRewriteFilter(location, filters.RequestURLRewrite, path)
477-
location = updateLocationMirrorFilters(location, filters.RequestMirrors, path, mirrorPercentage)
475+
location = updateLocationRewriteFilter(location, filters.RequestURLRewrite, pathRule)
476+
location = updateLocationMirrorFilters(location, filters.RequestMirrors, pathRule.Path, mirrorPercentage)
478477
location = updateLocationProxySettings(location, matchRule, grpc, keepAliveCheck)
479478

480479
return location
@@ -495,9 +494,9 @@ func updateLocationRedirectFilter(
495494
location http.Location,
496495
redirectFilter *dataplane.HTTPRequestRedirectFilter,
497496
listenerPort int32,
498-
path string,
497+
pathRule dataplane.PathRule,
499498
) http.Location {
500-
ret, rewrite := createReturnAndRewriteConfigForRedirectFilter(redirectFilter, listenerPort, path)
499+
ret, rewrite := createReturnAndRewriteConfigForRedirectFilter(redirectFilter, listenerPort, pathRule)
501500
if rewrite.MainRewrite != "" {
502501
location.Rewrites = append(location.Rewrites, rewrite.MainRewrite)
503502
}
@@ -509,9 +508,9 @@ func updateLocationRedirectFilter(
509508
func updateLocationRewriteFilter(
510509
location http.Location,
511510
rewriteFilter *dataplane.HTTPURLRewriteFilter,
512-
path string,
511+
pathRule dataplane.PathRule,
513512
) http.Location {
514-
rewrites := createRewritesValForRewriteFilter(rewriteFilter, path)
513+
rewrites := createRewritesValForRewriteFilter(rewriteFilter, pathRule)
515514
if rewrites != nil {
516515
if location.Type == http.InternalLocationType && rewrites.InternalRewrite != "" {
517516
location.Rewrites = append(location.Rewrites, rewrites.InternalRewrite)
@@ -658,7 +657,7 @@ func createProxySSLVerify(v *dataplane.VerifyTLS) *http.ProxySSLVerify {
658657
func createReturnAndRewriteConfigForRedirectFilter(
659658
filter *dataplane.HTTPRequestRedirectFilter,
660659
listenerPort int32,
661-
path string,
660+
pathRule dataplane.PathRule,
662661
) (*http.Return, *rewriteConfig) {
663662
if filter == nil {
664663
return nil, nil
@@ -702,7 +701,13 @@ func createReturnAndRewriteConfigForRedirectFilter(
702701

703702
rewrites := &rewriteConfig{}
704703
if filter.Path != nil {
705-
rewrites.MainRewrite = createMainRewriteForFilters(filter.Path, path)
704+
705+
if mainRewrite := createMainRewriteForFilters(filter.Path, pathRule); mainRewrite == "" {
706+
// Invalid configuration for the rewrite filter
707+
return nil, nil
708+
} else {
709+
rewrites.MainRewrite = mainRewrite
710+
}
706711
body = fmt.Sprintf("%s://%s$uri$is_args$args", scheme, hostnamePort)
707712
}
708713

@@ -712,19 +717,27 @@ func createReturnAndRewriteConfigForRedirectFilter(
712717
}, rewrites
713718
}
714719

715-
func createMainRewriteForFilters(pathModifier *dataplane.HTTPPathModifier, path string) string {
720+
func createMainRewriteForFilters(pathModifier *dataplane.HTTPPathModifier, pathRule dataplane.PathRule) string {
716721
var mainRewrite string
717722
switch pathModifier.Type {
718723
case dataplane.ReplaceFullPath:
719-
mainRewrite = fmt.Sprintf("^ %s", pathModifier.Replacement)
724+
// should we keep the args here?
725+
mainRewrite = fmt.Sprintf("^ %s$is_args$args", pathModifier.Replacement)
720726
case dataplane.ReplacePrefixMatch:
727+
// ReplacePrefixMatch is only compatible with a PathPrefix HTTPRouteMatch.
728+
// ReplaceFullPath is compatible with PathTypeExact/PathTypePrefix/PathTypeRegularExpression HTTPRouteMatch.
729+
// see https://gateway-api.sigs.k8s.io/reference/spec/?h=replaceprefixmatch#httppathmodifier
730+
if pathRule.PathType != dataplane.PathTypePrefix {
731+
return ""
732+
}
733+
721734
filterPrefix := pathModifier.Replacement
722735
if filterPrefix == "" {
723736
filterPrefix = "/"
724737
}
725738

726739
// capture everything following the configured prefix up to the first ?, if present.
727-
regex := fmt.Sprintf("^%s([^?]*)?", path)
740+
regex := fmt.Sprintf("^%s([^?]*)?", pathRule.Path)
728741
// replace the configured prefix with the filter prefix, append the captured segment,
729742
// and include the request arguments stored in nginx variable $args.
730743
// https://nginx.org/en/docs/http/ngx_http_core_module.html#var_args
@@ -733,13 +746,13 @@ func createMainRewriteForFilters(pathModifier *dataplane.HTTPPathModifier, path
733746
// if configured prefix does not end in /, but replacement prefix does end in /,
734747
// then make sure that we *require* but *don't capture* a trailing slash in the request,
735748
// otherwise we'll get duplicate slashes in the full replacement
736-
if strings.HasSuffix(filterPrefix, "/") && !strings.HasSuffix(path, "/") {
737-
regex = fmt.Sprintf("^%s(?:/([^?]*))?", path)
749+
if strings.HasSuffix(filterPrefix, "/") && !strings.HasSuffix(pathRule.Path, "/") {
750+
regex = fmt.Sprintf("^%s(?:/([^?]*))?", pathRule.Path)
738751
}
739752

740753
// if configured prefix ends in / we won't capture it for a request (since it's not in the regex),
741754
// so append it to the replacement prefix if the replacement prefix doesn't already end in /
742-
if strings.HasSuffix(path, "/") && !strings.HasSuffix(filterPrefix, "/") {
755+
if strings.HasSuffix(pathRule.Path, "/") && !strings.HasSuffix(filterPrefix, "/") {
743756
replacement = fmt.Sprintf("%s/$1?$args?", filterPrefix)
744757
}
745758

@@ -749,7 +762,7 @@ func createMainRewriteForFilters(pathModifier *dataplane.HTTPPathModifier, path
749762
return mainRewrite
750763
}
751764

752-
func createRewritesValForRewriteFilter(filter *dataplane.HTTPURLRewriteFilter, path string) *rewriteConfig {
765+
func createRewritesValForRewriteFilter(filter *dataplane.HTTPURLRewriteFilter, pathRule dataplane.PathRule) *rewriteConfig {
753766
if filter == nil {
754767
return nil
755768
}
@@ -758,8 +771,14 @@ func createRewritesValForRewriteFilter(filter *dataplane.HTTPURLRewriteFilter, p
758771
if filter.Path != nil {
759772
rewrites.InternalRewrite = "^ $request_uri"
760773

761-
// for URLRewriteFilter, we add a break to the rewrite to prevent further processing of the request.
762-
rewrites.MainRewrite = fmt.Sprintf("%s break", createMainRewriteForFilters(filter.Path, path))
774+
mainRewrite := createMainRewriteForFilters(filter.Path, pathRule)
775+
if mainRewrite == "" {
776+
// Invalid configuration for the rewrite filter
777+
return nil
778+
}
779+
// For URLRewriteFilter, add "break" to prevent further processing of the request.
780+
rewrites.MainRewrite = fmt.Sprintf("%s break", mainRewrite)
781+
763782
}
764783

765784
return rewrites

0 commit comments

Comments
 (0)