From 7eb00cdc9b3c3a73ce51aefba899afab67bc8abc Mon Sep 17 00:00:00 2001 From: Andreas Lind Date: Thu, 25 Jul 2024 01:38:43 +0200 Subject: [PATCH] Also use the qs module for the simple parser (#387) * Always use the qs module, even in simple mode https://github.com/expressjs/body-parser/pull/326#issuecomment-521823039 * Create the simple and extended parser with the same function, reducing duplication * Don't mention the querystring module in the README * Fix lint --- README.md | 10 ++--- lib/types/urlencoded.js | 91 +++++------------------------------------ 2 files changed, 14 insertions(+), 87 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`. diff --git a/lib/types/urlencoded.js b/lib/types/urlencoded.js index f4ba2cd0..6bef1141 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. * @@ -56,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' @@ -126,11 +119,10 @@ function urlencoded (options) { * @param {object} options */ -function extendedparser (options) { +function createQueryParser (options, extended) { 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') @@ -140,6 +132,8 @@ function extendedparser (options) { parameterLimit = parameterLimit | 0 } + var depth = extended ? Infinity : 0 + return function queryparse (body) { var paramCount = parameterCount(body, parameterLimit) @@ -150,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 parse(body, { + return qs.parse(body, { allowPrototypes: true, arrayLimit: arrayLimit, - depth: Infinity, + depth: depth, parameterLimit: parameterLimit }) } @@ -201,72 +196,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. - * - * @param {object} options - */ - -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') - } - - 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 parse(body, undefined, undefined, { maxKeys: parameterLimit }) - } -} - /** * Get the simple type checker. *