This repository has been archived on 2018-10-12. You can view files and clone it, but cannot push or open issues or pull requests.
node-task/node_modules/body-parser/lib/types/urlencoded.js

207 lines
3.9 KiB
JavaScript

/*!
* body-parser
* Copyright(c) 2014 Jonathan Ong
* Copyright(c) 2014 Douglas Christopher Wilson
* MIT Licensed
*/
/**
* Module dependencies.
*/
var bytes = require('bytes')
var deprecate = require('depd')('body-parser')
var read = require('../read')
var typer = require('media-typer')
var typeis = require('type-is')
/**
* Module exports.
*/
module.exports = urlencoded
/**
* Cache of parser modules.
*/
var parsers = Object.create(null)
/**
* Create a middleware to parse urlencoded bodies.
*
* @param {object} [options]
* @return {function}
* @api public
*/
function urlencoded(options){
options = options || {};
// notice because option default will flip in next major
if (options.extended === undefined) {
deprecate('undefined extended: provide extended option')
}
var extended = options.extended !== false
var inflate = options.inflate !== false
var limit = typeof options.limit !== 'number'
? bytes(options.limit || '100kb')
: options.limit
var type = options.type || 'urlencoded'
var verify = options.verify || false
if (verify !== false && typeof verify !== 'function') {
throw new TypeError('option verify must be function')
}
var queryparse = extended
? extendedparser(options)
: simpleparser(options)
function parse(body) {
return body.length
? queryparse(body)
: {}
}
return function urlencodedParser(req, res, next) {
if (req._body) return next();
req.body = req.body || {}
if (!typeis(req, type)) return next();
var charset = typer.parse(req).parameters.charset || 'utf-8'
if (charset.toLowerCase() !== 'utf-8') {
var err = new Error('unsupported charset')
err.status = 415
next(err)
return
}
// read
read(req, res, next, parse, {
encoding: charset,
inflate: inflate,
limit: limit,
verify: verify
})
}
}
/**
* Get the extended query parser.
*
* @param {object} options
*/
function extendedparser(options) {
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')
}
if (isFinite(parameterLimit)) {
parameterLimit = parameterLimit | 0
}
var opts = {
arrayLimit: 100,
parameterLimit: parameterLimit
}
return function queryparse(body) {
if (overlimit(body, parameterLimit)) {
var err = new Error('too many parameters')
err.status = 413
throw err
}
return parse(body, opts)
}
}
/**
* Determine if the parameter count is over the limit.
*
* @param {string} body
* @param {number} limit
* @api private
*/
function overlimit(body, limit) {
if (limit === Infinity) {
return false
}
var count = 0
var index = 0
while ((index = body.indexOf('&', index)) !== -1) {
count++
index++
if (count === limit) {
return true
}
}
return false
}
/**
* Get parser for module name dynamically.
*
* @param {string} name
* @return {function}
* @api private
*/
function parser(name) {
var mod = parsers[name]
if (mod) {
return mod.parse
}
// load module
mod = parsers[name] = require(name)
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) {
if (overlimit(body, parameterLimit)) {
var err = new Error('too many parameters')
err.status = 413
throw err
}
return parse(body, undefined, undefined, {maxKeys: parameterLimit})
}
}