Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 45 additions & 22 deletions internal/controller/nginx/config/servers.go
Original file line number Diff line number Diff line change
Expand Up @@ -414,7 +414,7 @@ func initializeExternalLocations(
}
if !exactPathExists {
externalLocExact := http.Location{
Path: exactPath(externalLocPath),
Path: exactPath(rule.Path),
Type: locType,
}
extLocations = append(extLocations, externalLocExact)
Expand Down Expand Up @@ -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
Expand All @@ -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)
}
Expand All @@ -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)
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)
}

Expand All @@ -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
Expand All @@ -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)
}

Expand All @@ -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
}
Expand All @@ -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
Expand Down Expand Up @@ -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
panic(fmt.Errorf("unknown path type %q for path %q", rule.PathType, rule.Path))
}
}

func createDefaultRootLocation() http.Location {
return http.Location{
Path: "/",
Path: "= /",
Return: &http.Return{Code: http.StatusNotFound},
}
}
Expand Down
Loading
Loading