diff --git a/config/crd/bases/k8s.nginx.org_virtualserverroutes.yaml b/config/crd/bases/k8s.nginx.org_virtualserverroutes.yaml index 544718e877..f8105b7dcd 100644 --- a/config/crd/bases/k8s.nginx.org_virtualserverroutes.yaml +++ b/config/crd/bases/k8s.nginx.org_virtualserverroutes.yaml @@ -878,6 +878,13 @@ spec: is enabled. The default is set in the proxy-busy-buffers-size ConfigMap key.' type: string + client-body-buffer-size: + description: |- + ClientBodyBufferSize sets the size of the buffer used for reading the client request body. Must be specified as a number followed by: + 'k' for kilobytes or 'm' for megabytes. + Examples: "10m" or "512k". + pattern: ^\d+[kKmM]?$ + type: string client-max-body-size: description: Sets the maximum allowed size of the client request body. The default is set in the client-max-body-size ConfigMap diff --git a/config/crd/bases/k8s.nginx.org_virtualservers.yaml b/config/crd/bases/k8s.nginx.org_virtualservers.yaml index ac5bdd456a..677beb84aa 100644 --- a/config/crd/bases/k8s.nginx.org_virtualservers.yaml +++ b/config/crd/bases/k8s.nginx.org_virtualservers.yaml @@ -1067,6 +1067,13 @@ spec: is enabled. The default is set in the proxy-busy-buffers-size ConfigMap key.' type: string + client-body-buffer-size: + description: |- + ClientBodyBufferSize sets the size of the buffer used for reading the client request body. Must be specified as a number followed by: + 'k' for kilobytes or 'm' for megabytes. + Examples: "10m" or "512k". + pattern: ^\d+[kKmM]?$ + type: string client-max-body-size: description: Sets the maximum allowed size of the client request body. The default is set in the client-max-body-size ConfigMap diff --git a/deploy/crds.yaml b/deploy/crds.yaml index fd080f2d59..3b47784561 100644 --- a/deploy/crds.yaml +++ b/deploy/crds.yaml @@ -1916,6 +1916,13 @@ spec: is enabled. The default is set in the proxy-busy-buffers-size ConfigMap key.' type: string + client-body-buffer-size: + description: |- + ClientBodyBufferSize sets the size of the buffer used for reading the client request body. Must be specified as a number followed by: + 'k' for kilobytes or 'm' for megabytes. + Examples: "10m" or "512k". + pattern: ^\d+[kKmM]?$ + type: string client-max-body-size: description: Sets the maximum allowed size of the client request body. The default is set in the client-max-body-size ConfigMap @@ -3335,6 +3342,13 @@ spec: is enabled. The default is set in the proxy-busy-buffers-size ConfigMap key.' type: string + client-body-buffer-size: + description: |- + ClientBodyBufferSize sets the size of the buffer used for reading the client request body. Must be specified as a number followed by: + 'k' for kilobytes or 'm' for megabytes. + Examples: "10m" or "512k". + pattern: ^\d+[kKmM]?$ + type: string client-max-body-size: description: Sets the maximum allowed size of the client request body. The default is set in the client-max-body-size ConfigMap diff --git a/docs/crd/k8s.nginx.org_virtualserverroutes.md b/docs/crd/k8s.nginx.org_virtualserverroutes.md index 52426dacee..3874555213 100644 --- a/docs/crd/k8s.nginx.org_virtualserverroutes.md +++ b/docs/crd/k8s.nginx.org_virtualserverroutes.md @@ -169,6 +169,7 @@ The `.spec` object supports the following fields: | `upstreams[].buffers.number` | `integer` | Configures the number of buffers. The default is set in the proxy-buffers ConfigMap key. | | `upstreams[].buffers.size` | `string` | Configures the size of a buffer. The default is set in the proxy-buffers ConfigMap key. | | `upstreams[].busy-buffers-size` | `string` | Sets the size of the buffers used for reading a response from the upstream server when the proxy_buffering is enabled. The default is set in the proxy-busy-buffers-size ConfigMap key.' | +| `upstreams[].client-body-buffer-size` | `string` | ClientBodyBufferSize sets the size of the buffer used for reading the client request body. Must be specified as a number followed by: 'k' for kilobytes or 'm' for megabytes. Examples: "10m" or "512k". | | `upstreams[].client-max-body-size` | `string` | Sets the maximum allowed size of the client request body. The default is set in the client-max-body-size ConfigMap key. | | `upstreams[].connect-timeout` | `string` | The timeout for establishing a connection with an upstream server. The default is specified in the proxy-connect-timeout ConfigMap key. | | `upstreams[].fail-timeout` | `string` | The time during which the specified number of unsuccessful attempts to communicate with an upstream server should happen to consider the server unavailable. The default is set in the fail-timeout ConfigMap key. | diff --git a/docs/crd/k8s.nginx.org_virtualservers.md b/docs/crd/k8s.nginx.org_virtualservers.md index 280e1bb8b2..cffd599ffd 100644 --- a/docs/crd/k8s.nginx.org_virtualservers.md +++ b/docs/crd/k8s.nginx.org_virtualservers.md @@ -204,6 +204,7 @@ The `.spec` object supports the following fields: | `upstreams[].buffers.number` | `integer` | Configures the number of buffers. The default is set in the proxy-buffers ConfigMap key. | | `upstreams[].buffers.size` | `string` | Configures the size of a buffer. The default is set in the proxy-buffers ConfigMap key. | | `upstreams[].busy-buffers-size` | `string` | Sets the size of the buffers used for reading a response from the upstream server when the proxy_buffering is enabled. The default is set in the proxy-busy-buffers-size ConfigMap key.' | +| `upstreams[].client-body-buffer-size` | `string` | ClientBodyBufferSize sets the size of the buffer used for reading the client request body. Must be specified as a number followed by: 'k' for kilobytes or 'm' for megabytes. Examples: "10m" or "512k". | | `upstreams[].client-max-body-size` | `string` | Sets the maximum allowed size of the client request body. The default is set in the client-max-body-size ConfigMap key. | | `upstreams[].connect-timeout` | `string` | The timeout for establishing a connection with an upstream server. The default is specified in the proxy-connect-timeout ConfigMap key. | | `upstreams[].fail-timeout` | `string` | The time during which the specified number of unsuccessful attempts to communicate with an upstream server should happen to consider the server unavailable. The default is set in the fail-timeout ConfigMap key. | diff --git a/internal/configs/version2/__snapshots__/templates_test.snap b/internal/configs/version2/__snapshots__/templates_test.snap index 50f2fe69b4..706165c222 100644 --- a/internal/configs/version2/__snapshots__/templates_test.snap +++ b/internal/configs/version2/__snapshots__/templates_test.snap @@ -1876,6 +1876,56 @@ server { --- +[TestExecuteVirtualServerTemplate_RendersTemplateWithClientBodyBufferSize - 1] + + +server { + listen 80; + listen [::]:80; + + + server_name example.com; + status_zone example.com; + set $resource_type "virtualserver"; + set $resource_name ""; + set $resource_namespace ""; + + server_tokens ""; + + + + + location / { + set $service ""; + status_zone ""; + + + set $default_connection_header close; + proxy_connect_timeout ; + proxy_read_timeout ; + proxy_send_timeout ; + client_max_body_size ; + client_body_buffer_size 16k; + + proxy_buffering off; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $vs_connection_header; + proxy_pass_request_headers off; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Host $host; + proxy_set_header X-Forwarded-Port $server_port; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_pass http://test-upstream; + proxy_next_upstream ; + proxy_next_upstream_timeout ; + proxy_next_upstream_tries 0; + } +} + +--- + [TestExecuteVirtualServerTemplate_RendersTemplateWithCustomListener - 1] diff --git a/internal/configs/version2/http.go b/internal/configs/version2/http.go index ea806bd563..da730fcf95 100644 --- a/internal/configs/version2/http.go +++ b/internal/configs/version2/http.go @@ -198,6 +198,7 @@ type Location struct { ProxyReadTimeout string ProxySendTimeout string ClientMaxBodySize string + ClientBodyBufferSize string ProxyMaxTempFileSize string ProxyBuffering bool ProxyBuffers string diff --git a/internal/configs/version2/nginx-plus.virtualserver.tmpl b/internal/configs/version2/nginx-plus.virtualserver.tmpl index 4886cc2463..9133427225 100644 --- a/internal/configs/version2/nginx-plus.virtualserver.tmpl +++ b/internal/configs/version2/nginx-plus.virtualserver.tmpl @@ -674,6 +674,9 @@ server { {{ $proxyOrGRPC }}_read_timeout {{ $l.ProxyReadTimeout }}; {{ $proxyOrGRPC }}_send_timeout {{ $l.ProxySendTimeout }}; client_max_body_size {{ $l.ClientMaxBodySize }}; + {{- if $l.ClientBodyBufferSize }} + client_body_buffer_size {{ $l.ClientBodyBufferSize }}; + {{- end }} {{- if $l.ProxyMaxTempFileSize }} proxy_max_temp_file_size {{ $l.ProxyMaxTempFileSize }}; diff --git a/internal/configs/version2/nginx.virtualserver.tmpl b/internal/configs/version2/nginx.virtualserver.tmpl index 13432de9d0..f4468e9464 100644 --- a/internal/configs/version2/nginx.virtualserver.tmpl +++ b/internal/configs/version2/nginx.virtualserver.tmpl @@ -368,6 +368,9 @@ server { {{ $proxyOrGRPC }}_read_timeout {{ $l.ProxyReadTimeout }}; {{ $proxyOrGRPC }}_send_timeout {{ $l.ProxySendTimeout }}; client_max_body_size {{ $l.ClientMaxBodySize }}; + {{- if $l.ClientBodyBufferSize }} + client_body_buffer_size {{ $l.ClientBodyBufferSize }}; + {{- end }} {{- if $l.ProxyMaxTempFileSize }} proxy_max_temp_file_size {{ $l.ProxyMaxTempFileSize }}; diff --git a/internal/configs/version2/templates_test.go b/internal/configs/version2/templates_test.go index 7b5253f92a..79943d57c7 100644 --- a/internal/configs/version2/templates_test.go +++ b/internal/configs/version2/templates_test.go @@ -440,6 +440,21 @@ func TestExecuteVirtualServerTemplate_RendersPlusTemplateWithHTTP2Off(t *testing t.Log(string(got)) } +func TestExecuteVirtualServerTemplate_RendersTemplateWithClientBodyBufferSize(t *testing.T) { + t.Parallel() + executor := newTmplExecutorNGINXPlus(t) + + got, err := executor.ExecuteVirtualServerTemplate(&virtualServerCfgWithClientBodyBufferSize) + if err != nil { + t.Error(err) + } + if !bytes.Contains(got, []byte("client_body_buffer_size 16k;")) { + t.Error("want `client_body_buffer_size 16k;` directive in generated template") + } + snaps.MatchSnapshot(t, string(got)) + t.Log(string(got)) +} + func TestExecuteVirtualServerTemplate_RendersOSSTemplateWithHTTP2On(t *testing.T) { t.Parallel() executor := newTmplExecutorNGINX(t) @@ -2171,6 +2186,20 @@ var ( }, } + virtualServerCfgWithClientBodyBufferSize = VirtualServerConfig{ + Server: Server{ + ServerName: "example.com", + StatusZone: "example.com", + Locations: []Location{ + { + Path: "/", + ProxyPass: "http://test-upstream", + ClientBodyBufferSize: "16k", + }, + }, + }, + } + virtualServerCfgWithRateLimitJWTClaim = VirtualServerConfig{ LimitReqZones: []LimitReqZone{ { diff --git a/internal/configs/virtualserver.go b/internal/configs/virtualserver.go index 8dc42d007a..9696afb174 100644 --- a/internal/configs/virtualserver.go +++ b/internal/configs/virtualserver.go @@ -2647,6 +2647,7 @@ func generateLocationForProxying(path string, upstreamName string, upstream conf ProxyReadTimeout: generateTimeWithDefault(upstream.ProxyReadTimeout, cfgParams.ProxyReadTimeout), ProxySendTimeout: generateTimeWithDefault(upstream.ProxySendTimeout, cfgParams.ProxySendTimeout), ClientMaxBodySize: generateString(upstream.ClientMaxBodySize, cfgParams.ClientMaxBodySize), + ClientBodyBufferSize: generateString(upstream.ClientBodyBufferSize, cfgParams.ClientBodyBufferSize), ProxyMaxTempFileSize: cfgParams.ProxyMaxTempFileSize, ProxyBuffering: generateBool(upstream.ProxyBuffering, cfgParams.ProxyBuffering), ProxyBuffers: generateBuffers(upstream.ProxyBuffers, cfgParams.ProxyBuffers), diff --git a/internal/configs/virtualserver_test.go b/internal/configs/virtualserver_test.go index bf5f8d78d1..d9dd0cf516 100644 --- a/internal/configs/virtualserver_test.go +++ b/internal/configs/virtualserver_test.go @@ -16221,6 +16221,7 @@ func TestGenerateLocationForProxying(t *testing.T) { ProxyReadTimeout: "31s", ProxySendTimeout: "32s", ClientMaxBodySize: "1m", + ClientBodyBufferSize: "16k", ProxyMaxTempFileSize: "1024m", ProxyBuffering: true, ProxyBuffers: "8 4k", @@ -16238,6 +16239,7 @@ func TestGenerateLocationForProxying(t *testing.T) { ProxyReadTimeout: "31s", ProxySendTimeout: "32s", ClientMaxBodySize: "1m", + ClientBodyBufferSize: "16k", ProxyMaxTempFileSize: "1024m", ProxyBuffering: true, ProxyBuffers: "8 4k", @@ -16269,6 +16271,7 @@ func TestGenerateLocationForGrpcProxying(t *testing.T) { ProxyReadTimeout: "31s", ProxySendTimeout: "32s", ClientMaxBodySize: "1m", + ClientBodyBufferSize: "16k", ProxyMaxTempFileSize: "1024m", ProxyBuffering: true, ProxyBuffers: "8 4k", @@ -16288,6 +16291,7 @@ func TestGenerateLocationForGrpcProxying(t *testing.T) { ProxyReadTimeout: "31s", ProxySendTimeout: "32s", ClientMaxBodySize: "1m", + ClientBodyBufferSize: "16k", ProxyMaxTempFileSize: "1024m", ProxyBuffering: true, ProxyBuffers: "8 4k", diff --git a/pkg/apis/configuration/v1/types.go b/pkg/apis/configuration/v1/types.go index 1f3dd4a6b7..12be8b7213 100644 --- a/pkg/apis/configuration/v1/types.go +++ b/pkg/apis/configuration/v1/types.go @@ -157,6 +157,12 @@ type Upstream struct { ProxyBusyBuffersSize string `json:"busy-buffers-size"` // Sets the maximum allowed size of the client request body. The default is set in the client-max-body-size ConfigMap key. ClientMaxBodySize string `json:"client-max-body-size"` + // +kubebuilder:validation:Optional + // +kubebuilder:validation:Pattern=`^\d+[kKmM]?$` + // ClientBodyBufferSize sets the size of the buffer used for reading the client request body. Must be specified as a number followed by: + // 'k' for kilobytes or 'm' for megabytes. + // Examples: "10m" or "512k". + ClientBodyBufferSize string `json:"client-body-buffer-size"` // The TLS configuration for the Upstream. TLS UpstreamTLS `json:"tls"` // The health check configuration for the Upstream. Note: this feature is supported only in NGINX Plus.