Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Avatar for KuCalc : devops.
Download
50654 views
1
/*!
2
* body-parser
3
* Copyright(c) 2014 Jonathan Ong
4
* Copyright(c) 2014-2015 Douglas Christopher Wilson
5
* MIT Licensed
6
*/
7
8
'use strict'
9
10
/**
11
* Module dependencies.
12
* @private
13
*/
14
15
var bytes = require('bytes')
16
var contentType = require('content-type')
17
var createError = require('http-errors')
18
var debug = require('debug')('body-parser:urlencoded')
19
var deprecate = require('depd')('body-parser')
20
var read = require('../read')
21
var typeis = require('type-is')
22
23
/**
24
* Module exports.
25
*/
26
27
module.exports = urlencoded
28
29
/**
30
* Cache of parser modules.
31
*/
32
33
var parsers = Object.create(null)
34
35
/**
36
* Create a middleware to parse urlencoded bodies.
37
*
38
* @param {object} [options]
39
* @return {function}
40
* @public
41
*/
42
43
function urlencoded (options) {
44
var opts = options || {}
45
46
// notice because option default will flip in next major
47
if (opts.extended === undefined) {
48
deprecate('undefined extended: provide extended option')
49
}
50
51
var extended = opts.extended !== false
52
var inflate = opts.inflate !== false
53
var limit = typeof opts.limit !== 'number'
54
? bytes.parse(opts.limit || '100kb')
55
: opts.limit
56
var type = opts.type || 'application/x-www-form-urlencoded'
57
var verify = opts.verify || false
58
59
if (verify !== false && typeof verify !== 'function') {
60
throw new TypeError('option verify must be function')
61
}
62
63
// create the appropriate query parser
64
var queryparse = extended
65
? extendedparser(opts)
66
: simpleparser(opts)
67
68
// create the appropriate type checking function
69
var shouldParse = typeof type !== 'function'
70
? typeChecker(type)
71
: type
72
73
function parse (body) {
74
return body.length
75
? queryparse(body)
76
: {}
77
}
78
79
return function urlencodedParser (req, res, next) {
80
if (req._body) {
81
debug('body already parsed')
82
next()
83
return
84
}
85
86
req.body = req.body || {}
87
88
// skip requests without bodies
89
if (!typeis.hasBody(req)) {
90
debug('skip empty body')
91
next()
92
return
93
}
94
95
debug('content-type %j', req.headers['content-type'])
96
97
// determine if request should be parsed
98
if (!shouldParse(req)) {
99
debug('skip parsing')
100
next()
101
return
102
}
103
104
// assert charset
105
var charset = getCharset(req) || 'utf-8'
106
if (charset !== 'utf-8') {
107
debug('invalid charset')
108
next(createError(415, 'unsupported charset "' + charset.toUpperCase() + '"', {
109
charset: charset
110
}))
111
return
112
}
113
114
// read
115
read(req, res, next, parse, debug, {
116
debug: debug,
117
encoding: charset,
118
inflate: inflate,
119
limit: limit,
120
verify: verify
121
})
122
}
123
}
124
125
/**
126
* Get the extended query parser.
127
*
128
* @param {object} options
129
*/
130
131
function extendedparser (options) {
132
var parameterLimit = options.parameterLimit !== undefined
133
? options.parameterLimit
134
: 1000
135
var parse = parser('qs')
136
137
if (isNaN(parameterLimit) || parameterLimit < 1) {
138
throw new TypeError('option parameterLimit must be a positive number')
139
}
140
141
if (isFinite(parameterLimit)) {
142
parameterLimit = parameterLimit | 0
143
}
144
145
return function queryparse (body) {
146
var paramCount = parameterCount(body, parameterLimit)
147
148
if (paramCount === undefined) {
149
debug('too many parameters')
150
throw createError(413, 'too many parameters')
151
}
152
153
var arrayLimit = Math.max(100, paramCount)
154
155
debug('parse extended urlencoding')
156
return parse(body, {
157
allowPrototypes: true,
158
arrayLimit: arrayLimit,
159
depth: Infinity,
160
parameterLimit: parameterLimit
161
})
162
}
163
}
164
165
/**
166
* Get the charset of a request.
167
*
168
* @param {object} req
169
* @api private
170
*/
171
172
function getCharset (req) {
173
try {
174
return contentType.parse(req).parameters.charset.toLowerCase()
175
} catch (e) {
176
return undefined
177
}
178
}
179
180
/**
181
* Count the number of parameters, stopping once limit reached
182
*
183
* @param {string} body
184
* @param {number} limit
185
* @api private
186
*/
187
188
function parameterCount (body, limit) {
189
var count = 0
190
var index = 0
191
192
while ((index = body.indexOf('&', index)) !== -1) {
193
count++
194
index++
195
196
if (count === limit) {
197
return undefined
198
}
199
}
200
201
return count
202
}
203
204
/**
205
* Get parser for module name dynamically.
206
*
207
* @param {string} name
208
* @return {function}
209
* @api private
210
*/
211
212
function parser (name) {
213
var mod = parsers[name]
214
215
if (mod !== undefined) {
216
return mod.parse
217
}
218
219
// this uses a switch for static require analysis
220
switch (name) {
221
case 'qs':
222
mod = require('qs')
223
break
224
case 'querystring':
225
mod = require('querystring')
226
break
227
}
228
229
// store to prevent invoking require()
230
parsers[name] = mod
231
232
return mod.parse
233
}
234
235
/**
236
* Get the simple query parser.
237
*
238
* @param {object} options
239
*/
240
241
function simpleparser (options) {
242
var parameterLimit = options.parameterLimit !== undefined
243
? options.parameterLimit
244
: 1000
245
var parse = parser('querystring')
246
247
if (isNaN(parameterLimit) || parameterLimit < 1) {
248
throw new TypeError('option parameterLimit must be a positive number')
249
}
250
251
if (isFinite(parameterLimit)) {
252
parameterLimit = parameterLimit | 0
253
}
254
255
return function queryparse (body) {
256
var paramCount = parameterCount(body, parameterLimit)
257
258
if (paramCount === undefined) {
259
debug('too many parameters')
260
throw createError(413, 'too many parameters')
261
}
262
263
debug('parse urlencoding')
264
return parse(body, undefined, undefined, {maxKeys: parameterLimit})
265
}
266
}
267
268
/**
269
* Get the simple type checker.
270
*
271
* @param {string} type
272
* @return {function}
273
*/
274
275
function typeChecker (type) {
276
return function checkType (req) {
277
return Boolean(typeis(req, type))
278
}
279
}
280
281