text: /*!
   * body-parser
   * Copyright(c) 2014-2015 Douglas Christopher Wilson
   * MIT Licensed
   */
  
  'use strict'
  
  /**
   * Module dependencies.
   * @private
   */
  
  var createError = require('http-errors')
  var getBody = require('raw-body')
  var iconv = require('iconv-lite')
  var onFinished = require('on-finished')
  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]
   * @api 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 || 'utf-8'
      : 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()
      }))
    }
  
    // read body
    debug('read body')
    getBody(stream, opts, function (err, body) {
      if (err) {
        // default to 400
        setErrorStatus(err, 400)
  
        // echo back charset
        if (err.type === 'encoding.unsupported') {
          err = createError(415, 'unsupported charset "' + encoding.toUpperCase() + '"', {
            charset: encoding.toLowerCase()
          })
        }
  
        // read off entire request
        stream.resume()
        onFinished(req, function onfinished () {
          next(err)
        })
        return
      }
  
      // verify
      if (verify) {
        try {
          debug('verify body')
          verify(req, res, body, encoding)
        } catch (err) {
          // default to 403
          setErrorStatus(err, 403)
          next(err)
          return
        }
      }
  
      // parse
      var str
      try {
        debug('parse body')
        str = typeof body !== 'string' && encoding !== null
          ? iconv.decode(body, encoding)
          : body
        req.body = parse(str)
      } catch (err) {
        err.body = str === undefined
          ? body
          : str
  
        // default to 400
        setErrorStatus(err, 400)
  
        next(err)
        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')
    }
  
    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
        })
    }
  
    return stream
  }
  
  /**
   * Set a status on an error object, if ones does not exist
   * @private
   */
  
  function setErrorStatus (error, status) {
    if (!error.status && !error.statusCode) {
      error.status = status
      error.statusCode = status
    }
  }
  