Skip to content

Commit 0a22e1a

Browse files
authored
Add client-body-buffer-size directive to Ingress Annotations & Configmap (#8548)
1 parent 4b17636 commit 0a22e1a

File tree

14 files changed

+595
-10
lines changed

14 files changed

+595
-10
lines changed

internal/configs/annotations.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,14 @@ func parseAnnotations(ingEx *IngressEx, baseCfgParams *ConfigParams, isPlus bool
247247
cfgParams.ClientMaxBodySize = clientMaxBodySize
248248
}
249249

250+
if clientBodyBufferSize, exists := ingEx.Ingress.Annotations["nginx.org/client-body-buffer-size"]; exists {
251+
size, err := ParseSize(clientBodyBufferSize)
252+
if err != nil {
253+
nl.Errorf(l, "Ingress %s/%s: Invalid value nginx.org/client-body-buffer-size: got %q: %v", ingEx.Ingress.GetNamespace(), ingEx.Ingress.GetName(), clientBodyBufferSize, err)
254+
}
255+
cfgParams.ClientBodyBufferSize = size
256+
}
257+
250258
if redirectToHTTPS, exists, err := GetMapKeyAsBool(ingEx.Ingress.Annotations, "nginx.org/redirect-to-https", ingEx.Ingress); exists {
251259
if err != nil {
252260
nl.Error(l, err)

internal/configs/annotations_test.go

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -755,3 +755,175 @@ func TestGetRewriteTargetWithComplexValues(t *testing.T) {
755755
})
756756
}
757757
}
758+
759+
func TestClientBodyBufferSizeAnnotationValid(t *testing.T) {
760+
t.Parallel()
761+
762+
tests := []struct {
763+
name string
764+
clientBodyBufferSize string
765+
expected string
766+
}{
767+
{
768+
name: "valid size with k",
769+
clientBodyBufferSize: "16k",
770+
expected: "16k",
771+
},
772+
{
773+
name: "valid size with M",
774+
clientBodyBufferSize: "4M",
775+
expected: "4M",
776+
},
777+
{
778+
name: "valid size without suffix",
779+
clientBodyBufferSize: "8192",
780+
expected: "8192",
781+
},
782+
{
783+
name: "single digit",
784+
clientBodyBufferSize: "1k",
785+
expected: "1k",
786+
},
787+
{
788+
name: "zero value",
789+
clientBodyBufferSize: "0",
790+
expected: "0",
791+
},
792+
{
793+
name: "large buffer size",
794+
clientBodyBufferSize: "512K",
795+
expected: "512K",
796+
},
797+
{
798+
name: "megabyte buffer size",
799+
clientBodyBufferSize: "64M",
800+
expected: "64M",
801+
},
802+
{
803+
name: "empty annotation",
804+
clientBodyBufferSize: "",
805+
expected: "",
806+
},
807+
{
808+
name: "very large number",
809+
clientBodyBufferSize: "999999999",
810+
expected: "999999999",
811+
},
812+
}
813+
814+
for _, tt := range tests {
815+
t.Run(tt.name, func(t *testing.T) {
816+
t.Parallel()
817+
818+
ingress := &networking.Ingress{
819+
ObjectMeta: metav1.ObjectMeta{
820+
Name: "test-ingress",
821+
Namespace: "default",
822+
Annotations: map[string]string{
823+
"nginx.org/client-body-buffer-size": tt.clientBodyBufferSize,
824+
},
825+
},
826+
}
827+
828+
ingEx := &IngressEx{
829+
Ingress: ingress,
830+
}
831+
832+
baseCfgParams := NewDefaultConfigParams(context.Background(), false)
833+
result := parseAnnotations(ingEx, baseCfgParams, false, false, false, false, false)
834+
835+
if result.ClientBodyBufferSize != tt.expected {
836+
t.Errorf("Test %q: expected ClientBodyBufferSize %q, got %q", tt.name, tt.expected, result.ClientBodyBufferSize)
837+
}
838+
839+
result2 := parseAnnotations(ingEx, baseCfgParams, false, false, false, false, false)
840+
if result2.ClientBodyBufferSize != tt.expected {
841+
t.Errorf("Test %q with other annotations: expected ClientBodyBufferSize %q, got %q", tt.name, tt.expected, result2.ClientBodyBufferSize)
842+
}
843+
})
844+
}
845+
}
846+
847+
func TestClientBodyBufferSizeAnnotationInvalid(t *testing.T) {
848+
t.Parallel()
849+
850+
tests := []struct {
851+
name string
852+
annotations map[string]string
853+
}{
854+
{
855+
name: "annotation name case sensitivity",
856+
annotations: map[string]string{
857+
"nginx.org/Client-Body-Buffer-Size": "16k", // capital letters
858+
},
859+
},
860+
{
861+
name: "invalid time unit h",
862+
annotations: map[string]string{
863+
"nginx.org/client-body-buffer-size": "4h",
864+
},
865+
},
866+
{
867+
name: "invalid random string",
868+
annotations: map[string]string{
869+
"nginx.org/client-body-buffer-size": "3cd2", // wrong format, too many chars
870+
},
871+
},
872+
{
873+
name: "invalid with g suffix",
874+
annotations: map[string]string{
875+
"nginx.org/client-body-buffer-size": "2g",
876+
},
877+
},
878+
879+
{
880+
name: "invalid negative value",
881+
annotations: map[string]string{
882+
"nginx.org/client-body-buffer-size": "-16k",
883+
},
884+
},
885+
{
886+
name: "invalid with text prefix",
887+
annotations: map[string]string{
888+
"nginx.org/client-body-buffer-size": "abc16k",
889+
},
890+
},
891+
{
892+
name: "invalid with special characters",
893+
annotations: map[string]string{
894+
"nginx.org/client-body-buffer-size": "16@k",
895+
},
896+
},
897+
{
898+
name: "invalid with letters",
899+
annotations: map[string]string{
900+
"nginx.org/client-body-buffer-size": "abcdef",
901+
},
902+
},
903+
}
904+
905+
for _, tt := range tests {
906+
t.Run(tt.name, func(t *testing.T) {
907+
t.Parallel()
908+
909+
ingress := &networking.Ingress{
910+
ObjectMeta: metav1.ObjectMeta{
911+
Name: "test-ingress",
912+
Namespace: "default",
913+
Annotations: tt.annotations,
914+
},
915+
}
916+
917+
ingEx := &IngressEx{
918+
Ingress: ingress,
919+
}
920+
921+
baseCfgParams := NewDefaultConfigParams(context.Background(), false)
922+
result := parseAnnotations(ingEx, baseCfgParams, false, false, false, false, false)
923+
924+
if result.ClientBodyBufferSize != "" {
925+
t.Errorf(`Test %q: expected ClientBodyBufferSize %q, got ""`, tt.name, result.ClientBodyBufferSize)
926+
}
927+
})
928+
}
929+
}

internal/configs/config_params.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
type ConfigParams struct {
1313
Context context.Context
1414
ClientMaxBodySize string
15+
ClientBodyBufferSize string
1516
DefaultServerAccessLogOff bool
1617
DefaultServerReturn string
1718
FailTimeout string
@@ -52,6 +53,7 @@ type ConfigParams struct {
5253
MainWorkerProcesses string
5354
MainWorkerRlimitNofile string
5455
MainWorkerShutdownTimeout string
56+
MainClientBodyBufferSize string
5557
MaxConns int
5658
MaxFails int
5759
AppProtectEnable string

internal/configs/configmaps.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,17 @@ func ParseConfigMap(ctx context.Context, cfgm *v1.ConfigMap, nginxPlus bool, has
103103
cfgParams.ClientMaxBodySize = clientMaxBodySize
104104
}
105105

106+
if clientBodyBufferSize, exists := cfgm.Data["client-body-buffer-size"]; exists {
107+
if parsedClientBodyBufferSize, err := ParseSize(clientBodyBufferSize); err != nil {
108+
wrappedError := fmt.Errorf("ConfigMap %s/%s: invalid value for 'client-body-buffer-size': %w", cfgm.GetNamespace(), cfgm.GetName(), err)
109+
nl.Errorf(l, "%s", wrappedError.Error())
110+
eventLog.Event(cfgm, v1.EventTypeWarning, nl.EventReasonInvalidValue, wrappedError.Error())
111+
configOk = false
112+
} else {
113+
cfgParams.MainClientBodyBufferSize = parsedClientBodyBufferSize
114+
}
115+
}
116+
106117
if serverNamesHashBucketSize, exists := cfgm.Data["server-names-hash-bucket-size"]; exists {
107118
cfgParams.MainServerNamesHashBucketSize = serverNamesHashBucketSize
108119
}
@@ -1146,6 +1157,7 @@ func GenerateNginxMainConfig(staticCfgParams *StaticConfigParams, config *Config
11461157
ServerNamesHashMaxSize: config.MainServerNamesHashMaxSize,
11471158
MapHashBucketSize: config.MainMapHashBucketSize,
11481159
MapHashMaxSize: config.MainMapHashMaxSize,
1160+
ClientBodyBufferSize: config.MainClientBodyBufferSize,
11491161
ServerTokens: config.ServerTokens,
11501162
SSLCiphers: config.MainServerSSLCiphers,
11511163
SSLDHParam: config.MainServerSSLDHParam,

0 commit comments

Comments
 (0)