UNPKG

body-parser

Version:
191 lines (152 loc) 3.87 kB
var bytes = require('bytes'); var getBody = require('raw-body'); var typeis = require('type-is'); var http = require('http'); var qs = require('qs'); var firstcharRegExp = /^\s*(.)/ exports = module.exports = bodyParser; exports.json = json; exports.urlencoded = urlencoded; function bodyParser(options){ var opts = {} options = options || {} // exclude type option for (var prop in options) { if ('type' !== prop) { opts[prop] = options[prop] } } var _urlencoded = urlencoded(opts) var _json = json(opts) return function bodyParser(req, res, next) { _json(req, res, function(err){ if (err) return next(err); _urlencoded(req, res, next); }); } } function json(options){ options = options || {}; var limit = typeof options.limit !== 'number' ? bytes(options.limit || '100kb') : options.limit; var reviver = options.reviver var strict = options.strict !== false; var type = options.type || 'json'; var verify = options.verify || false if (verify !== false && typeof verify !== 'function') { throw new TypeError('option verify must be function') } function parse(str) { if (0 === str.length) { throw new Error('invalid json, empty body') } if (strict) { var first = firstchar(str) if (first !== '{' && first !== '[') { throw new Error('invalid json') } } return JSON.parse(str, reviver) } return function jsonParser(req, res, next) { if (req._body) return next(); req.body = req.body || {} if (!typeis(req, type)) return next(); // read read(req, res, next, parse, { limit: limit, verify: verify }) } } function urlencoded(options){ options = options || {}; 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') } function parse(str) { return str.length ? qs.parse(str) : {} } return function urlencodedParser(req, res, next) { if (req._body) return next(); req.body = req.body || {} if (!typeis(req, type)) return next(); // read read(req, res, next, parse, { limit: limit, verify: verify }) } } function firstchar(str) { if (!str) return '' var match = firstcharRegExp.exec(str) return match ? match[1] : '' } function read(req, res, next, parse, options) { var length = req.headers['content-length'] var waitend = true // flag as parsed req._body = true options = options || {} options.length = length var encoding = options.encoding || 'utf-8' var verify = options.verify options.encoding = verify ? null : encoding req.on('aborted', cleanup) req.on('end', cleanup) req.on('error', cleanup) // read body getBody(req, options, function (err, body) { if (err && waitend && req.readable) { // read off entire request req.resume() req.once('end', function onEnd() { next(err) }) return } if (err) { next(err) return } var str // verify if (verify) { try { verify(req, res, body, encoding) } catch (err) { if (!err.status) err.status = 403 return next(err) } } // parse try { str = typeof body !== 'string' ? body.toString(encoding) : body req.body = parse(str) } catch (err){ err.body = str err.status = 400 return next(err) } next() }) function cleanup() { waitend = false req.removeListener('aborted', cleanup) req.removeListener('end', cleanup) req.removeListener('error', cleanup) } }