avancement planning

This commit is contained in:
2026-05-26 11:58:39 +02:00
parent 619a2b240a
commit 150b97cd2e
4892 changed files with 99214 additions and 429382 deletions
+60 -23
View File
@@ -16,6 +16,8 @@ var getBody = require('raw-body')
var iconv = require('iconv-lite')
var onFinished = require('on-finished')
var zlib = require('node:zlib')
var hasBody = require('type-is').hasBody
var { getCharset } = require('./utils')
/**
* Module exports.
@@ -26,24 +28,61 @@ module.exports = read
/**
* Read a request into a buffer and parse.
*
* @param {object} req
* @param {object} res
* @param {function} next
* @param {function} parse
* @param {function} debug
* @param {object} options
* @param {Object} req
* @param {Object} res
* @param {Function} next
* @param {Function} parse
* @param {Function} debug
* @param {Object} options
* @private
*/
function read (req, res, next, parse, debug, options) {
if (onFinished.isFinished(req)) {
debug('body already parsed')
next()
return
}
if (!('body' in req)) {
req.body = undefined
}
// skip requests without bodies
if (!hasBody(req)) {
debug('skip empty body')
next()
return
}
debug('content-type %j', req.headers['content-type'])
// determine if request should be parsed
if (!options.shouldParse(req)) {
debug('skip parsing')
next()
return
}
var encoding = null
if (options?.skipCharset !== true) {
encoding = getCharset(req) || options.defaultCharset
// validate charset
if (!!options?.isValidCharset && !options.isValidCharset(encoding)) {
debug('invalid charset')
next(createError(415, 'unsupported charset "' + encoding.toUpperCase() + '"', {
charset: encoding,
type: 'charset.unsupported'
}))
return
}
}
var length
var opts = options
var stream
// read options
var encoding = opts.encoding !== null
? opts.encoding
: null
var verify = opts.verify
try {
@@ -136,13 +175,12 @@ function read (req, res, next, parse, debug, options) {
/**
* Get the content stream of the request.
*
* @param {object} req
* @param {function} debug
* @param {boolean} [inflate=true]
* @return {object}
* @api private
* @param {Object} req
* @param {Function} debug
* @param {boolean} inflate
* @returns {Object}
* @private
*/
function contentstream (req, debug, inflate) {
var encoding = (req.headers['content-encoding'] || 'identity').toLowerCase()
var length = req.headers['content-length']
@@ -169,9 +207,9 @@ function contentstream (req, debug, inflate) {
/**
* Create a decompression stream for the given encoding.
* @param {string} encoding
* @param {function} debug
* @return {object}
* @api private
* @param {Function} debug
* @returns {Object}
* @private
*/
function createDecompressionStream (encoding, debug) {
switch (encoding) {
@@ -195,11 +233,10 @@ function createDecompressionStream (encoding, debug) {
/**
* Dump the contents of a request.
*
* @param {object} req
* @param {function} callback
* @api private
* @param {Object} req
* @param {Function} callback
* @private
*/
function dump (req, callback) {
if (onFinished.isFinished(req)) {
callback(null)
+16 -64
View File
@@ -12,12 +12,9 @@
* @private
*/
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')
var { normalizeOptions } = require('../utils')
/**
* Module exports.
@@ -36,7 +33,6 @@ module.exports = json
* %x0A / ; Line feed or New line
* %x0D ) ; Carriage return
*/
var FIRST_CHAR_REGEXP = /^[\x20\x09\x0a\x0d]*([^\x20\x09\x0a\x0d])/ // eslint-disable-line no-control-regex
var JSON_SYNTAX_CHAR = '#'
@@ -45,13 +41,12 @@ var JSON_SYNTAX_REGEXP = /#+/g
/**
* Create a middleware to parse JSON bodies.
*
* @param {object} [options]
* @return {function}
* @param {Object} [options]
* @returns {Function}
* @public
*/
function json (options) {
var { inflate, limit, verify, shouldParse } = normalizeOptions(options, 'application/json')
const normalizedOptions = normalizeOptions(options, 'application/json')
var reviver = options?.reviver
var strict = options?.strict !== false
@@ -83,51 +78,14 @@ function json (options) {
}
}
return function jsonParser (req, res, next) {
if (isFinished(req)) {
debug('body already parsed')
next()
return
}
if (!('body' in req)) {
req.body = undefined
}
// skip requests without bodies
if (!typeis.hasBody(req)) {
debug('skip empty body')
next()
return
}
debug('content-type %j', req.headers['content-type'])
// determine if request should be parsed
if (!shouldParse(req)) {
debug('skip parsing')
next()
return
}
const readOptions = {
...normalizedOptions,
// assert charset per RFC 7159 sec 8.1
var charset = getCharset(req) || 'utf-8'
if (charset.slice(0, 4) !== 'utf-') {
debug('invalid charset')
next(createError(415, 'unsupported charset "' + charset.toUpperCase() + '"', {
charset: charset,
type: 'charset.unsupported'
}))
return
}
isValidCharset: (charset) => charset.slice(0, 4) === 'utf-'
}
// read
read(req, res, next, parse, debug, {
encoding: charset,
inflate,
limit,
verify
})
return function jsonParser (req, res, next) {
read(req, res, next, parse, debug, readOptions)
}
}
@@ -136,20 +94,15 @@ function json (options) {
*
* @param {string} str
* @param {string} char
* @return {Error}
* @returns {Error}
* @private
*/
function createStrictSyntaxError (str, char) {
var index = str.indexOf(char)
var partial = ''
if (index !== -1) {
partial = str.substring(0, index) + JSON_SYNTAX_CHAR
for (var i = index + 1; i < str.length; i++) {
partial += JSON_SYNTAX_CHAR
}
partial = str.substring(0, index) + JSON_SYNTAX_CHAR.repeat(str.length - index)
}
try {
@@ -168,10 +121,9 @@ function createStrictSyntaxError (str, char) {
* Get the first non-whitespace character in a string.
*
* @param {string} str
* @return {function}
* @returns {string|undefined}
* @private
*/
function firstchar (str) {
var match = FIRST_CHAR_REGEXP.exec(str)
@@ -184,10 +136,10 @@ function firstchar (str) {
* Normalize a SyntaxError for JSON.parse.
*
* @param {SyntaxError} error
* @param {object} obj
* @return {SyntaxError}
* @param {Object} obj
* @returns {SyntaxError}
* @private
*/
function normalizeJsonSyntaxError (error, obj) {
var keys = Object.getOwnPropertyNames(error)
+10 -43
View File
@@ -11,10 +11,8 @@
*/
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')
var { normalizeOptions, passthrough } = require('../utils')
/**
* Module exports.
@@ -25,51 +23,20 @@ module.exports = raw
/**
* Create a middleware to parse raw bodies.
*
* @param {object} [options]
* @return {function}
* @api public
* @param {Object} [options]
* @returns {Function}
* @public
*/
function raw (options) {
var { inflate, limit, verify, shouldParse } = normalizeOptions(options, 'application/octet-stream')
const normalizedOptions = normalizeOptions(options, 'application/octet-stream')
function parse (buf) {
return buf
const readOptions = {
...normalizedOptions,
// Skip charset validation and parse the body as is
skipCharset: true
}
return function rawParser (req, res, next) {
if (isFinished(req)) {
debug('body already parsed')
next()
return
}
if (!('body' in req)) {
req.body = undefined
}
// skip requests without bodies
if (!typeis.hasBody(req)) {
debug('skip empty body')
next()
return
}
debug('content-type %j', req.headers['content-type'])
// determine if request should be parsed
if (!shouldParse(req)) {
debug('skip parsing')
next()
return
}
// read
read(req, res, next, parse, debug, {
encoding: null,
inflate,
limit,
verify
})
read(req, res, next, passthrough, debug, readOptions)
}
}
+6 -50
View File
@@ -11,10 +11,8 @@
*/
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')
var { normalizeOptions, passthrough } = require('../utils')
/**
* Module exports.
@@ -25,56 +23,14 @@ module.exports = text
/**
* Create a middleware to parse text bodies.
*
* @param {object} [options]
* @return {function}
* @api public
* @param {Object} [options]
* @returns {Function}
* @public
*/
function text (options) {
var { inflate, limit, verify, shouldParse } = normalizeOptions(options, 'text/plain')
var defaultCharset = options?.defaultCharset || 'utf-8'
function parse (buf) {
return buf
}
const normalizedOptions = normalizeOptions(options, 'text/plain')
return function textParser (req, res, next) {
if (isFinished(req)) {
debug('body already parsed')
next()
return
}
if (!('body' in req)) {
req.body = undefined
}
// skip requests without bodies
if (!typeis.hasBody(req)) {
debug('skip empty body')
next()
return
}
debug('content-type %j', req.headers['content-type'])
// determine if request should be parsed
if (!shouldParse(req)) {
debug('skip parsing')
next()
return
}
// get charset
var charset = getCharset(req) || defaultCharset
// read
read(req, res, next, parse, debug, {
encoding: charset,
inflate,
limit,
verify
})
read(req, res, next, passthrough, debug, normalizedOptions)
}
}
+25 -60
View File
@@ -14,11 +14,9 @@
var createError = require('http-errors')
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')
var { getCharset, normalizeOptions } = require('../utils')
var { normalizeOptions } = require('../utils')
/**
* Module exports.
@@ -29,16 +27,14 @@ module.exports = urlencoded
/**
* Create a middleware to parse urlencoded bodies.
*
* @param {object} [options]
* @return {function}
* @param {Object} [options]
* @returns {Function}
* @public
*/
function urlencoded (options) {
var { inflate, limit, verify, shouldParse } = normalizeOptions(options, 'application/x-www-form-urlencoded')
const normalizedOptions = normalizeOptions(options, 'application/x-www-form-urlencoded')
var defaultCharset = options?.defaultCharset || 'utf-8'
if (defaultCharset !== 'utf-8' && defaultCharset !== 'iso-8859-1') {
if (normalizedOptions.defaultCharset !== 'utf-8' && normalizedOptions.defaultCharset !== 'iso-8859-1') {
throw new TypeError('option defaultCharset must be either utf-8 or iso-8859-1')
}
@@ -51,60 +47,24 @@ function urlencoded (options) {
: {}
}
return function urlencodedParser (req, res, next) {
if (isFinished(req)) {
debug('body already parsed')
next()
return
}
if (!('body' in req)) {
req.body = undefined
}
// skip requests without bodies
if (!typeis.hasBody(req)) {
debug('skip empty body')
next()
return
}
debug('content-type %j', req.headers['content-type'])
// determine if request should be parsed
if (!shouldParse(req)) {
debug('skip parsing')
next()
return
}
const readOptions = {
...normalizedOptions,
// assert charset
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,
type: 'charset.unsupported'
}))
return
}
isValidCharset: (charset) => charset === 'utf-8' || charset === 'iso-8859-1'
}
// read
read(req, res, next, parse, debug, {
encoding: charset,
inflate,
limit,
verify
})
return function urlencodedParser (req, res, next) {
read(req, res, next, parse, debug, readOptions)
}
}
/**
* Get the extended query parser.
*
* @param {object} options
* @param {Object} options
* @returns {Function}
* @private
*/
function createQueryParser (options) {
var extended = Boolean(options?.extended)
var parameterLimit = options?.parameterLimit !== undefined
@@ -136,7 +96,7 @@ function createQueryParser (options) {
})
}
var arrayLimit = extended ? Math.max(100, paramCount) : 0
var arrayLimit = extended ? Math.max(100, paramCount) : paramCount
debug('parse ' + (extended ? 'extended ' : '') + 'urlencoding')
try {
@@ -167,11 +127,16 @@ function createQueryParser (options) {
*
* @param {string} body
* @param {number} limit
* @api private
* @returns {number|undefined} Returns undefined if limit exceeded
* @private
*/
function parameterCount (body, limit) {
var len = body.split('&').length
return len > limit ? undefined : len - 1
let count = 0
let index = -1
do {
count++
if (count > limit) return undefined // Early exit if limit exceeded
index = body.indexOf('&', index + 1)
} while (index !== -1)
return count
}
+25 -10
View File
@@ -11,19 +11,19 @@ var typeis = require('type-is')
/**
* Module exports.
*/
module.exports = {
getCharset,
normalizeOptions
normalizeOptions,
passthrough
}
/**
* Get the charset of a request.
*
* @param {object} req
* @api private
* @param {Object} req
* @returns {string | undefined}
* @private
*/
function getCharset (req) {
try {
return (contentType.parse(req).parameters.charset || '').toLowerCase()
@@ -36,9 +36,9 @@ function getCharset (req) {
* Get the simple type checker.
*
* @param {string | string[]} type
* @return {function}
* @returns {Function}
* @private
*/
function typeChecker (type) {
return function checkType (req) {
return Boolean(typeis(req, type))
@@ -48,9 +48,10 @@ function typeChecker (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}
* @param {Object} options options to normalize
* @param {string | string[] | Function} defaultType default content type(s) or a function to determine it
* @returns {Object}
* @private
*/
function normalizeOptions (options, defaultType) {
if (!defaultType) {
@@ -64,6 +65,7 @@ function normalizeOptions (options, defaultType) {
: options?.limit
var type = options?.type || defaultType
var verify = options?.verify || false
var defaultCharset = options?.defaultCharset || 'utf-8'
if (verify !== false && typeof verify !== 'function') {
throw new TypeError('option verify must be function')
@@ -78,6 +80,19 @@ function normalizeOptions (options, defaultType) {
inflate,
limit,
verify,
defaultCharset,
shouldParse
}
}
/**
* Passthrough function that returns input unchanged.
* Used by parsers that don't need to transform the data.
*
* @param {*} value
* @returns {*}
* @private
*/
function passthrough (value) {
return value
}