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 895c15c

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 2f19ba8 commit 895c15c

File tree

14 files changed

+696
-125
lines changed

14 files changed

+696
-125
lines changed

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

Lines changed: 45 additions & 22 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,26 @@ 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:
719723
mainRewrite = fmt.Sprintf("^ %s", pathModifier.Replacement)
720724
case dataplane.ReplacePrefixMatch:
725+
// ReplacePrefixMatch is only compatible with a PathPrefix HTTPRouteMatch.
726+
// ReplaceFullPath is compatible with PathTypeExact/PathTypePrefix/PathTypeRegularExpression HTTPRouteMatch.
727+
// see https://gateway-api.sigs.k8s.io/reference/spec/?h=replaceprefixmatch#httppathmodifier
728+
if pathRule.PathType != dataplane.PathTypePrefix {
729+
return ""
730+
}
731+
721732
filterPrefix := pathModifier.Replacement
722733
if filterPrefix == "" {
723734
filterPrefix = "/"
724735
}
725736

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

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

@@ -749,7 +760,10 @@ func createMainRewriteForFilters(pathModifier *dataplane.HTTPPathModifier, path
749760
return mainRewrite
750761
}
751762

752-
func createRewritesValForRewriteFilter(filter *dataplane.HTTPURLRewriteFilter, path string) *rewriteConfig {
763+
func createRewritesValForRewriteFilter(
764+
filter *dataplane.HTTPURLRewriteFilter,
765+
pathRule dataplane.PathRule,
766+
) *rewriteConfig {
753767
if filter == nil {
754768
return nil
755769
}
@@ -758,8 +772,13 @@ func createRewritesValForRewriteFilter(filter *dataplane.HTTPURLRewriteFilter, p
758772
if filter.Path != nil {
759773
rewrites.InternalRewrite = "^ $request_uri"
760774

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

765784
return rewrites
@@ -982,14 +1001,18 @@ func createPath(rule dataplane.PathRule) string {
9821001
switch rule.PathType {
9831002
case dataplane.PathTypeExact:
9841003
return exactPath(rule.Path)
1004+
case dataplane.PathTypePrefix:
1005+
return fmt.Sprintf("^~ %s", rule.Path)
1006+
case dataplane.PathTypeRegularExpression:
1007+
return fmt.Sprintf("~ %s", rule.Path)
9851008
default:
986-
return rule.Path
1009+
return ""// should never happen because path type is validated earlier
9871010
}
9881011
}
9891012

9901013
func createDefaultRootLocation() http.Location {
9911014
return http.Location{
992-
Path: "/",
1015+
Path: "= /",
9931016
Return: &http.Return{Code: http.StatusNotFound},
9941017
}
9951018
}

0 commit comments

Comments
(0)

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