https://project.mdnd-it.cc/work_packages/94
This commit is contained in:
2025-08-23 04:25:28 +02:00
parent 725516ad6c
commit 19cfa031d0
25823 changed files with 1095587 additions and 2801760 deletions
+60 -1
View File
@@ -1,10 +1,69 @@
2.2.0 / 2025-03-27
=========================
* refactor: normalize common options for all parsers
* deps:
* iconv-lite@^0.6.3
2.1.0 / 2025-02-10
=========================
* deps:
* type-is@^2.0.0
* debug@^4.4.0
* Removed destroy
* refactor: prefix built-in node module imports
* use the node require cache instead of custom caching
2.0.2 / 2024-10-31
=========================
* remove `unpipe` package and use native `unpipe()` method
2.0.1 / 2024-09-10
=========================
* Restore expected behavior `extended` to `false`
2.0.0 / 2024-09-10
=========================
* Propagate changes from 1.20.3
* add brotli support #406
* Breaking Change: Node.js 18 is the minimum supported version
2.0.0-beta.2 / 2023-02-23
=========================
This incorporates all changes after 1.19.1 up to 1.20.2.
* Remove deprecated `bodyParser()` combination middleware
* deps: debug@3.1.0
- Add `DEBUG_HIDE_DATE` environment variable
- Change timer to per-namespace instead of global
- Change non-TTY date format
- Remove `DEBUG_FD` environment variable support
- Support 256 namespace colors
* deps: iconv-lite@0.5.2
- Add encoding cp720
- Add encoding UTF-32
* deps: raw-body@3.0.0-beta.1
2.0.0-beta.1 / 2021-12-17
=========================
* Drop support for Node.js 0.8
* `req.body` is no longer always initialized to `{}`
- it is left `undefined` unless a body is parsed
* `urlencoded` parser now defaults `extended` to `false`
* Use `on-finished` to determine when body read
1.20.3 / 2024-09-10
===================
* deps: qs@6.13.0
* add `depth` option to customize the depth level in the parser
* IMPORTANT: The default `depth` level for parsing URL-encoded data is now `32` (previously was `Infinity`)
1.20.2 / 2023-02-21
===================
+46 -31
View File
@@ -51,14 +51,12 @@ $ npm install body-parser
## API
```js
var bodyParser = require('body-parser')
const bodyParser = require('body-parser')
```
The `bodyParser` object exposes various factories to create middlewares. All
middlewares will populate the `req.body` property with the parsed body when
the `Content-Type` request header matches the `type` option, or an empty
object (`{}`) if there was no body to parse, the `Content-Type` was not matched,
or an error occurred.
the `Content-Type` request header matches the `type` option.
The various errors returned by this module are described in the
[errors section](#errors).
@@ -67,8 +65,8 @@ The various errors returned by this module are described in the
Returns middleware that only parses `json` and only looks at requests where
the `Content-Type` header matches the `type` option. This parser accepts any
Unicode encoding of the body and supports automatic inflation of `gzip` and
`deflate` encodings.
Unicode encoding of the body and supports automatic inflation of `gzip`,
`br` (brotli) and `deflate` encodings.
A new `body` object containing the parsed data is populated on the `request`
object after the middleware (i.e. `req.body`).
@@ -122,7 +120,8 @@ encoding of the request. The parsing can be aborted by throwing an error.
Returns middleware that parses all bodies as a `Buffer` and only looks at
requests where the `Content-Type` header matches the `type` option. This
parser supports automatic inflation of `gzip` and `deflate` encodings.
parser supports automatic inflation of `gzip`, `br` (brotli) and `deflate`
encodings.
A new `body` object containing the parsed data is populated on the `request`
object after the middleware (i.e. `req.body`). This will be a `Buffer` object
@@ -167,7 +166,8 @@ encoding of the request. The parsing can be aborted by throwing an error.
Returns middleware that parses all bodies as a string and only looks at
requests where the `Content-Type` header matches the `type` option. This
parser supports automatic inflation of `gzip` and `deflate` encodings.
parser supports automatic inflation of `gzip`, `br` (brotli) and `deflate`
encodings.
A new `body` string containing the parsed data is populated on the `request`
object after the middleware (i.e. `req.body`). This will be a string of the
@@ -217,7 +217,7 @@ encoding of the request. The parsing can be aborted by throwing an error.
Returns middleware that only parses `urlencoded` bodies and only looks at
requests where the `Content-Type` header matches the `type` option. This
parser accepts only UTF-8 encoding of the body and supports automatic
inflation of `gzip` and `deflate` encodings.
inflation of `gzip`, `br` (brotli) and `deflate` encodings.
A new `body` object containing the parsed data is populated on the `request`
object after the middleware (i.e. `req.body`). This object will contain
@@ -231,16 +231,12 @@ 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 `true`, but using the default has been deprecated. Please
research into the difference between `qs` and `querystring` and choose the
appropriate setting.
Defaults to `false`.
##### inflate
@@ -278,6 +274,23 @@ The `verify` option, if supplied, is called as `verify(req, res, buf, encoding)`
where `buf` is a `Buffer` of the raw request body and `encoding` is the
encoding of the request. The parsing can be aborted by throwing an error.
##### defaultCharset
The default charset to parse as, if not specified in content-type. Must be
either `utf-8` or `iso-8859-1`. Defaults to `utf-8`.
##### charsetSentinel
Whether to let the value of the `utf8` parameter take precedence as the charset
selector. It requires the form to contain a parameter named `utf8` with a value
of `✓`. Defaults to `false`.
##### interpretNumericEntities
Whether to decode numeric entities such as `☺` when parsing an iso-8859-1
form. Defaults to `false`.
#### depth
The `depth` option is used to configure the maximum depth of the `qs` library when `extended` is `true`. This allows you to limit the amount of keys that are parsed and can be useful to prevent certain types of abuse. Defaults to `32`. It is recommended to keep this value as low as possible.
@@ -391,13 +404,13 @@ top-level middleware, which will parse the bodies of all incoming requests.
This is the simplest setup.
```js
var express = require('express')
var bodyParser = require('body-parser')
const express = require('express')
const bodyParser = require('body-parser')
var app = express()
const app = express()
// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }))
app.use(bodyParser.urlencoded())
// parse application/json
app.use(bodyParser.json())
@@ -405,7 +418,7 @@ app.use(bodyParser.json())
app.use(function (req, res) {
res.setHeader('Content-Type', 'text/plain')
res.write('you posted:\n')
res.end(JSON.stringify(req.body, null, 2))
res.end(String(JSON.stringify(req.body, null, 2)))
})
```
@@ -416,24 +429,26 @@ need them. In general, this is the most recommended way to use body-parser with
Express.
```js
var express = require('express')
var bodyParser = require('body-parser')
const express = require('express')
const bodyParser = require('body-parser')
var app = express()
const app = express()
// create application/json parser
var jsonParser = bodyParser.json()
const jsonParser = bodyParser.json()
// create application/x-www-form-urlencoded parser
var urlencodedParser = bodyParser.urlencoded({ extended: false })
const urlencodedParser = bodyParser.urlencoded()
// POST /login gets urlencoded bodies
app.post('/login', urlencodedParser, function (req, res) {
if (!req.body || !req.body.username) res.sendStatus(400)
res.send('welcome, ' + req.body.username)
})
// POST /api/users gets JSON bodies
app.post('/api/users', jsonParser, function (req, res) {
if (!req.body) res.sendStatus(400)
// create user in req.body
})
```
@@ -444,10 +459,10 @@ All the parsers accept a `type` option which allows you to change the
`Content-Type` that the middleware will parse.
```js
var express = require('express')
var bodyParser = require('body-parser')
const express = require('express')
const bodyParser = require('body-parser')
var app = express()
const app = express()
// parse various different custom JSON types as JSON
app.use(bodyParser.json({ type: 'application/*+json' }))
-25
View File
@@ -1,25 +0,0 @@
# Security Policies and Procedures
## Reporting a Bug
The Express team and community take all security bugs seriously. Thank you
for improving the security of Express. We appreciate your efforts and
responsible disclosure and will make every effort to acknowledge your
contributions.
Report security bugs by emailing the current owner(s) of `body-parser`. This
information can be found in the npm registry using the command
`npm owner ls body-parser`.
If unsure or unable to get the information from the above, open an issue
in the [project issue tracker](https://github.com/expressjs/body-parser/issues)
asking for the current contact information.
To ensure the timely response to your report, please ensure that the entirety
of the report is contained within the email body and not solely behind a web
link or an attachment.
At least one owner will acknowledge your email within 48 hours, and will send a
more detailed response within 48 hours indicating the next steps in handling
your report. After the initial reply to your report, the owners will
endeavor to keep you informed of the progress towards a fix and full
announcement, and may ask for additional information or guidance.
+7 -83
View File
@@ -6,20 +6,6 @@
'use strict'
/**
* Module dependencies.
* @private
*/
var deprecate = require('depd')('body-parser')
/**
* Cache of loaded parsers.
* @private
*/
var parsers = Object.create(null)
/**
* @typedef Parsers
* @type {function}
@@ -34,8 +20,7 @@ var parsers = Object.create(null)
* @type {Parsers}
*/
exports = module.exports = deprecate.function(bodyParser,
'bodyParser: use individual json/urlencoded middlewares')
exports = module.exports = bodyParser
/**
* JSON parser.
@@ -45,7 +30,7 @@ exports = module.exports = deprecate.function(bodyParser,
Object.defineProperty(exports, 'json', {
configurable: true,
enumerable: true,
get: createParserGetter('json')
get: () => require('./lib/types/json')
})
/**
@@ -56,7 +41,7 @@ Object.defineProperty(exports, 'json', {
Object.defineProperty(exports, 'raw', {
configurable: true,
enumerable: true,
get: createParserGetter('raw')
get: () => require('./lib/types/raw')
})
/**
@@ -67,7 +52,7 @@ Object.defineProperty(exports, 'raw', {
Object.defineProperty(exports, 'text', {
configurable: true,
enumerable: true,
get: createParserGetter('text')
get: () => require('./lib/types/text')
})
/**
@@ -78,7 +63,7 @@ Object.defineProperty(exports, 'text', {
Object.defineProperty(exports, 'urlencoded', {
configurable: true,
enumerable: true,
get: createParserGetter('urlencoded')
get: () => require('./lib/types/urlencoded')
})
/**
@@ -90,67 +75,6 @@ Object.defineProperty(exports, 'urlencoded', {
* @public
*/
function bodyParser (options) {
// use default type for parsers
var opts = Object.create(options || null, {
type: {
configurable: true,
enumerable: true,
value: undefined,
writable: true
}
})
var _urlencoded = exports.urlencoded(opts)
var _json = exports.json(opts)
return function bodyParser (req, res, next) {
_json(req, res, function (err) {
if (err) return next(err)
_urlencoded(req, res, next)
})
}
}
/**
* Create a getter for loading a parser.
* @private
*/
function createParserGetter (name) {
return function get () {
return loadParser(name)
}
}
/**
* Load a parser module.
* @private
*/
function loadParser (parserName) {
var parser = parsers[parserName]
if (parser !== undefined) {
return parser
}
// this uses a switch for static require analysis
switch (parserName) {
case 'json':
parser = require('./lib/types/json')
break
case 'raw':
parser = require('./lib/types/raw')
break
case 'text':
parser = require('./lib/types/text')
break
case 'urlencoded':
parser = require('./lib/types/urlencoded')
break
}
// store to prevent invoking require()
return (parsers[parserName] = parser)
function bodyParser () {
throw new Error('The bodyParser() generic has been split into individual middleware to use instead.')
}
+27 -22
View File
@@ -12,12 +12,10 @@
*/
var createError = require('http-errors')
var destroy = require('destroy')
var getBody = require('raw-body')
var iconv = require('iconv-lite')
var onFinished = require('on-finished')
var unpipe = require('unpipe')
var zlib = require('zlib')
var zlib = require('node:zlib')
/**
* Module exports.
@@ -42,9 +40,6 @@ function read (req, res, next, parse, debug, options) {
var opts = options
var stream
// flag as parsed
req._body = true
// read options
var encoding = opts.encoding !== null
? opts.encoding
@@ -93,8 +88,8 @@ function read (req, res, next, parse, debug, options) {
// unpipe from stream and destroy
if (stream !== req) {
unpipe(req)
destroy(stream, true)
req.unpipe()
stream.destroy()
}
// read off entire request
@@ -125,7 +120,7 @@ function read (req, res, next, parse, debug, options) {
str = typeof body !== 'string' && encoding !== null
? iconv.decode(body, encoding)
: body
req.body = parse(str)
req.body = parse(str, encoding)
} catch (err) {
next(createError(400, err, {
body: str,
@@ -151,7 +146,6 @@ function read (req, res, next, parse, debug, options) {
function contentstream (req, debug, inflate) {
var encoding = (req.headers['content-encoding'] || 'identity').toLowerCase()
var length = req.headers['content-length']
var stream
debug('content-encoding "%s"', encoding)
@@ -162,29 +156,40 @@ function contentstream (req, debug, inflate) {
})
}
if (encoding === 'identity') {
req.length = length
return req
}
var stream = createDecompressionStream(encoding, debug)
req.pipe(stream)
return stream
}
/**
* Create a decompression stream for the given encoding.
* @param {string} encoding
* @param {function} debug
* @return {object}
* @api private
*/
function createDecompressionStream (encoding, debug) {
switch (encoding) {
case 'deflate':
stream = zlib.createInflate()
debug('inflate body')
req.pipe(stream)
break
return zlib.createInflate()
case 'gzip':
stream = zlib.createGunzip()
debug('gunzip body')
req.pipe(stream)
break
case 'identity':
stream = req
stream.length = length
break
return zlib.createGunzip()
case 'br':
debug('brotli decompress body')
return zlib.createBrotliDecompress()
default:
throw createError(415, 'unsupported content encoding "' + encoding + '"', {
encoding: encoding,
type: 'encoding.unsupported'
})
}
return stream
}
/**
+12 -53
View File
@@ -12,12 +12,12 @@
* @private
*/
var bytes = require('bytes')
var contentType = require('content-type')
var createError = require('http-errors')
var debug = require('debug')('body-parser:json')
var isFinished = require('on-finished').isFinished
var read = require('../read')
var typeis = require('type-is')
var { getCharset, normalizeOptions } = require('../utils')
/**
* Module exports.
@@ -51,25 +51,10 @@ var JSON_SYNTAX_REGEXP = /#+/g
*/
function json (options) {
var opts = options || {}
var { inflate, limit, verify, shouldParse } = normalizeOptions(options, 'application/json')
var limit = typeof opts.limit !== 'number'
? bytes.parse(opts.limit || '100kb')
: opts.limit
var inflate = opts.inflate !== false
var reviver = opts.reviver
var strict = opts.strict !== false
var type = opts.type || 'application/json'
var verify = opts.verify || false
if (verify !== false && typeof verify !== 'function') {
throw new TypeError('option verify must be function')
}
// create the appropriate type checking function
var shouldParse = typeof type !== 'function'
? typeChecker(type)
: type
var reviver = options?.reviver
var strict = options?.strict !== false
function parse (body) {
if (body.length === 0) {
@@ -99,13 +84,15 @@ function json (options) {
}
return function jsonParser (req, res, next) {
if (req._body) {
if (isFinished(req)) {
debug('body already parsed')
next()
return
}
req.body = req.body || {}
if (!('body' in req)) {
req.body = undefined
}
// skip requests without bodies
if (!typeis.hasBody(req)) {
@@ -137,9 +124,9 @@ function json (options) {
// read
read(req, res, next, parse, debug, {
encoding: charset,
inflate: inflate,
limit: limit,
verify: verify
inflate,
limit,
verify
})
}
}
@@ -193,21 +180,6 @@ function firstchar (str) {
: undefined
}
/**
* Get the charset of a request.
*
* @param {object} req
* @api private
*/
function getCharset (req) {
try {
return (contentType.parse(req).parameters.charset || '').toLowerCase()
} catch (e) {
return undefined
}
}
/**
* Normalize a SyntaxError for JSON.parse.
*
@@ -232,16 +204,3 @@ function normalizeJsonSyntaxError (error, obj) {
return error
}
/**
* Get the simple type checker.
*
* @param {string} type
* @return {function}
*/
function typeChecker (type) {
return function checkType (req) {
return Boolean(typeis(req, type))
}
}
+10 -36
View File
@@ -10,10 +10,11 @@
* Module dependencies.
*/
var bytes = require('bytes')
var debug = require('debug')('body-parser:raw')
var isFinished = require('on-finished').isFinished
var read = require('../read')
var typeis = require('type-is')
var { normalizeOptions } = require('../utils')
/**
* Module exports.
@@ -30,36 +31,22 @@ module.exports = raw
*/
function raw (options) {
var opts = options || {}
var inflate = opts.inflate !== false
var limit = typeof opts.limit !== 'number'
? bytes.parse(opts.limit || '100kb')
: opts.limit
var type = opts.type || 'application/octet-stream'
var verify = opts.verify || false
if (verify !== false && typeof verify !== 'function') {
throw new TypeError('option verify must be function')
}
// create the appropriate type checking function
var shouldParse = typeof type !== 'function'
? typeChecker(type)
: type
var { inflate, limit, verify, shouldParse } = normalizeOptions(options, 'application/octet-stream')
function parse (buf) {
return buf
}
return function rawParser (req, res, next) {
if (req._body) {
if (isFinished(req)) {
debug('body already parsed')
next()
return
}
req.body = req.body || {}
if (!('body' in req)) {
req.body = undefined
}
// skip requests without bodies
if (!typeis.hasBody(req)) {
@@ -80,22 +67,9 @@ function raw (options) {
// read
read(req, res, next, parse, debug, {
encoding: null,
inflate: inflate,
limit: limit,
verify: verify
inflate,
limit,
verify
})
}
}
/**
* Get the simple type checker.
*
* @param {string} type
* @return {function}
*/
function typeChecker (type) {
return function checkType (req) {
return Boolean(typeis(req, type))
}
}
+11 -52
View File
@@ -10,11 +10,11 @@
* Module dependencies.
*/
var bytes = require('bytes')
var contentType = require('content-type')
var debug = require('debug')('body-parser:text')
var isFinished = require('on-finished').isFinished
var read = require('../read')
var typeis = require('type-is')
var { getCharset, normalizeOptions } = require('../utils')
/**
* Module exports.
@@ -31,37 +31,24 @@ module.exports = text
*/
function text (options) {
var opts = options || {}
var { inflate, limit, verify, shouldParse } = normalizeOptions(options, 'text/plain')
var defaultCharset = opts.defaultCharset || 'utf-8'
var inflate = opts.inflate !== false
var limit = typeof opts.limit !== 'number'
? bytes.parse(opts.limit || '100kb')
: opts.limit
var type = opts.type || 'text/plain'
var verify = opts.verify || false
if (verify !== false && typeof verify !== 'function') {
throw new TypeError('option verify must be function')
}
// create the appropriate type checking function
var shouldParse = typeof type !== 'function'
? typeChecker(type)
: type
var defaultCharset = options?.defaultCharset || 'utf-8'
function parse (buf) {
return buf
}
return function textParser (req, res, next) {
if (req._body) {
if (isFinished(req)) {
debug('body already parsed')
next()
return
}
req.body = req.body || {}
if (!('body' in req)) {
req.body = undefined
}
// skip requests without bodies
if (!typeis.hasBody(req)) {
@@ -85,37 +72,9 @@ function text (options) {
// read
read(req, res, next, parse, debug, {
encoding: charset,
inflate: inflate,
limit: limit,
verify: verify
inflate,
limit,
verify
})
}
}
/**
* Get the charset of a request.
*
* @param {object} req
* @api private
*/
function getCharset (req) {
try {
return (contentType.parse(req).parameters.charset || '').toLowerCase()
} catch (e) {
return undefined
}
}
/**
* Get the simple type checker.
*
* @param {string} type
* @return {function}
*/
function typeChecker (type) {
return function checkType (req) {
return Boolean(typeis(req, type))
}
}
+37 -167
View File
@@ -12,13 +12,13 @@
* @private
*/
var bytes = require('bytes')
var contentType = require('content-type')
var createError = require('http-errors')
var debug = require('debug')('body-parser:urlencoded')
var deprecate = require('depd')('body-parser')
var isFinished = require('on-finished').isFinished
var read = require('../read')
var typeis = require('type-is')
var qs = require('qs')
var { getCharset, normalizeOptions } = require('../utils')
/**
* Module exports.
@@ -26,12 +26,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.
*
@@ -41,52 +35,32 @@ var parsers = Object.create(null)
*/
function urlencoded (options) {
var opts = options || {}
var { inflate, limit, verify, shouldParse } = normalizeOptions(options, 'application/x-www-form-urlencoded')
// notice because option default will flip in next major
if (opts.extended === undefined) {
deprecate('undefined extended: provide extended option')
}
var extended = opts.extended !== false
var inflate = opts.inflate !== false
var limit = typeof opts.limit !== 'number'
? bytes.parse(opts.limit || '100kb')
: opts.limit
var type = opts.type || 'application/x-www-form-urlencoded'
var verify = opts.verify || false
var depth = typeof opts.depth !== 'number'
? Number(opts.depth || 32)
: opts.depth
if (verify !== false && typeof verify !== 'function') {
throw new TypeError('option verify must be function')
var defaultCharset = options?.defaultCharset || 'utf-8'
if (defaultCharset !== 'utf-8' && defaultCharset !== 'iso-8859-1') {
throw new TypeError('option defaultCharset must be either utf-8 or iso-8859-1')
}
// create the appropriate query parser
var queryparse = extended
? extendedparser(opts)
: simpleparser(opts)
var queryparse = createQueryParser(options)
// create the appropriate type checking function
var shouldParse = typeof type !== 'function'
? typeChecker(type)
: type
function parse (body) {
function parse (body, encoding) {
return body.length
? queryparse(body)
? queryparse(body, encoding)
: {}
}
return function urlencodedParser (req, res, next) {
if (req._body) {
if (isFinished(req)) {
debug('body already parsed')
next()
return
}
req.body = req.body || {}
if (!('body' in req)) {
req.body = undefined
}
// skip requests without bodies
if (!typeis.hasBody(req)) {
@@ -105,8 +79,8 @@ function urlencoded (options) {
}
// assert charset
var charset = getCharset(req) || 'utf-8'
if (charset !== 'utf-8') {
var charset = getCharset(req) || defaultCharset
if (charset !== 'utf-8' && charset !== 'iso-8859-1') {
debug('invalid charset')
next(createError(415, 'unsupported charset "' + charset.toUpperCase() + '"', {
charset: charset,
@@ -117,12 +91,10 @@ function urlencoded (options) {
// read
read(req, res, next, parse, debug, {
debug: debug,
encoding: charset,
inflate: inflate,
limit: limit,
verify: verify,
depth: depth
inflate,
limit,
verify
})
}
}
@@ -133,15 +105,14 @@ function urlencoded (options) {
* @param {object} options
*/
function extendedparser (options) {
var parameterLimit = options.parameterLimit !== undefined
? options.parameterLimit
function createQueryParser (options) {
var extended = Boolean(options?.extended)
var parameterLimit = options?.parameterLimit !== undefined
? options?.parameterLimit
: 1000
var depth = typeof options.depth !== 'number'
? Number(options.depth || 32)
: options.depth
var parse = parser('qs')
var charsetSentinel = options?.charsetSentinel
var interpretNumericEntities = options?.interpretNumericEntities
var depth = extended ? (options?.depth !== undefined ? options?.depth : 32) : 0
if (isNaN(parameterLimit) || parameterLimit < 1) {
throw new TypeError('option parameterLimit must be a positive number')
@@ -155,7 +126,7 @@ function extendedparser (options) {
parameterLimit = parameterLimit | 0
}
return function queryparse (body) {
return function queryparse (body, encoding) {
var paramCount = parameterCount(body, parameterLimit)
if (paramCount === undefined) {
@@ -165,16 +136,19 @@ function extendedparser (options) {
})
}
var arrayLimit = Math.max(100, paramCount)
var arrayLimit = extended ? Math.max(100, paramCount) : 0
debug('parse extended urlencoding')
debug('parse ' + (extended ? 'extended ' : '') + 'urlencoding')
try {
return parse(body, {
return qs.parse(body, {
allowPrototypes: true,
arrayLimit: arrayLimit,
depth: depth,
strictDepth: true,
parameterLimit: parameterLimit
charsetSentinel: charsetSentinel,
interpretNumericEntities: interpretNumericEntities,
charset: encoding,
parameterLimit: parameterLimit,
strictDepth: true
})
} catch (err) {
if (err instanceof RangeError) {
@@ -188,21 +162,6 @@ function extendedparser (options) {
}
}
/**
* Get the charset of a request.
*
* @param {object} req
* @api private
*/
function getCharset (req) {
try {
return (contentType.parse(req).parameters.charset || '').toLowerCase()
} catch (e) {
return undefined
}
}
/**
* Count the number of parameters, stopping once limit reached
*
@@ -212,96 +171,7 @@ function getCharset (req) {
*/
function parameterCount (body, limit) {
var count = 0
var index = 0
var len = body.split('&').length
while ((index = body.indexOf('&', index)) !== -1) {
count++
index++
if (count === limit) {
return undefined
}
}
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.
*
* @param {string} type
* @return {function}
*/
function typeChecker (type) {
return function checkType (req) {
return Boolean(typeis(req, type))
}
return len > limit ? undefined : len - 1
}
+83
View File
@@ -0,0 +1,83 @@
'use strict'
/**
* Module dependencies.
*/
var bytes = require('bytes')
var contentType = require('content-type')
var typeis = require('type-is')
/**
* Module exports.
*/
module.exports = {
getCharset,
normalizeOptions
}
/**
* Get the charset of a request.
*
* @param {object} req
* @api private
*/
function getCharset (req) {
try {
return (contentType.parse(req).parameters.charset || '').toLowerCase()
} catch {
return undefined
}
}
/**
* Get the simple type checker.
*
* @param {string | string[]} type
* @return {function}
*/
function typeChecker (type) {
return function checkType (req) {
return Boolean(typeis(req, type))
}
}
/**
* Normalizes the common options for all parsers.
*
* @param {object} options options to normalize
* @param {string | string[] | function} defaultType default content type(s) or a function to determine it
* @returns {object}
*/
function normalizeOptions (options, defaultType) {
if (!defaultType) {
// Parsers must define a default content type
throw new TypeError('defaultType must be provided')
}
var inflate = options?.inflate !== false
var limit = typeof options?.limit !== 'number'
? bytes.parse(options?.limit || '100kb')
: options?.limit
var type = options?.type || defaultType
var verify = options?.verify || false
if (verify !== false && typeof verify !== 'function') {
throw new TypeError('option verify must be function')
}
// create the appropriate type checking function
var shouldParse = typeof type !== 'function'
? typeChecker(type)
: type
return {
inflate,
limit,
verify,
shouldParse
}
}
+16 -23
View File
@@ -1,7 +1,7 @@
{
"name": "body-parser",
"description": "Node.js body parsing middleware",
"version": "1.20.3",
"version": "2.2.0",
"contributors": [
"Douglas Christopher Wilson <doug@somethingdoug.com>",
"Jonathan Ong <me@jongleberry.com> (http://jongleberry.com)"
@@ -9,18 +9,15 @@
"license": "MIT",
"repository": "expressjs/body-parser",
"dependencies": {
"bytes": "3.1.2",
"content-type": "~1.0.5",
"debug": "2.6.9",
"depd": "2.0.0",
"destroy": "1.2.0",
"http-errors": "2.0.0",
"iconv-lite": "0.4.24",
"on-finished": "2.4.1",
"qs": "6.13.0",
"raw-body": "2.5.2",
"type-is": "~1.6.18",
"unpipe": "1.0.0"
"bytes": "^3.1.2",
"content-type": "^1.0.5",
"debug": "^4.4.0",
"http-errors": "^2.0.0",
"iconv-lite": "^0.6.3",
"on-finished": "^2.4.1",
"qs": "^6.14.0",
"raw-body": "^3.0.0",
"type-is": "^2.0.0"
},
"devDependencies": {
"eslint": "8.34.0",
@@ -30,27 +27,23 @@
"eslint-plugin-node": "11.1.0",
"eslint-plugin-promise": "6.1.1",
"eslint-plugin-standard": "4.1.0",
"methods": "1.1.2",
"mocha": "10.2.0",
"nyc": "15.1.0",
"safe-buffer": "5.2.1",
"supertest": "6.3.3"
"mocha": "^11.1.0",
"nyc": "^17.1.0",
"supertest": "^7.0.0"
},
"files": [
"lib/",
"LICENSE",
"HISTORY.md",
"SECURITY.md",
"index.js"
],
"engines": {
"node": ">= 0.8",
"npm": "1.2.8000 || >= 1.4.16"
"node": ">=18"
},
"scripts": {
"lint": "eslint .",
"test": "mocha --require test/support/env --reporter spec --check-leaks --bail test/",
"test-ci": "nyc --reporter=lcov --reporter=text npm test",
"test": "mocha --reporter spec --check-leaks test/",
"test-ci": "nyc --reporter=lcovonly --reporter=text npm test",
"test-cov": "nyc --reporter=html --reporter=text npm test"
}
}