diff --git a/docs/_api/plugins.md b/docs/_api/plugins.md index 7dc9a3130..5df4aefaf 100644 --- a/docs/_api/plugins.md +++ b/docs/_api/plugins.md @@ -369,6 +369,9 @@ Many options correspond directly to option defined for the underlying methods, e.g. `?hasOwnProperty=blah`. (optional, default `false`) - `options.strictNullHandling` **[Boolean][88]** If true, `?a&b=` results in `{a: null, b: ''}`. Otherwise, `{a: '', b: ''}`. (optional, default `false`) + - `options.throwOnLimitExceeded` **[Boolean][88]** If true, throws + (surfaced as a `InvalidContentError`) when `arrayLimit` or `parameterLimit` + is exceeded, instead of silently dropping the offending params. (optional, default `false`) #### Examples @@ -476,6 +479,12 @@ All bodyParsers support the following options: Limits the amount of memory all fields together (except files) can allocate in bytes. The default size is `2 * 1024 * 1024` bytes _(2MB)_. (optional, default `2*1024*1024`) + - `options.arrayLimit` **[Number][86]** `urlEncodedBodyParser` only. Only + transform `a[$index]=b` to an array if `$index` is less than `arrayLimit`. (optional, default `20`) + - `options.throwOnLimitExceeded` **[Boolean][88]** `urlEncodedBodyParser` + only. If true, throws when `arrayLimit` or `parameterLimit` is exceeded, + instead of silently dropping the offending params. The error is surfaced + as an `InvalidContentError`. (optional, default `false`) #### Examples diff --git a/lib/plugins/bodyParser.js b/lib/plugins/bodyParser.js index aaf4d5fac..49170dac8 100644 --- a/lib/plugins/bodyParser.js +++ b/lib/plugins/bodyParser.js @@ -95,6 +95,12 @@ var UnsupportedMediaTypeError = errors.UnsupportedMediaTypeError; * Limits the amount of memory all fields together (except files) * can allocate in bytes. * The default size is `2 * 1024 * 1024` bytes *(2MB)*. + * @param {Number} [options.arrayLimit=20] - `urlEncodedBodyParser` only. Only + * transform `a[$index]=b` to an array if `$index` is less than `arrayLimit`. + * @param {Boolean} [options.throwOnLimitExceeded=false] - `urlEncodedBodyParser` + * only. If true, throws when `arrayLimit` or `parameterLimit` is exceeded, + * instead of silently dropping the offending params. The error is surfaced + * as an `InvalidContentError`. * @returns {Function} Handler * @example * server.use(restify.plugins.bodyParser({ diff --git a/lib/plugins/formBodyParser.js b/lib/plugins/formBodyParser.js index 45731e8e7..42fac4dbc 100644 --- a/lib/plugins/formBodyParser.js +++ b/lib/plugins/formBodyParser.js @@ -24,6 +24,12 @@ var MIME_TYPE = 'application/x-www-form-urlencoded'; * @public * @function urlEncodedBodyParser * @param {Object} options - an option sobject + * @param {Number} [options.arrayLimit=20] - Only transform `a[$index]=b` + * to an array if `$index` is less than `arrayLimit`. + * @param {Boolean} [options.throwOnLimitExceeded=false] - If true, throws + * when `arrayLimit` or `parameterLimit` is exceeded, instead of silently + * dropping the offending params. The error is surfaced as an + * `InvalidContentError`. * @returns {Function} Handler */ function urlEncodedBodyParser(options) { @@ -42,7 +48,7 @@ function urlEncodedBodyParser(options) { } try { - var params = querystring.parse(req.body); + var params = querystring.parse(req.body, opts); if (opts.mapParams === true) { var keys = Object.keys(params); diff --git a/lib/plugins/query.js b/lib/plugins/query.js index 49aec971f..bfcb37e0c 100644 --- a/lib/plugins/query.js +++ b/lib/plugins/query.js @@ -4,6 +4,7 @@ var qs = require('qs'); var assert = require('assert-plus'); +var errors = require('restify-errors'); /** * Parses the HTTP query string (i.e., `/foo?id=bar&name=mark`). @@ -39,6 +40,9 @@ var assert = require('assert-plus'); * methods, e.g. `?hasOwnProperty=blah`. * @param {Boolean} [options.strictNullHandling=false] - If true, `?a&b=` * results in `{a: null, b: ''}`. Otherwise, `{a: '', b: ''}`. + * @param {Boolean} [options.throwOnLimitExceeded=false] - If true, throws + * (surfaced as a `InvalidContentError`) when `arrayLimit` or `parameterLimit` + * is exceeded, instead of silently dropping the offending params. * @returns {Function} Handler * @example * server.use(restify.plugins.queryParser({ mapParams: false })); @@ -53,7 +57,11 @@ function queryParser(options) { return next(); } - req.query = qs.parse(req.getQuery(), opts); + try { + req.query = qs.parse(req.getQuery(), opts); + } catch (e) { + return next(new errors.InvalidContentError(e.message)); + } if (opts.mapParams === true) { Object.keys(req.query).forEach(function forEach(k) { diff --git a/package.json b/package.json index ebbc092f2..e6f541a8f 100644 --- a/package.json +++ b/package.json @@ -107,7 +107,7 @@ "once": "^1.4.0", "pidusage": "^3.0.2", "pino": "^8.7.0", - "qs": "^6.7.0", + "qs": "^6.15.2", "restify-errors": "^8.0.2", "semver": "^7.3.8", "send": "^1.2.1",