@@ -47,6 +47,34 @@ func TestQueryMatcher_Match(t *testing.T) {
4747 url : "/path" ,
4848 want : false ,
4949 },
50+ {
51+ name : "match second value of multi-value" ,
52+ key : "foo" ,
53+ value : "b" ,
54+ url : "/path?foo=a&foo=b" ,
55+ want : true ,
56+ },
57+ {
58+ name : "no match across multi-value" ,
59+ key : "foo" ,
60+ value : "c" ,
61+ url : "/path?foo=a&foo=b" ,
62+ want : false ,
63+ },
64+ {
65+ name : "no match empty value with missing key" ,
66+ key : "foo" ,
67+ value : "" ,
68+ url : "/path" ,
69+ want : false ,
70+ },
71+ {
72+ name : "match empty value with present empty value" ,
73+ key : "foo" ,
74+ value : "" ,
75+ url : "/path?foo=" ,
76+ want : true ,
77+ },
5078 }
5179
5280 for _ , tc := range cases {
@@ -129,6 +157,27 @@ func TestQueryRegexpMatcher_Match(t *testing.T) {
129157 url : "/path?other=123" ,
130158 want : false ,
131159 },
160+ {
161+ name : "match second value of multi-value" ,
162+ key : "id" ,
163+ pattern : `^\d+$` ,
164+ url : "/path?id=abc&id=123" ,
165+ want : true ,
166+ },
167+ {
168+ name : "no match across multi-value" ,
169+ key : "id" ,
170+ pattern : `^\d+$` ,
171+ url : "/path?id=abc&id=def" ,
172+ want : false ,
173+ },
174+ {
175+ name : "no match permissive regex with missing key" ,
176+ key : "id" ,
177+ pattern : `^.*$` ,
178+ url : "/path" ,
179+ want : false ,
180+ },
132181 }
133182
134183 for _ , tc := range cases {
@@ -187,28 +236,28 @@ func TestHeaderMatcher_Match(t *testing.T) {
187236 name string
188237 headerKey string
189238 value string
190- headers map [string ]string
239+ headers map [string ][] string
191240 want bool
192241 }{
193242 {
194243 name : "match header" ,
195244 headerKey : "Content-Type" ,
196245 value : "application/json" ,
197- headers : map [string ]string {"Content-Type" : "application/json" },
246+ headers : map [string ][] string {"Content-Type" : { "application/json" } },
198247 want : true ,
199248 },
200249 {
201250 name : "no match different value" ,
202251 headerKey : "Content-Type" ,
203252 value : "application/json" ,
204- headers : map [string ]string {"Content-Type" : "text/plain" },
253+ headers : map [string ][] string {"Content-Type" : { "text/plain" } },
205254 want : false ,
206255 },
207256 {
208257 name : "no match missing header" ,
209258 headerKey : "Content-Type" ,
210259 value : "application/json" ,
211- headers : map [string ]string {"Accept" : "application/json" },
260+ headers : map [string ][] string {"Accept" : { "application/json" } },
212261 want : false ,
213262 },
214263 {
@@ -218,14 +267,30 @@ func TestHeaderMatcher_Match(t *testing.T) {
218267 headers : nil ,
219268 want : false ,
220269 },
270+ {
271+ name : "match second value of multi-value" ,
272+ headerKey : "Content-Type" ,
273+ value : "application/json" ,
274+ headers : map [string ][]string {"Content-Type" : {"text/plain" , "application/json" }},
275+ want : true ,
276+ },
277+ {
278+ name : "no match across multi-value" ,
279+ headerKey : "Content-Type" ,
280+ value : "application/json" ,
281+ headers : map [string ][]string {"Content-Type" : {"text/plain" , "text/html" }},
282+ want : false ,
283+ },
221284 }
222285
223286 for _ , tc := range cases {
224287 t .Run (tc .name , func (t * testing.T ) {
225288 m := HeaderMatcher {canonicalKey : http .CanonicalHeaderKey (tc .headerKey ), value : tc .value }
226289 req := httptest .NewRequest (http .MethodGet , "/path" , nil )
227- for k , v := range tc .headers {
228- req .Header .Set (k , v )
290+ for k , vs := range tc .headers {
291+ for _ , v := range vs {
292+ req .Header .Add (k , v )
293+ }
229294 }
230295 w := httptest .NewRecorder ()
231296 c := NewTestContextOnly (w , req )
@@ -279,28 +344,42 @@ func TestHeaderRegexpMatcher_Match(t *testing.T) {
279344 name string
280345 headerKey string
281346 pattern string
282- headers map [string ]string
347+ headers map [string ][] string
283348 want bool
284349 }{
285350 {
286351 name : "match regex" ,
287352 headerKey : "Content-Type" ,
288353 pattern : `^application/.*` ,
289- headers : map [string ]string {"Content-Type" : "application/json" },
354+ headers : map [string ][] string {"Content-Type" : { "application/json" } },
290355 want : true ,
291356 },
292357 {
293358 name : "no match regex" ,
294359 headerKey : "Content-Type" ,
295360 pattern : `^application/.*` ,
296- headers : map [string ]string {"Content-Type" : "text/plain" },
361+ headers : map [string ][] string {"Content-Type" : { "text/plain" } },
297362 want : false ,
298363 },
299364 {
300365 name : "missing header" ,
301366 headerKey : "Content-Type" ,
302367 pattern : `^application/.*` ,
303- headers : map [string ]string {"Accept" : "application/json" },
368+ headers : map [string ][]string {"Accept" : {"application/json" }},
369+ want : false ,
370+ },
371+ {
372+ name : "match second value of multi-value" ,
373+ headerKey : "Content-Type" ,
374+ pattern : `^application/.*` ,
375+ headers : map [string ][]string {"Content-Type" : {"text/plain" , "application/json" }},
376+ want : true ,
377+ },
378+ {
379+ name : "no match across multi-value" ,
380+ headerKey : "Content-Type" ,
381+ pattern : `^application/.*` ,
382+ headers : map [string ][]string {"Content-Type" : {"text/plain" , "text/html" }},
304383 want : false ,
305384 },
306385 }
@@ -309,8 +388,10 @@ func TestHeaderRegexpMatcher_Match(t *testing.T) {
309388 t .Run (tc .name , func (t * testing.T ) {
310389 m := HeaderRegexpMatcher {canonicalKey : http .CanonicalHeaderKey (tc .headerKey ), regex : regexp .MustCompile (tc .pattern )}
311390 req := httptest .NewRequest (http .MethodGet , "/path" , nil )
312- for k , v := range tc .headers {
313- req .Header .Set (k , v )
391+ for k , vs := range tc .headers {
392+ for _ , v := range vs {
393+ req .Header .Add (k , v )
394+ }
314395 }
315396 w := httptest .NewRecorder ()
316397 c := NewTestContextOnly (w , req )
0 commit comments