-
Notifications
You must be signed in to change notification settings - Fork 6
Expand file tree
/
Copy pathmiddleware_internal_test.go
More file actions
255 lines (243 loc) · 7.86 KB
/
middleware_internal_test.go
File metadata and controls
255 lines (243 loc) · 7.86 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
package raiden
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestIsValidHeaders(t *testing.T) {
tests := []struct {
name string
requestHeaders string
allowedHeaders []string
expected bool
description string
}{
{
name: "Empty allowed headers list - should allow any headers",
requestHeaders: "content-type, authorization",
allowedHeaders: []string{},
expected: true,
description: "When no headers are restricted, all requests should pass",
},
{
name: "Empty request headers - should allow",
requestHeaders: "",
allowedHeaders: []string{"content-type", "authorization"},
expected: true,
description: "Requests with no custom headers should be allowed",
},
{
name: "Whitespace only request headers - should allow",
requestHeaders: " ",
allowedHeaders: []string{"content-type", "authorization"},
expected: true,
description: "Requests with only whitespace headers should be allowed",
},
{
name: "Headers without spaces after comma",
requestHeaders: "content-type,authorization",
allowedHeaders: []string{"content-type", "authorization"},
expected: true,
description: "Should support comma-only separated headers (no spaces)",
},
{
name: "Headers with spaces after comma",
requestHeaders: "content-type, authorization",
allowedHeaders: []string{"content-type", "authorization"},
expected: true,
description: "Should support traditional comma-space separated headers",
},
{
name: "Mixed case headers - should normalize to lowercase",
requestHeaders: "Content-Type,Authorization",
allowedHeaders: []string{"content-type", "authorization"},
expected: true,
description: "Header names should be case-insensitive",
},
{
name: "Headers with extra whitespace",
requestHeaders: " content-type , authorization ",
allowedHeaders: []string{"content-type", "authorization"},
expected: true,
description: "Should trim whitespace from header names",
},
{
name: "Headers with empty entries (trailing comma)",
requestHeaders: "content-type,authorization,",
allowedHeaders: []string{"content-type", "authorization"},
expected: true,
description: "Should skip empty entries from trailing commas",
},
{
name: "Headers with empty entries (multiple commas)",
requestHeaders: "content-type,,authorization",
allowedHeaders: []string{"content-type", "authorization"},
expected: true,
description: "Should skip empty entries from consecutive commas",
},
{
name: "Single valid header",
requestHeaders: "content-type",
allowedHeaders: []string{"content-type", "authorization"},
expected: true,
description: "Single header should be validated correctly",
},
{
name: "Invalid header - not in allowed list",
requestHeaders: "x-custom-header",
allowedHeaders: []string{"content-type", "authorization"},
expected: false,
description: "Headers not in allowed list should be rejected",
},
{
name: "Mixed valid and invalid headers",
requestHeaders: "content-type,x-custom-header",
allowedHeaders: []string{"content-type", "authorization"},
expected: false,
description: "Should reject if any header is not allowed",
},
{
name: "Case mismatch with mixed separators",
requestHeaders: "Content-Type,Authorization, X-Requested-With",
allowedHeaders: []string{"content-type", "authorization", "x-requested-with"},
expected: true,
description: "Should handle mixed case with both separator styles",
},
{
name: "Complex realistic scenario",
requestHeaders: "content-type, authorization,x-requested-with",
allowedHeaders: []string{"content-type", "authorization", "x-requested-with"},
expected: true,
description: "Should handle real-world mixed formatting",
},
{
name: "All empty entries",
requestHeaders: ",,,",
allowedHeaders: []string{"content-type"},
expected: true,
description: "Should handle all empty entries gracefully",
},
{
name: "Duplicate headers - same header repeated",
requestHeaders: "content-type,content-type",
allowedHeaders: []string{"content-type", "authorization"},
expected: true,
description: "Should allow duplicate headers if all are in allowed list",
},
{
name: "Duplicate headers with mixed case",
requestHeaders: "content-type,Content-Type,CONTENT-TYPE",
allowedHeaders: []string{"content-type", "authorization"},
expected: true,
description: "Should handle duplicate headers with case variations",
},
{
name: "Duplicate headers with one invalid",
requestHeaders: "content-type,content-type,x-custom-header",
allowedHeaders: []string{"content-type", "authorization"},
expected: false,
description: "Should reject if any header (even among duplicates) is not allowed",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := isValidHeaders(tt.requestHeaders, tt.allowedHeaders)
assert.Equal(t, tt.expected, result, tt.description)
})
}
}
func TestIsValidHeadersEdgeCases(t *testing.T) {
t.Run("Nil allowed headers slice", func(t *testing.T) {
result := isValidHeaders("content-type", nil)
assert.True(t, result, "Nil allowed headers should allow all requests")
})
t.Run("Very long header list", func(t *testing.T) {
longHeaders := "header1,header2,header3,header4,header5,header6,header7,header8,header9,header10"
allowedHeaders := []string{
"header1", "header2", "header3", "header4", "header5",
"header6", "header7", "header8", "header9", "header10",
}
result := isValidHeaders(longHeaders, allowedHeaders)
assert.True(t, result, "Should handle long header lists")
})
t.Run("Headers with tabs and special whitespace", func(t *testing.T) {
result := isValidHeaders("content-type\t,\tauthorization", []string{"content-type", "authorization"})
assert.True(t, result, "Should handle tab characters")
})
t.Run("Single comma only", func(t *testing.T) {
result := isValidHeaders(",", []string{"content-type"})
assert.True(t, result, "Single comma should be treated as empty")
})
}
func TestContains(t *testing.T) {
tests := []struct {
name string
arr []string
str string
expected bool
}{
{
name: "String exists in array",
arr: []string{"content-type", "authorization"},
str: "content-type",
expected: true,
},
{
name: "String does not exist in array",
arr: []string{"content-type", "authorization"},
str: "x-custom-header",
expected: false,
},
{
name: "Empty array",
arr: []string{},
str: "content-type",
expected: false,
},
{
name: "Empty string search",
arr: []string{"content-type", "authorization"},
str: "",
expected: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := contains(tt.arr, tt.str)
assert.Equal(t, tt.expected, result)
})
}
}
func TestGetCanonicalHeaderKey(t *testing.T) {
tests := []struct {
name string
input string
expected string
}{
{
name: "Lowercase with no spaces",
input: "content-type",
expected: "content-type",
},
{
name: "Mixed case with spaces",
input: "Content Type",
expected: "content_type",
},
{
name: "Uppercase with spaces",
input: "CONTENT TYPE",
expected: "content_type",
},
{
name: "Multiple spaces",
input: "X Custom Header",
expected: "x__custom__header",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := getCanonicalHeaderKey(tt.input)
assert.Equal(t, tt.expected, result)
})
}
}