From 11c7d20498f6592b90335920487fa0a40acdc271 Mon Sep 17 00:00:00 2001 From: Andreas Lind Date: Mon, 10 Feb 2020 21:55:36 +0100 Subject: [PATCH 1/4] Always use the qs module, even in simple mode https://github.com/expressjs/body-parser/pull/326#issuecomment-521823039 --- lib/types/urlencoded.js | 48 ++++++----------------------------------- 1 file changed, 7 insertions(+), 41 deletions(-) diff --git a/lib/types/urlencoded.js b/lib/types/urlencoded.js index f4ba2cd0..707f004d 100644 --- a/lib/types/urlencoded.js +++ b/lib/types/urlencoded.js @@ -19,6 +19,7 @@ var debug = require('debug')('body-parser:urlencoded') var isFinished = require('on-finished').isFinished var read = require('../read') var typeis = require('type-is') +var qs = require('qs') /** * Module exports. @@ -26,12 +27,6 @@ var typeis = require('type-is') module.exports = urlencoded -/** - * Cache of parser modules. - */ - -var parsers = Object.create(null) - /** * Create a middleware to parse urlencoded bodies. * @@ -130,7 +125,6 @@ function extendedparser (options) { var parameterLimit = options.parameterLimit !== undefined ? options.parameterLimit : 1000 - var parse = parser('qs') if (isNaN(parameterLimit) || parameterLimit < 1) { throw new TypeError('option parameterLimit must be a positive number') @@ -153,7 +147,7 @@ function extendedparser (options) { var arrayLimit = Math.max(100, paramCount) debug('parse extended urlencoding') - return parse(body, { + return qs.parse(body, { allowPrototypes: true, arrayLimit: arrayLimit, depth: Infinity, @@ -201,37 +195,6 @@ function parameterCount (body, limit) { return count } -/** - * Get parser for module name dynamically. - * - * @param {string} name - * @return {function} - * @api private - */ - -function parser (name) { - var mod = parsers[name] - - if (mod !== undefined) { - return mod.parse - } - - // this uses a switch for static require analysis - switch (name) { - case 'qs': - mod = require('qs') - break - case 'querystring': - mod = require('querystring') - break - } - - // store to prevent invoking require() - parsers[name] = mod - - return mod.parse -} - /** * Get the simple query parser. * @@ -242,7 +205,6 @@ function simpleparser (options) { var parameterLimit = options.parameterLimit !== undefined ? options.parameterLimit : 1000 - var parse = parser('querystring') if (isNaN(parameterLimit) || parameterLimit < 1) { throw new TypeError('option parameterLimit must be a positive number') @@ -263,7 +225,11 @@ function simpleparser (options) { } debug('parse urlencoding') - return parse(body, undefined, undefined, { maxKeys: parameterLimit }) + return qs.parse(body, { + allowPrototypes: true, + depth: 0, + parameterLimit: parameterLimit + }) } } From f8fd3541aebf05830e9722b74d3c4b7b45b93590 Mon Sep 17 00:00:00 2001 From: Andreas Lind Date: Mon, 10 Feb 2020 22:15:09 +0100 Subject: [PATCH 2/4] Create the simple and extended parser with the same function, reducing duplication --- lib/types/urlencoded.js | 53 +++++++---------------------------------- 1 file changed, 8 insertions(+), 45 deletions(-) diff --git a/lib/types/urlencoded.js b/lib/types/urlencoded.js index 707f004d..552b8ff2 100644 --- a/lib/types/urlencoded.js +++ b/lib/types/urlencoded.js @@ -51,9 +51,7 @@ function urlencoded (options) { } // create the appropriate query parser - var queryparse = extended - ? extendedparser(opts) - : simpleparser(opts) + var queryparse = createQueryParser(opts, extended); // create the appropriate type checking function var shouldParse = typeof type !== 'function' @@ -121,7 +119,7 @@ function urlencoded (options) { * @param {object} options */ -function extendedparser (options) { +function createQueryParser (options, extended) { var parameterLimit = options.parameterLimit !== undefined ? options.parameterLimit : 1000 @@ -134,6 +132,8 @@ function extendedparser (options) { parameterLimit = parameterLimit | 0 } + var depth = extended ? Infinity : 0; + return function queryparse (body) { var paramCount = parameterCount(body, parameterLimit) @@ -144,13 +144,14 @@ function extendedparser (options) { }) } - var arrayLimit = Math.max(100, paramCount) + var arrayLimit = extended ? Math.max(100, paramCount) : 0 + + debug('parse ' + (extended ? 'extended ' : '') + 'urlencoding') - debug('parse extended urlencoding') return qs.parse(body, { allowPrototypes: true, arrayLimit: arrayLimit, - depth: Infinity, + depth: depth, parameterLimit: parameterLimit }) } @@ -195,44 +196,6 @@ function parameterCount (body, limit) { return count } -/** - * Get the simple query parser. - * - * @param {object} options - */ - -function simpleparser (options) { - var parameterLimit = options.parameterLimit !== undefined - ? options.parameterLimit - : 1000 - - if (isNaN(parameterLimit) || parameterLimit < 1) { - throw new TypeError('option parameterLimit must be a positive number') - } - - if (isFinite(parameterLimit)) { - parameterLimit = parameterLimit | 0 - } - - return function queryparse (body) { - var paramCount = parameterCount(body, parameterLimit) - - if (paramCount === undefined) { - debug('too many parameters') - throw createError(413, 'too many parameters', { - type: 'parameters.too.many' - }) - } - - debug('parse urlencoding') - return qs.parse(body, { - allowPrototypes: true, - depth: 0, - parameterLimit: parameterLimit - }) - } -} - /** * Get the simple type checker. * From 2655928f1deb6863747da6f9ff1afa4bd70061f5 Mon Sep 17 00:00:00 2001 From: Andreas Lind Date: Mon, 10 Feb 2020 22:18:43 +0100 Subject: [PATCH 3/4] Don't mention the querystring module in the README --- README.md | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index c9cbf023..c67f27e9 100644 --- a/README.md +++ b/README.md @@ -228,12 +228,10 @@ any of the following keys: ##### extended -The `extended` option allows to choose between parsing the URL-encoded data -with the `querystring` library (when `false`) or the `qs` library (when -`true`). The "extended" syntax allows for rich objects and arrays to be -encoded into the URL-encoded format, allowing for a JSON-like experience -with URL-encoded. For more information, please -[see the qs library](https://www.npmjs.org/package/qs#readme). +The "extended" syntax allows for rich objects and arrays to be encoded into the +URL-encoded format, allowing for a JSON-like experience with URL-encoded. For +more information, please [see the qs +library](https://www.npmjs.org/package/qs#readme). Defaults to `false`. From 9b83d8181f86f03fcdb0fae8e0e7476e8f60da9e Mon Sep 17 00:00:00 2001 From: Andreas Lind Date: Mon, 10 Feb 2020 22:25:57 +0100 Subject: [PATCH 4/4] Fix lint --- lib/types/urlencoded.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/types/urlencoded.js b/lib/types/urlencoded.js index 552b8ff2..6bef1141 100644 --- a/lib/types/urlencoded.js +++ b/lib/types/urlencoded.js @@ -51,7 +51,7 @@ function urlencoded (options) { } // create the appropriate query parser - var queryparse = createQueryParser(opts, extended); + var queryparse = createQueryParser(opts, extended) // create the appropriate type checking function var shouldParse = typeof type !== 'function' @@ -132,7 +132,7 @@ function createQueryParser (options, extended) { parameterLimit = parameterLimit | 0 } - var depth = extended ? Infinity : 0; + var depth = extended ? Infinity : 0 return function queryparse (body) { var paramCount = parameterCount(body, parameterLimit)