| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205 | /*! * body-parser * Copyright(c) 2014-2015 Douglas Christopher Wilson * MIT Licensed */'use strict'/** * Module dependencies. * @private */var createError = require('http-errors')var destroy = require('destroy')var getBody = require('raw-body')var iconv = require('iconv-lite')var onFinished = require('on-finished')var unpipe = require('unpipe')var zlib = require('zlib')/** * Module exports. */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 * @private */function read (req, res, next, parse, debug, options) {  var length  var opts = options  var stream  // flag as parsed  req._body = true  // read options  var encoding = opts.encoding !== null    ? opts.encoding    : null  var verify = opts.verify  try {    // get the content stream    stream = contentstream(req, debug, opts.inflate)    length = stream.length    stream.length = undefined  } catch (err) {    return next(err)  }  // set raw-body options  opts.length = length  opts.encoding = verify    ? null    : encoding  // assert charset is supported  if (opts.encoding === null && encoding !== null && !iconv.encodingExists(encoding)) {    return next(createError(415, 'unsupported charset "' + encoding.toUpperCase() + '"', {      charset: encoding.toLowerCase(),      type: 'charset.unsupported'    }))  }  // read body  debug('read body')  getBody(stream, opts, function (error, body) {    if (error) {      var _error      if (error.type === 'encoding.unsupported') {        // echo back charset        _error = createError(415, 'unsupported charset "' + encoding.toUpperCase() + '"', {          charset: encoding.toLowerCase(),          type: 'charset.unsupported'        })      } else {        // set status code on error        _error = createError(400, error)      }      // unpipe from stream and destroy      if (stream !== req) {        unpipe(req)        destroy(stream, true)      }      // read off entire request      dump(req, function onfinished () {        next(createError(400, _error))      })      return    }    // verify    if (verify) {      try {        debug('verify body')        verify(req, res, body, encoding)      } catch (err) {        next(createError(403, err, {          body: body,          type: err.type || 'entity.verify.failed'        }))        return      }    }    // parse    var str = body    try {      debug('parse body')      str = typeof body !== 'string' && encoding !== null        ? iconv.decode(body, encoding)        : body      req.body = parse(str)    } catch (err) {      next(createError(400, err, {        body: str,        type: err.type || 'entity.parse.failed'      }))      return    }    next()  })}/** * Get the content stream of the request. * * @param {object} req * @param {function} debug * @param {boolean} [inflate=true] * @return {object} * @api private */function contentstream (req, debug, inflate) {  var encoding = (req.headers['content-encoding'] || 'identity').toLowerCase()  var length = req.headers['content-length']  var stream  debug('content-encoding "%s"', encoding)  if (inflate === false && encoding !== 'identity') {    throw createError(415, 'content encoding unsupported', {      encoding: encoding,      type: 'encoding.unsupported'    })  }  switch (encoding) {    case 'deflate':      stream = zlib.createInflate()      debug('inflate body')      req.pipe(stream)      break    case 'gzip':      stream = zlib.createGunzip()      debug('gunzip body')      req.pipe(stream)      break    case 'identity':      stream = req      stream.length = length      break    default:      throw createError(415, 'unsupported content encoding "' + encoding + '"', {        encoding: encoding,        type: 'encoding.unsupported'      })  }  return stream}/** * Dump the contents of a request. * * @param {object} req * @param {function} callback * @api private */function dump (req, callback) {  if (onFinished.isFinished(req)) {    callback(null)  } else {    onFinished(req, callback)    req.resume()  }}
 |