Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 6d0d8a6

Browse files
committed
Add regex support for path matching
Problem: As regex path matching is missing support for NGF. Solution: Add support for regex path matching, only allow a full path rewrite/redirect after the regex path match. Testing: Add additional unit test case for regex path match.
1 parent 4ac413b commit 6d0d8a6

File tree

14 files changed

+691
-132
lines changed

14 files changed

+691
-132
lines changed

‎internal/controller/nginx/config/servers.go‎

Lines changed: 55 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -414,7 +414,7 @@ func initializeExternalLocations(
414414
}
415415
if !exactPathExists {
416416
externalLocExact := http.Location{
417-
Path: exactPath(externalLocPath),
417+
Path: exactPath(rule.Path),
418418
Type: locType,
419419
}
420420
extLocations = append(extLocations, externalLocExact)
@@ -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-
pathstring,
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-
pathstring,
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-
pathstring,
660+
pathRule dataplane.PathRule,
662661
) (*http.Return, *rewriteConfig) {
663662
if filter == nil {
664663
return nil, nil
@@ -702,7 +701,12 @@ func createReturnAndRewriteConfigForRedirectFilter(
702701

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

@@ -712,19 +716,27 @@ func createReturnAndRewriteConfigForRedirectFilter(
712716
}, rewrites
713717
}
714718

715-
func createMainRewriteForFilters(pathModifier *dataplane.HTTPPathModifier, pathstring) string {
719+
func createMainRewriteForFilters(pathModifier *dataplane.HTTPPathModifier, pathRule dataplane.PathRule) string {
716720
var mainRewrite string
717721
switch pathModifier.Type {
718722
case dataplane.ReplaceFullPath:
719-
mainRewrite = fmt.Sprintf("^ %s", pathModifier.Replacement)
723+
// should we keep the args here?
724+
mainRewrite = fmt.Sprintf("^ %s$is_args$args", pathModifier.Replacement)
720725
case dataplane.ReplacePrefixMatch:
726+
// ReplacePrefixMatch is only compatible with a PathPrefix HTTPRouteMatch.
727+
// ReplaceFullPath is compatible with PathTypeExact/PathTypePrefix/PathTypeRegularExpression HTTPRouteMatch.
728+
// see https://gateway-api.sigs.k8s.io/reference/spec/?h=replaceprefixmatch#httppathmodifier
729+
if pathRule.PathType != dataplane.PathTypePrefix {
730+
return ""
731+
}
732+
721733
filterPrefix := pathModifier.Replacement
722734
if filterPrefix == "" {
723735
filterPrefix = "/"
724736
}
725737

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

740752
// if configured prefix ends in / we won't capture it for a request (since it's not in the regex),
741753
// so append it to the replacement prefix if the replacement prefix doesn't already end in /
742-
if strings.HasSuffix(path, "/") && !strings.HasSuffix(filterPrefix, "/") {
754+
if strings.HasSuffix(pathRule.Path, "/") && !strings.HasSuffix(filterPrefix, "/") {
743755
replacement = fmt.Sprintf("%s/1ドル?$args?", filterPrefix)
744756
}
745757

@@ -749,7 +761,10 @@ func createMainRewriteForFilters(pathModifier *dataplane.HTTPPathModifier, path
749761
return mainRewrite
750762
}
751763

752-
func createRewritesValForRewriteFilter(filter *dataplane.HTTPURLRewriteFilter, path string) *rewriteConfig {
764+
func createRewritesValForRewriteFilter(
765+
filter *dataplane.HTTPURLRewriteFilter,
766+
pathRule dataplane.PathRule,
767+
) *rewriteConfig {
753768
if filter == nil {
754769
return nil
755770
}
@@ -758,8 +773,13 @@ func createRewritesValForRewriteFilter(filter *dataplane.HTTPURLRewriteFilter, p
758773
if filter.Path != nil {
759774
rewrites.InternalRewrite = "^ $request_uri"
760775

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))
776+
mainRewrite := createMainRewriteForFilters(filter.Path, pathRule)
777+
if mainRewrite == "" {
778+
// Invalid configuration for the rewrite filter
779+
return nil
780+
}
781+
// For URLRewriteFilter, add "break" to prevent further processing of the request.
782+
rewrites.MainRewrite = fmt.Sprintf("%s break", mainRewrite)
763783
}
764784

765785
return rewrites
@@ -977,19 +997,31 @@ func exactPath(path string) string {
977997
return fmt.Sprintf("= %s", path)
978998
}
979999

1000+
func prefixPath(path string) string {
1001+
return fmt.Sprintf("^~ %s", path)
1002+
}
1003+
1004+
func regularExpressionPath(path string) string {
1005+
return fmt.Sprintf("~ %s", path)
1006+
}
1007+
9801008
// createPath builds the location path depending on the path type.
9811009
func createPath(rule dataplane.PathRule) string {
9821010
switch rule.PathType {
9831011
case dataplane.PathTypeExact:
9841012
return exactPath(rule.Path)
1013+
case dataplane.PathTypePrefix:
1014+
return prefixPath(rule.Path)
1015+
case dataplane.PathTypeRegularExpression:
1016+
return regularExpressionPath(rule.Path)
9851017
default:
986-
return rule.Path
1018+
return ""// should never happen because path type is validated earlier
9871019
}
9881020
}
9891021

9901022
func createDefaultRootLocation() http.Location {
9911023
return http.Location{
992-
Path: "/",
1024+
Path: "= /",
9931025
Return: &http.Return{Code: http.StatusNotFound},
9941026
}
9951027
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /