-
-
Notifications
You must be signed in to change notification settings - Fork 758
Expand file tree
/
Copy pathurlencoded.js
More file actions
149 lines (124 loc) · 3.54 KB
/
urlencoded.js
File metadata and controls
149 lines (124 loc) · 3.54 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
/*!
* body-parser
* Copyright(c) 2014 Jonathan Ong
* Copyright(c) 2014-2015 Douglas Christopher Wilson
* MIT Licensed
*/
'use strict'
/**
* Module dependencies.
* @private
*/
var createError = require('http-errors')
var debug = require('debug')('body-parser:urlencoded')
var read = require('../read')
var qs = require('qs')
var { normalizeOptions } = require('../utils')
/**
* Module exports.
*/
module.exports = urlencoded
/**
* Create a middleware to parse urlencoded bodies.
*
* @param {object} [options]
* @return {function}
* @public
*/
function urlencoded (options) {
const normalizedOptions = normalizeOptions(options, 'application/x-www-form-urlencoded')
if (normalizedOptions.defaultCharset !== 'utf-8' && normalizedOptions.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 = createQueryParser(options)
function parse (body, encoding) {
return body.length
? queryparse(body, encoding)
: {}
}
const readOptions = {
...normalizedOptions,
// assert charset
isValidCharset: (charset) => charset === 'utf-8' || charset === 'iso-8859-1'
}
return function urlencodedParser (req, res, next) {
read(req, res, next, parse, debug, readOptions)
}
}
/**
* Get the extended query parser.
*
* @param {object} options
*/
function createQueryParser (options) {
var extended = Boolean(options?.extended)
var parameterLimit = options?.parameterLimit !== undefined
? options?.parameterLimit
: 1000
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')
}
if (isNaN(depth) || depth < 0) {
throw new TypeError('option depth must be a zero or a positive number')
}
if (isFinite(parameterLimit)) {
parameterLimit = parameterLimit | 0
}
return function queryparse (body, encoding) {
var paramCount = parameterCount(body, parameterLimit)
if (paramCount === undefined) {
debug('too many parameters')
throw createError(413, 'too many parameters', {
type: 'parameters.too.many'
})
}
var arrayLimit = extended ? Math.max(100, paramCount) : 0
debug('parse ' + (extended ? 'extended ' : '') + 'urlencoding')
try {
return qs.parse(body, {
allowPrototypes: true,
arrayLimit: arrayLimit,
depth: depth,
charsetSentinel: charsetSentinel,
interpretNumericEntities: interpretNumericEntities,
charset: encoding,
parameterLimit: parameterLimit,
strictDepth: true
})
} catch (err) {
if (err instanceof RangeError) {
throw createError(400, 'The input exceeded the depth', {
type: 'querystring.parse.rangeError'
})
} else {
throw err
}
}
}
}
/**
* Count the number of parameters, stopping once limit reached
*
* @param {string} body
* @param {number} limit
* @return {number|undefined} Returns undefined if limit exceeded
* @api private
*/
function parameterCount (body, limit) {
if (body.length === 0) {
return 0
}
let ampersandCount = 0
let index = -1
while ((index = body.indexOf('&', index + 1)) !== -1) {
ampersandCount++
if (ampersandCount >= limit) {
return undefined
}
}
return ampersandCount + 1
}