Skip to content

Commit bda13ef

Browse files
committed
Update handling of query params in njs
Updating NGINX to 1.23.1 image brought changes with njs-0.7.6, which now supports examining all values of a query param. The commit updates njs code for matching query params so that in the case of multiple values of a query param, the first value is used. This is consistent with the previous behavior and the Gateway API spec. Additionally, the unit tests for 'paramsMatch' were fixed and updated to cover multiple param values and different case of a param name.
1 parent 4b37d80 commit bda13ef

File tree

2 files changed

+73
-6
lines changed

2 files changed

+73
-6
lines changed

internal/nginx/modules/src/httpmatches.js

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -175,9 +175,20 @@ function paramsMatch(requestParams, params) {
175175
// Divide string into key value using the index.
176176
let kv = [p.slice(0, idx), p.slice(idx + 1)];
177177

178-
const val = requestParams[kv[0]];
178+
// val can either be a string or an array of strings.
179+
// Also, the NGINX request's args object lookup is case-sensitive.
180+
// For example, 'a=1&b=2&A=3&b=4' will be parsed into {a: "1", b: ["2", "4"], A: "3"}
181+
let val = requestParams[kv[0]];
182+
if (!val) {
183+
return false;
184+
}
185+
186+
// If val is an array, we will match against the first element in the array according to the Gateway API spec.
187+
if (Array.isArray(val)) {
188+
val = val[0];
189+
}
179190

180-
if (!val || val !== kv[1]) {
191+
if (val !== kv[1]) {
181192
return false;
182193
}
183194
}

internal/nginx/modules/test/httpmatches.test.js

Lines changed: 60 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -297,25 +297,81 @@ describe('paramsMatch', () => {
297297
{
298298
name: 'returns false if one of the params is missing from request',
299299
params: params,
300-
requestParams: ['arg2=value2=SOME=other=value', 'arg3===value3&*1(*+'],
300+
requestParams: {
301+
// Arg1 is missing,
302+
arg2: 'value2=SOME=other=value',
303+
arg3: '==value3&*1(*+',
304+
},
305+
expected: false,
306+
},
307+
{
308+
name: 'returns false if one of the params has an empty value',
309+
params: params,
310+
requestParams: {
311+
Arg1: 'value1',
312+
arg2: 'value2=SOME=other=value',
313+
arg3: '', // empty value
314+
},
301315
expected: false,
302316
},
303317
{
304318
name: 'returns false if one of the param values does not match',
305319
params: params,
306-
requestParams: ['Arg1=not-value-1', 'arg2=value2=SOME=other=value', 'arg3===value3&*1(*+'],
320+
requestParams: {
321+
Arg1: 'Arg1=not-value-1', // this value does not match
322+
arg2: 'value2=SOME=other=value',
323+
arg3: '==value3&*1(*+',
324+
},
307325
expected: false,
308326
},
309327
{
310328
name: 'returns false if the case of one param values does not match',
311329
params: params,
312-
requestParams: ['Arg1=VALUE1', 'arg2=value2=SOME=other=value', 'arg3===value3&*1(*+'],
330+
requestParams: {
331+
Arg1: 'VALUE1', // this value is not the correct case
332+
arg2: 'value2=SOME=other=value',
333+
arg3: '==value3&*1(*+',
334+
},
335+
expected: false,
336+
},
337+
{
338+
name: 'returns false if the case of one param name does not match',
339+
params: params,
340+
requestParams: {
341+
Arg1: 'value1',
342+
arg2: 'value2=SOME=other=value',
343+
ARG3: '==value3&*1(*+', // this param name is not the correct case
344+
},
313345
expected: false,
314346
},
315347
{
316348
name: 'returns true if all params match',
317349
params: params,
318-
requestParams: params,
350+
requestParams: {
351+
Arg1: 'value1',
352+
arg2: 'value2=SOME=other=value',
353+
arg3: '==value3&*1(*+',
354+
},
355+
expected: true,
356+
},
357+
{
358+
name: 'returns true if all params match with one param having multiple values',
359+
params: params,
360+
requestParams: {
361+
Arg1: ['value1', 'value2'], // 'value1' wins
362+
arg2: 'value2=SOME=other=value',
363+
arg3: '==value3&*1(*+',
364+
},
365+
expected: true,
366+
},
367+
{
368+
name: 'returns false if one param does not match because of multiple values',
369+
params: params,
370+
requestParams: {
371+
Arg1: ['value2', 'value1'], // 'value2' wins but it does not match
372+
arg2: 'value2=SOME=other=value',
373+
arg3: '==value3&*1(*+',
374+
},
319375
expected: false,
320376
},
321377
];

0 commit comments

Comments
 (0)