Skip to content

Commit

Permalink
feat: parse: add throwOnParameterLimitExceeded option
Browse files Browse the repository at this point in the history
  • Loading branch information
IamLizu committed Nov 12, 2024
1 parent d185cee commit 692ea72
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 2 deletions.
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,18 @@ var limited = qs.parse('a=b&c=d', { parameterLimit: 1 });
assert.deepEqual(limited, { a: 'b' });
```

If you want an error to be thrown whenever the parameter limit is exceeded, set the `throwOnParameterLimitExceeded` option to `true`. This option will generate a descriptive error if the query string exceeds the parameterLimit.
```javascript
try {
qs.parse('a=1&b=2&c=3&d=4', { parameterLimit: 3, throwOnParameterLimitExceeded: true });
} catch (err) {
assert(err instanceof Error);
assert.strictEqual(err.message, 'Parameter limit exceeded. Only 3 parameters allowed.');
}
```

When `throwOnParameterLimitExceeded` is set to `false` (default), **qs** will parse up to the specified `parameterLimit` and ignore the rest without throwing an error.

To bypass the leading question mark, use `ignoreQueryPrefix`:

```javascript
Expand Down
16 changes: 14 additions & 2 deletions lib/parse.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,19 @@ var parseValues = function parseQueryStringValues(str, options) {

var cleanStr = options.ignoreQueryPrefix ? str.replace(/^\?/, '') : str;
cleanStr = cleanStr.replace(/%5B/gi, '[').replace(/%5D/gi, ']');

// Calculate limit and split query string
var limit = options.parameterLimit === Infinity ? undefined : options.parameterLimit;
var parts = cleanStr.split(options.delimiter, limit);
var parts = cleanStr.split(options.delimiter);

// Check if parts exceed the parameter limit and handle it
if (parts.length > limit) {
if (options.throwOnParameterLimitExceeded) {
throw new Error(`Parameter limit exceeded. Only ${limit} parameters allowed.`);
}
parts = parts.slice(0, limit); // Keep only up to the limit
}

var skipIndex = -1; // Keep track of where the utf8 sentinel was found
var i;

Expand Down Expand Up @@ -266,7 +277,8 @@ var normalizeParseOptions = function normalizeParseOptions(opts) {
parseArrays: opts.parseArrays !== false,
plainObjects: typeof opts.plainObjects === 'boolean' ? opts.plainObjects : defaults.plainObjects,
strictDepth: typeof opts.strictDepth === 'boolean' ? !!opts.strictDepth : defaults.strictDepth,
strictNullHandling: typeof opts.strictNullHandling === 'boolean' ? opts.strictNullHandling : defaults.strictNullHandling
strictNullHandling: typeof opts.strictNullHandling === 'boolean' ? opts.strictNullHandling : defaults.strictNullHandling,
throwOnParameterLimitExceeded: typeof opts.throwOnParameterLimitExceeded === 'boolean' ? opts.throwOnParameterLimitExceeded : false
};
};

Expand Down
40 changes: 40 additions & 0 deletions test/parse.js
Original file line number Diff line number Diff line change
Expand Up @@ -1035,6 +1035,46 @@ test('parse()', function (t) {
st.end();
});

t.test('parameter limit tests', function (st) {
st.test('does not throw error when within parameter limit', function (sst) {
const result = qs.parse('a=1&b=2&c=3', { parameterLimit: 5, throwOnParameterLimitExceeded: true });
sst.deepEqual(result, { a: '1', b: '2', c: '3' }, 'Should parse without errors');
sst.end();
});

st.test('throws error when parameter limit exceeded', function (sst) {
sst.throws(
function () {
qs.parse('a=1&b=2&c=3&d=4&e=5&f=6', { parameterLimit: 3, throwOnParameterLimitExceeded: true });
},
new Error('Parameter limit exceeded. Only 3 parameters allowed.'),
'Should throw error when parameter limit is exceeded'
);
sst.end();
});

st.test('silently truncates when throwOnParameterLimitExceeded is not given', function (sst) {
const result = qs.parse('a=1&b=2&c=3&d=4&e=5', { parameterLimit: 3 });
sst.deepEqual(result, { a: '1', b: '2', c: '3' }, 'Should parse and truncate silently');
sst.end();
});

st.test('silently truncates when parameter limit exceeded without error', function (sst) {
const result = qs.parse('a=1&b=2&c=3&d=4&e=5', { parameterLimit: 3, throwOnParameterLimitExceeded: false });
sst.deepEqual(result, { a: '1', b: '2', c: '3' }, 'Should parse and truncate silently');
sst.end();
});

st.test('allows unlimited parameters when parameterLimit set to Infinity', function (sst) {
const result = qs.parse('a=1&b=2&c=3&d=4&e=5&f=6', { parameterLimit: Infinity });
sst.deepEqual(result, { a: '1', b: '2', c: '3', d: '4', e: '5', f: '6' }, 'Should parse all parameters without truncation');
sst.end();
});

st.end();
});


t.end();
});

Expand Down

0 comments on commit 692ea72

Please sign in to comment.