@@ -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- 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(
509508func 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 {
658657func 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,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 , path string ) 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.
9811009func 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
9901022func createDefaultRootLocation () http.Location {
9911023 return http.Location {
992- Path : "/" ,
1024+ Path : "= /" ,
9931025 Return : & http.Return {Code : http .StatusNotFound },
9941026 }
9951027}
0 commit comments