-
Notifications
You must be signed in to change notification settings - Fork 136
Add regex for path matching #3874
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -414,7 +414,7 @@ func initializeExternalLocations( | |
} | ||
if !exactPathExists { | ||
externalLocExact := http.Location{ | ||
Path: exactPath(externalLocPath), | ||
Path: exactPath(rule.Path), | ||
Type: locType, | ||
} | ||
extLocations = append(extLocations, externalLocExact) | ||
|
@@ -458,23 +458,22 @@ func updateLocation( | |
mirrorPercentage *float64, | ||
) http.Location { | ||
filters := matchRule.Filters | ||
path := pathRule.Path | ||
grpc := pathRule.GRPC | ||
|
||
if filters.InvalidFilter != nil { | ||
location.Return = &http.Return{Code: http.StatusInternalServerError} | ||
return location | ||
} | ||
|
||
location = updateLocationMirrorRoute(location, path, grpc) | ||
location = updateLocationMirrorRoute(location, pathRule.Path, grpc) | ||
location.Includes = append(location.Includes, createIncludesFromLocationSnippetsFilters(filters.SnippetsFilters)...) | ||
|
||
if filters.RequestRedirect != nil { | ||
return updateLocationRedirectFilter(location, filters.RequestRedirect, listenerPort, path) | ||
return updateLocationRedirectFilter(location, filters.RequestRedirect, listenerPort, pathRule) | ||
} | ||
|
||
location = updateLocationRewriteFilter(location, filters.RequestURLRewrite, path) | ||
location = updateLocationMirrorFilters(location, filters.RequestMirrors, path, mirrorPercentage) | ||
location = updateLocationRewriteFilter(location, filters.RequestURLRewrite, pathRule) | ||
location = updateLocationMirrorFilters(location, filters.RequestMirrors, pathRule.Path, mirrorPercentage) | ||
location = updateLocationProxySettings(location, matchRule, grpc, keepAliveCheck) | ||
|
||
return location | ||
|
@@ -495,9 +494,9 @@ func updateLocationRedirectFilter( | |
location http.Location, | ||
redirectFilter *dataplane.HTTPRequestRedirectFilter, | ||
listenerPort int32, | ||
path string, | ||
pathRule dataplane.PathRule, | ||
) http.Location { | ||
ret, rewrite := createReturnAndRewriteConfigForRedirectFilter(redirectFilter, listenerPort, path) | ||
ret, rewrite := createReturnAndRewriteConfigForRedirectFilter(redirectFilter, listenerPort, pathRule) | ||
if rewrite.MainRewrite != "" { | ||
location.Rewrites = append(location.Rewrites, rewrite.MainRewrite) | ||
} | ||
|
@@ -509,9 +508,9 @@ func updateLocationRedirectFilter( | |
func updateLocationRewriteFilter( | ||
location http.Location, | ||
rewriteFilter *dataplane.HTTPURLRewriteFilter, | ||
path string, | ||
pathRule dataplane.PathRule, | ||
) http.Location { | ||
rewrites := createRewritesValForRewriteFilter(rewriteFilter, path) | ||
rewrites := createRewritesValForRewriteFilter(rewriteFilter, pathRule) | ||
if rewrites != nil { | ||
if location.Type == http.InternalLocationType && rewrites.InternalRewrite != "" { | ||
location.Rewrites = append(location.Rewrites, rewrites.InternalRewrite) | ||
|
@@ -658,7 +657,7 @@ func createProxySSLVerify(v *dataplane.VerifyTLS) *http.ProxySSLVerify { | |
func createReturnAndRewriteConfigForRedirectFilter( | ||
filter *dataplane.HTTPRequestRedirectFilter, | ||
listenerPort int32, | ||
path string, | ||
pathRule dataplane.PathRule, | ||
) (*http.Return, *rewriteConfig) { | ||
if filter == nil { | ||
return nil, nil | ||
|
@@ -702,7 +701,12 @@ func createReturnAndRewriteConfigForRedirectFilter( | |
|
||
rewrites := &rewriteConfig{} | ||
if filter.Path != nil { | ||
rewrites.MainRewrite = createMainRewriteForFilters(filter.Path, path) | ||
mainRewrite := createMainRewriteForFilters(filter.Path, pathRule) | ||
if mainRewrite == "" { | ||
// Invalid configuration for the rewrite filter | ||
return nil, nil | ||
} | ||
rewrites.MainRewrite = mainRewrite | ||
body = fmt.Sprintf("%s://%s$uri$is_args$args", scheme, hostnamePort) | ||
} | ||
|
||
|
@@ -712,19 +716,26 @@ func createReturnAndRewriteConfigForRedirectFilter( | |
}, rewrites | ||
} | ||
|
||
func createMainRewriteForFilters(pathModifier *dataplane.HTTPPathModifier, path string) string { | ||
func createMainRewriteForFilters(pathModifier *dataplane.HTTPPathModifier, pathRule dataplane.PathRule) string { | ||
var mainRewrite string | ||
switch pathModifier.Type { | ||
case dataplane.ReplaceFullPath: | ||
mainRewrite = fmt.Sprintf("^ %s", pathModifier.Replacement) | ||
case dataplane.ReplacePrefixMatch: | ||
// ReplacePrefixMatch is only compatible with a PathPrefix HTTPRouteMatch. | ||
// ReplaceFullPath is compatible with PathTypeExact/PathTypePrefix/PathTypeRegularExpression HTTPRouteMatch. | ||
// see https://gateway-api.sigs.k8s.io/reference/spec/?h=replaceprefixmatch#httppathmodifier | ||
if pathRule.PathType != dataplane.PathTypePrefix { | ||
return "" | ||
} | ||
|
||
filterPrefix := pathModifier.Replacement | ||
if filterPrefix == "" { | ||
filterPrefix = "/" | ||
} | ||
|
||
// capture everything following the configured prefix up to the first ?, if present. | ||
regex := fmt.Sprintf("^%s([^?]*)?", path) | ||
regex := fmt.Sprintf("^%s([^?]*)?", pathRule.Path) | ||
// replace the configured prefix with the filter prefix, append the captured segment, | ||
// and include the request arguments stored in nginx variable $args. | ||
// https://nginx.org/en/docs/http/ngx_http_core_module.html#var_args | ||
|
@@ -733,13 +744,13 @@ func createMainRewriteForFilters(pathModifier *dataplane.HTTPPathModifier, path | |
// if configured prefix does not end in /, but replacement prefix does end in /, | ||
// then make sure that we *require* but *don't capture* a trailing slash in the request, | ||
// otherwise we'll get duplicate slashes in the full replacement | ||
if strings.HasSuffix(filterPrefix, "/") && !strings.HasSuffix(path, "/") { | ||
regex = fmt.Sprintf("^%s(?:/([^?]*))?", path) | ||
if strings.HasSuffix(filterPrefix, "/") && !strings.HasSuffix(pathRule.Path, "/") { | ||
regex = fmt.Sprintf("^%s(?:/([^?]*))?", pathRule.Path) | ||
} | ||
|
||
// if configured prefix ends in / we won't capture it for a request (since it's not in the regex), | ||
// so append it to the replacement prefix if the replacement prefix doesn't already end in / | ||
if strings.HasSuffix(path, "/") && !strings.HasSuffix(filterPrefix, "/") { | ||
if strings.HasSuffix(pathRule.Path, "/") && !strings.HasSuffix(filterPrefix, "/") { | ||
replacement = fmt.Sprintf("%s/1ドル?$args?", filterPrefix) | ||
} | ||
|
||
|
@@ -749,7 +760,10 @@ func createMainRewriteForFilters(pathModifier *dataplane.HTTPPathModifier, path | |
return mainRewrite | ||
} | ||
|
||
func createRewritesValForRewriteFilter(filter *dataplane.HTTPURLRewriteFilter, path string) *rewriteConfig { | ||
func createRewritesValForRewriteFilter( | ||
filter *dataplane.HTTPURLRewriteFilter, | ||
pathRule dataplane.PathRule, | ||
) *rewriteConfig { | ||
if filter == nil { | ||
return nil | ||
} | ||
|
@@ -758,8 +772,13 @@ func createRewritesValForRewriteFilter(filter *dataplane.HTTPURLRewriteFilter, p | |
if filter.Path != nil { | ||
rewrites.InternalRewrite = "^ $request_uri" | ||
|
||
// for URLRewriteFilter, we add a break to the rewrite to prevent further processing of the request. | ||
rewrites.MainRewrite = fmt.Sprintf("%s break", createMainRewriteForFilters(filter.Path, path)) | ||
mainRewrite := createMainRewriteForFilters(filter.Path, pathRule) | ||
if mainRewrite == "" { | ||
// Invalid configuration for the rewrite filter | ||
return nil | ||
} | ||
// For URLRewriteFilter, add "break" to prevent further processing of the request. | ||
rewrites.MainRewrite = fmt.Sprintf("%s break", mainRewrite) | ||
} | ||
|
||
return rewrites | ||
|
@@ -982,14 +1001,18 @@ func createPath(rule dataplane.PathRule) string { | |
switch rule.PathType { | ||
case dataplane.PathTypeExact: | ||
return exactPath(rule.Path) | ||
case dataplane.PathTypePrefix: | ||
return fmt.Sprintf("^~ %s", rule.Path) | ||
case dataplane.PathTypeRegularExpression: | ||
return fmt.Sprintf("~ %s", rule.Path) | ||
default: | ||
return rule.Path | ||
return "" // should never happen because path type is validated earlier | ||
salonichf5 marked this conversation as resolved.
Show resolved
Hide resolved
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. should we panic here like we do for other cases @ciarams87 ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i guess its fine, this is how we have handled it in the past so should be good There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think your first instinct was correct actually - this should be a panic. Now this function silently returns an invalid location path instead of at least returning the original path as a fallback. This is a programmer error (all path types should be handled), not a runtime error from user input (which is validated earlier), so panic() is appropriate and consistent. |
||
} | ||
} | ||
|
||
func createDefaultRootLocation() http.Location { | ||
return http.Location{ | ||
Path: "/", | ||
Path: "= /", | ||
Return: &http.Return{Code: http.StatusNotFound}, | ||
} | ||
} | ||
|