diff --git a/internal/configs/version2/http.go b/internal/configs/version2/http.go index 007f45ee32..682c2fcf68 100644 --- a/internal/configs/version2/http.go +++ b/internal/configs/version2/http.go @@ -337,8 +337,9 @@ type Distribution struct { // InternalRedirectLocation defines a location for internally redirecting requests to named locations. type InternalRedirectLocation struct { - Path string - Destination string + Path string + Destination string + ClientMaxBodySize string } // Map defines a map. diff --git a/internal/configs/version2/nginx-plus.virtualserver.tmpl b/internal/configs/version2/nginx-plus.virtualserver.tmpl index 8ec53a528e..2e2311a6ec 100644 --- a/internal/configs/version2/nginx-plus.virtualserver.tmpl +++ b/internal/configs/version2/nginx-plus.virtualserver.tmpl @@ -399,6 +399,9 @@ server { {{- range $l := $s.InternalRedirectLocations }} location {{ $l.Path }} { + {{- if $l.ClientMaxBodySize }} + client_max_body_size {{ $l.ClientMaxBodySize }}; + {{- end }} rewrite ^ {{ $l.Destination }} last; } {{- end }} diff --git a/internal/configs/version2/nginx.virtualserver.tmpl b/internal/configs/version2/nginx.virtualserver.tmpl index 13432de9d0..713aedb946 100644 --- a/internal/configs/version2/nginx.virtualserver.tmpl +++ b/internal/configs/version2/nginx.virtualserver.tmpl @@ -211,6 +211,9 @@ server { {{- range $l := $s.InternalRedirectLocations }} location {{ $l.Path }} { + {{- if $l.ClientMaxBodySize }} + client_max_body_size {{ $l.ClientMaxBodySize }}; + {{- end }} rewrite ^ {{ $l.Destination }} last; } {{- end }} diff --git a/internal/configs/virtualserver.go b/internal/configs/virtualserver.go index 94f63ed5f4..3e4ee18133 100644 --- a/internal/configs/virtualserver.go +++ b/internal/configs/virtualserver.go @@ -3067,10 +3067,21 @@ func generateMatchesConfig(route conf_v1.Route, upstreamNamer *upstreamNamer, cr } } + // Find any locations with a clientMaxBodySize defined to populate the parent rewrite/redirect location + // See issue #7332 for why this needs to exist on the InternalRedirectLocation struct + var clientMaxBodySize string + for _, l := range locations { + if l.ClientMaxBodySize != "" { + clientMaxBodySize = l.ClientMaxBodySize + break + } + } + // Generate an InternalRedirectLocation to the location defined by the main map variable irl := version2.InternalRedirectLocation{ - Path: route.Path, - Destination: variable, + Path: route.Path, + Destination: variable, + ClientMaxBodySize: clientMaxBodySize, } return routingCfg{ diff --git a/internal/configs/virtualserver_test.go b/internal/configs/virtualserver_test.go index efd59ac345..553f655448 100644 --- a/internal/configs/virtualserver_test.go +++ b/internal/configs/virtualserver_test.go @@ -1181,6 +1181,77 @@ func vsEx() VirtualServerEx { } } +// TestUpstreamClientMaxBodySizeInInternalRedirect validates that clientMaxBodySize from upstream is present in the InternalRedirectLocation after config generation. +func TestUpstreamClientMaxBodySizeInInternalRedirect(t *testing.T) { + t.Parallel() + + vse := VirtualServerEx{ + VirtualServer: &conf_v1.VirtualServer{ + ObjectMeta: meta_v1.ObjectMeta{ + Name: "cafe", + Namespace: "default", + }, + Spec: conf_v1.VirtualServerSpec{ + Host: "cafe.example.com", + Upstreams: []conf_v1.Upstream{ + { + Name: "tea", + Service: "tea-svc", + Port: 80, + ClientMaxBodySize: "7m", + }, + }, + Routes: []conf_v1.Route{ + { + Path: "/tea", + Matches: []conf_v1.Match{ + { + Conditions: []conf_v1.Condition{ + { + Variable: "$request_method", + Value: "POST", + }, + }, + Action: &conf_v1.Action{ + Proxy: &conf_v1.ActionProxy{ + Upstream: "tea", + }, + }, + }, + }, + Action: &conf_v1.Action{ + Return: &conf_v1.ActionReturn{ + Code: 200, + Body: "Hello from cafe", + }, + }, + }, + }, + }, + }, + } + + vsc := newVirtualServerConfigurator(&baseCfgParams, true, false, &StaticConfigParams{TLSPassthrough: true}, false, &fakeBV) + vsConfig, warnings := vsc.GenerateVirtualServerConfig(&vse, nil, nil) + if len(warnings) > 0 { + t.Fatalf("unexpected warnings: %v", warnings) + } + + // Check InternalRedirectLocations for /tea and validate ClientMaxBodySize + foundIR := false + for _, ir := range vsConfig.Server.InternalRedirectLocations { + if ir.Path == "/tea" { + foundIR = true + if ir.ClientMaxBodySize != "7m" { + t.Errorf("expected InternalRedirectLocation.ClientMaxBodySize to be '7m', got '%s'", ir.ClientMaxBodySize) + } + } + } + if !foundIR { + t.Fatalf("InternalRedirectLocation for /tea not found in generated config") + } +} + func TestGenerateVirtualServerConfigWithBackupForNGINXPlus(t *testing.T) { t.Parallel()