[Pkg-javascript-commits] [node-body-parser] 01/04: Imported Upstream version 1.4.3

Andrew Kelley andrewrk-guest at moszumanska.debian.org
Mon Jun 30 17:13:06 UTC 2014


This is an automated email from the git hooks/post-receive script.

andrewrk-guest pushed a commit to branch master
in repository node-body-parser.

commit 467948802255d15fd66466b43ebbf1a52c67dce0
Author: Andrew Kelley <superjoe30 at gmail.com>
Date:   Mon Jun 30 16:58:04 2014 +0000

    Imported Upstream version 1.4.3
---
 .gitignore              |   3 +
 .npmignore              |   3 +
 .travis.yml             |  11 ++
 HISTORY.md              |  90 ++++++++++
 README.md               | 144 +++++++++++++++
 index.js                |  83 +++++++++
 lib/read.js             | 155 ++++++++++++++++
 lib/types/json.js       | 105 +++++++++++
 lib/types/raw.js        |  60 +++++++
 lib/types/text.js       |  65 +++++++
 lib/types/urlencoded.js | 109 ++++++++++++
 package.json            |  34 ++++
 test/body-parser.js     | 113 ++++++++++++
 test/json.js            | 460 ++++++++++++++++++++++++++++++++++++++++++++++++
 test/raw.js             | 281 +++++++++++++++++++++++++++++
 test/support/env.js     |   2 +
 test/text.js            | 324 ++++++++++++++++++++++++++++++++++
 test/urlencoded.js      | 367 ++++++++++++++++++++++++++++++++++++++
 18 files changed, 2409 insertions(+)

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..3cd27af
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
+coverage/
+node_modules/
+npm-debug.log
diff --git a/.npmignore b/.npmignore
new file mode 100644
index 0000000..cd39b77
--- /dev/null
+++ b/.npmignore
@@ -0,0 +1,3 @@
+coverage/
+test/
+.travis.yml
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..1ff243c
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,11 @@
+language: node_js
+node_js:
+  - "0.8"
+  - "0.10"
+  - "0.11"
+matrix:
+  allow_failures:
+    - node_js: "0.11"
+  fast_finish: true
+script: "npm run-script test-travis"
+after_script: "npm install coveralls at 2.10.0 && cat ./coverage/lcov.info | coveralls"
diff --git a/HISTORY.md b/HISTORY.md
new file mode 100644
index 0000000..b818f66
--- /dev/null
+++ b/HISTORY.md
@@ -0,0 +1,90 @@
+1.4.3 / 2014-06-19
+==================
+
+  * deps: type-is at 1.3.1
+    - fix global variable leak
+
+1.4.2 / 2014-06-19
+==================
+
+  * deps: type-is at 1.3.0
+    - improve type parsing
+
+1.4.1 / 2014-06-19
+==================
+
+  * fix urlencoded extended deprecation message
+
+1.4.0 / 2014-06-19
+==================
+
+  * add `text` parser
+  * add `raw` parser
+  * check accepted charset in content-type (accepts utf-8)
+  * check accepted encoding in content-encoding (accepts identity)
+  * deprecate `bodyParser()` middleware; use `.json()` and `.urlencoded()` as needed
+  * deprecate `urlencoded()` without provided `extended` option
+  * lazy-load urlencoded parsers
+  * parsers split into files for reduced mem usage
+  * support gzip and deflate bodies
+    - set `inflate: false` to turn off
+  * deps: raw-body at 1.2.2
+    - Support all encodings from `iconv-lite`
+
+1.3.1 / 2014-06-11
+==================
+
+  * deps: type-is at 1.2.1
+    - Switch dependency from mime to mime-types at 1.0.0
+
+1.3.0 / 2014-05-31
+==================
+
+  * add `extended` option to urlencoded parser
+
+1.2.2 / 2014-05-27
+==================
+
+  * deps: raw-body at 1.1.6
+    - assert stream encoding on node.js 0.8
+    - assert stream encoding on node.js < 0.10.6
+    - deps: bytes at 1
+
+1.2.1 / 2014-05-26
+==================
+
+  * invoke `next(err)` after request fully read
+    - prevents hung responses and socket hang ups
+
+1.2.0 / 2014-05-11
+==================
+
+  * add `verify` option
+  * deps: type-is at 1.2.0
+    - support suffix matching
+
+1.1.2 / 2014-05-11
+==================
+
+  * improve json parser speed
+
+1.1.1 / 2014-05-11
+==================
+
+  * fix repeated limit parsing with every request
+
+1.1.0 / 2014-05-10
+==================
+
+  * add `type` option
+  * deps: pin for safety and consistency
+
+1.0.2 / 2014-04-14
+==================
+
+  * use `type-is` module
+
+1.0.1 / 2014-03-20
+==================
+
+  * lower default limits to 100kb
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..575f808
--- /dev/null
+++ b/README.md
@@ -0,0 +1,144 @@
+# body-parser
+
+[![NPM version](https://badge.fury.io/js/body-parser.svg)](https://badge.fury.io/js/body-parser)
+[![Build Status](https://travis-ci.org/expressjs/body-parser.svg?branch=master)](https://travis-ci.org/expressjs/body-parser)
+[![Coverage Status](https://img.shields.io/coveralls/expressjs/body-parser.svg?branch=master)](https://coveralls.io/r/expressjs/body-parser)
+
+Node.js body parsing middleware.
+
+This does not handle multipart bodies, due to their complex and typically large nature. For multipart bodies, you may be interested in the following modules:
+
+- [busboy](https://www.npmjs.org/package/busboy#readme) and [connect-busboy](https://www.npmjs.org/package/connect-busboy#readme)
+- [multiparty](https://www.npmjs.org/package/multiparty#readme) and [connect-multiparty](https://www.npmjs.org/package/connect-multiparty#readme)
+- [formidable](https://www.npmjs.org/package/formidable#readme)
+- [multer](https://www.npmjs.org/package/multer#readme)
+
+Other body parsers you might be interested in:
+
+- [body](https://www.npmjs.org/package/body#readme)
+- [co-body](https://www.npmjs.org/package/co-body#readme)
+
+## Installation
+
+```sh
+$ npm install body-parser
+```
+
+## API
+
+```js
+var express    = require('express')
+var bodyParser = require('body-parser')
+
+var app = express()
+
+// parse application/x-www-form-urlencoded
+app.use(bodyParser.urlencoded())
+
+// parse application/json
+app.use(bodyParser.json())
+
+// parse application/vnd.api+json as json
+app.use(bodyParser.json({ type: 'application/vnd.api+json' }))
+
+app.use(function (req, res, next) {
+  console.log(req.body) // populated!
+  next()
+})
+```
+
+### bodyParser.json(options)
+
+Returns middleware that only parses `json`. This parser accepts any Unicode encoding of the body and supports automatic inflation of `gzip` and `deflate` encodings.
+
+The options are:
+
+- `strict` - only parse objects and arrays. (default: `true`)
+- `inflate` - if deflated bodies will be inflated. (default: `true`)
+- `limit` - maximum request body size. (default: `<100kb>`)
+- `reviver` - passed to `JSON.parse()`
+- `type` - request content-type to parse (default: `json`)
+- `verify` - function to verify body content
+
+The `type` argument is passed directly to the [type-is](https://www.npmjs.org/package/type-is#readme) library. This can be an extension name (like `json`), a mime type (like `application/json`), or a mime time with a wildcard (like `*/json`).
+
+The `verify` argument, if supplied, is called as `verify(req, res, buf, encoding)`, where `buf` is a `Buffer` of the raw request body and `encoding` is the encoding of the request. The parsing can be aborted by throwing an error.
+
+The `reviver` argument is passed directly to `JSON.parse` as the second argument. You can find more information on this argument [in the MDN documentation about JSON.parse](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse#Example.3A_Using_the_reviver_parameter).
+
+### bodyParser.raw(options)
+
+Returns middleware that parses all bodies as a `Buffer`. This parser supports automatic inflation of `gzip` and `deflate` encodings.
+
+The options are:
+
+- `inflate` - if deflated bodies will be inflated. (default: `true`)
+- `limit` - maximum request body size. (default: `<100kb>`)
+- `type` - request content-type to parse (default: `application/octet-stream`)
+- `verify` - function to verify body content
+
+The `type` argument is passed directly to the [type-is](https://www.npmjs.org/package/type-is#readme) library. This can be an extension name (like `bin`), a mime type (like `application/octet-stream`), or a mime time with a wildcard (like `application/*`).
+
+The `verify` argument, if supplied, is called as `verify(req, res, buf, encoding)`, where `buf` is a `Buffer` of the raw request body and `encoding` is the encoding of the request. The parsing can be aborted by throwing an error.
+
+### bodyParser.text(options)
+
+Returns middleware that parses all bodies as a string. This parser supports automatic inflation of `gzip` and `deflate` encodings.
+
+The options are:
+
+- `defaultCharset` - the default charset to parse as, if not specified in content-type. (default: `utf-8`)
+- `inflate` - if deflated bodies will be inflated. (default: `true`)
+- `limit` - maximum request body size. (default: `<100kb>`)
+- `type` - request content-type to parse (default: `text/plain`)
+- `verify` - function to verify body content
+
+The `type` argument is passed directly to the [type-is](https://www.npmjs.org/package/type-is#readme) library. This can be an extension name (like `txt`), a mime type (like `text/plain`), or a mime time with a wildcard (like `text/*`).
+
+The `verify` argument, if supplied, is called as `verify(req, res, buf, encoding)`, where `buf` is a `Buffer` of the raw request body and `encoding` is the encoding of the request. The parsing can be aborted by throwing an error.
+
+### bodyParser.urlencoded(options)
+
+Returns middleware that only parses `urlencoded` bodies. This parser accepts only UTF-8 encoding of the body and supports automatic inflation of `gzip` and `deflate` encodings.
+
+The options are:
+
+- `extended` - parse extended syntax with the [qs](https://www.npmjs.org/package/qs#readme) module. (default: `true`)
+- `inflate` - if deflated bodies will be inflated. (default: `true`)
+- `limit` - maximum request body size. (default: `<100kb>`)
+- `type` - request content-type to parse (default: `urlencoded`)
+- `verify` - function to verify body content
+
+The `extended` argument allows to choose between parsing the urlencoded data with the `querystring` library (when `false`) or the `qs` library (when `true`). The "extended" syntax allows for rich objects and arrays to be encoded into the urlencoded format, allowing for a JSON-like exterience with urlencoded. For more information, please [see the qs library](https://www.npmjs.org/package/qs#readme).
+
+The `type` argument is passed directly to the [type-is](https://www.npmjs.org/package/type-is#readme) library. This can be an extension name (like `urlencoded`), a mime type (like `application/x-www-form-urlencoded`), or a mime time with a wildcard (like `*/x-www-form-urlencoded`).
+
+The `verify` argument, if supplied, is called as `verify(req, res, buf, encoding)`, where `buf` is a `Buffer` of the raw request body and `encoding` is the encoding of the request. The parsing can be aborted by throwing an error.
+
+### req.body
+
+A new `body` object containing the parsed data is populated on the `request` object after the middleware.
+
+## License
+
+The MIT License (MIT)
+
+Copyright (c) 2014 Jonathan Ong me at jongleberry.com
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/index.js b/index.js
new file mode 100644
index 0000000..bb9b04e
--- /dev/null
+++ b/index.js
@@ -0,0 +1,83 @@
+/*!
+ * body-parser
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var deprecate = require('depd')('body-parser')
+var fs = require('fs')
+var path = require('path')
+
+/**
+ * Module exports.
+ */
+
+exports = module.exports = deprecate.function(bodyParser,
+  'bodyParser: use individual json/urlencoded middlewares')
+
+/**
+ * Path to the parser modules.
+ */
+
+var parsersDir = path.join(__dirname, 'lib', 'types')
+
+/**
+ * Auto-load bundled parsers with getters.
+ */
+
+fs.readdirSync(parsersDir).forEach(function onfilename(filename) {
+  if (!/\.js$/.test(filename)) return
+
+  var loc = path.resolve(parsersDir, filename)
+  var mod
+  var name = path.basename(filename, '.js')
+
+  function load() {
+    if (mod) {
+      return mod
+    }
+
+    return mod = require(loc)
+  }
+
+  Object.defineProperty(exports, name, {
+    configurable: true,
+    enumerable: true,
+    get: load
+  })
+})
+
+/**
+ * Create a middleware to parse json and urlencoded bodies.
+ *
+ * @param {object} [options]
+ * @return {function}
+ * @deprecated
+ * @api public
+ */
+
+function bodyParser(options){
+  var opts = {}
+
+  options = options || {}
+
+  // exclude type option
+  for (var prop in options) {
+    if ('type' !== prop) {
+      opts[prop] = options[prop]
+    }
+  }
+
+  var _urlencoded = exports.urlencoded(opts)
+  var _json = exports.json(opts)
+
+  return function bodyParser(req, res, next) {
+    _json(req, res, function(err){
+      if (err) return next(err);
+      _urlencoded(req, res, next);
+    });
+  }
+}
diff --git a/lib/read.js b/lib/read.js
new file mode 100644
index 0000000..6dd3c2b
--- /dev/null
+++ b/lib/read.js
@@ -0,0 +1,155 @@
+/*!
+ * body-parser
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var getBody = require('raw-body')
+var iconv = require('iconv-lite')
+var typer = require('media-typer')
+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 {object} options
+ * @api private
+ */
+
+function read(req, res, next, parse, options) {
+  var length
+  var stream
+  var waitend = true
+
+  // flag as parsed
+  req._body = true
+
+  try {
+    stream = contentstream(req, options.inflate)
+    length = stream.length
+    delete stream.length
+  } catch (err) {
+    return next(err)
+  }
+
+  options = options || {}
+  options.length = length
+
+  var encoding = options.encoding !== null
+    ? options.encoding || 'utf-8'
+    : null
+  var verify = options.verify
+
+  options.encoding = verify
+    ? null
+    : encoding
+
+  req.on('aborted', cleanup)
+  req.on('end', cleanup)
+  req.on('error', cleanup)
+
+  // read body
+  getBody(stream, 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) {
+      if (!err.status) err.status = 400
+      next(err)
+      return
+    }
+
+    // verify
+    if (verify) {
+      try {
+        verify(req, res, body, encoding)
+      } catch (err) {
+        if (!err.status) err.status = 403
+        return next(err)
+      }
+    }
+
+    // parse
+    try {
+      body = typeof body !== 'string' && encoding !== null
+        ? iconv.decode(body, encoding)
+        : body
+      req.body = parse(body)
+    } catch (err){
+      err.body = body
+      err.status = 400
+      return next(err)
+    }
+
+    next()
+  })
+
+  function cleanup() {
+    waitend = false
+    req.removeListener('aborted', cleanup)
+    req.removeListener('end', cleanup)
+    req.removeListener('error', cleanup)
+  }
+}
+
+/**
+ * Get the content stream of the request.
+ *
+ * @param {object} req
+ * @param {boolean} [inflate=true]
+ * @return {object}
+ * @api private
+ */
+
+function contentstream(req, inflate) {
+  var encoding = req.headers['content-encoding'] || 'identity'
+  var err
+  var length = req.headers['content-length']
+  var stream
+
+  if (inflate === false && encoding !== 'identity') {
+    err = new Error('content encoding unsupported')
+    err.status = 415
+    throw err
+  }
+
+  switch (encoding) {
+    case 'deflate':
+      stream = zlib.createInflate()
+      req.pipe(stream)
+      break
+    case 'gzip':
+      stream = zlib.createGunzip()
+      req.pipe(stream)
+      break
+    case 'identity':
+      stream = req
+      stream.length = length
+      break
+    default:
+      err = new Error('unsupported content encoding')
+      err.status = 415
+      throw err
+  }
+
+  return stream
+}
diff --git a/lib/types/json.js b/lib/types/json.js
new file mode 100644
index 0000000..fe15a97
--- /dev/null
+++ b/lib/types/json.js
@@ -0,0 +1,105 @@
+/*!
+ * body-parser
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var bytes = require('bytes')
+var read = require('../read')
+var typer = require('media-typer')
+var typeis = require('type-is')
+
+/**
+ * Module exports.
+ */
+
+module.exports = json
+
+/**
+ * RegExp to match the first non-space in a string.
+ */
+
+var firstcharRegExp = /^\s*(.)/
+
+/**
+ * Create a middleware to parse JSON bodies.
+ *
+ * @param {object} [options]
+ * @return {function}
+ * @api public
+ */
+
+function json(options) {
+  options = options || {}
+
+  var limit = typeof options.limit !== 'number'
+    ? bytes(options.limit || '100kb')
+    : options.limit
+  var inflate = options.inflate !== false
+  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(body) {
+    if (0 === body.length) {
+      throw new Error('invalid json, empty body')
+    }
+
+    if (strict) {
+      var first = firstchar(body)
+
+      if (first !== '{' && first !== '[') {
+        throw new Error('invalid json')
+      }
+    }
+
+    return JSON.parse(body, reviver)
+  }
+
+  return function jsonParser(req, res, next) {
+    if (req._body) return next()
+    req.body = req.body || {}
+
+    if (!typeis(req, type)) return next()
+
+    // RFC 7159 sec 8.1
+    var charset = typer.parse(req).parameters.charset || 'utf-8'
+    if (charset.substr(0, 4).toLowerCase() !== 'utf-') {
+      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 first non-whitespace character in a string.
+ *
+ * @param {string} str
+ * @return {function}
+ * @api public
+ */
+
+
+function firstchar(str) {
+  if (!str) return ''
+  var match = firstcharRegExp.exec(str)
+  return match ? match[1] : ''
+}
diff --git a/lib/types/raw.js b/lib/types/raw.js
new file mode 100644
index 0000000..c1e7805
--- /dev/null
+++ b/lib/types/raw.js
@@ -0,0 +1,60 @@
+/*!
+ * body-parser
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var bytes = require('bytes')
+var read = require('../read')
+var typeis = require('type-is')
+
+/**
+ * Module exports.
+ */
+
+module.exports = raw
+
+/**
+ * Create a middleware to parse raw bodies.
+ *
+ * @param {object} [options]
+ * @return {function}
+ * @api public
+ */
+
+function raw(options) {
+  options = options || {};
+
+  var inflate = options.inflate !== false
+  var limit = typeof options.limit !== 'number'
+    ? bytes(options.limit || '100kb')
+    : options.limit
+  var type = options.type || 'application/octet-stream'
+  var verify = options.verify || false
+
+  if (verify !== false && typeof verify !== 'function') {
+    throw new TypeError('option verify must be function')
+  }
+
+  function parse(buf) {
+    return buf
+  }
+
+  return function rawParser(req, res, next) {
+    if (req._body) return next()
+    req.body = req.body || {}
+
+    if (!typeis(req, type)) return next()
+
+    // read
+    read(req, res, next, parse, {
+      encoding: null,
+      inflate: inflate,
+      limit: limit,
+      verify: verify
+    })
+  }
+}
diff --git a/lib/types/text.js b/lib/types/text.js
new file mode 100644
index 0000000..379ab6e
--- /dev/null
+++ b/lib/types/text.js
@@ -0,0 +1,65 @@
+/*!
+ * body-parser
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var bytes = require('bytes')
+var read = require('../read')
+var typeis = require('type-is')
+var typer = require('media-typer')
+
+/**
+ * Module exports.
+ */
+
+module.exports = text
+
+/**
+ * Create a middleware to parse text bodies.
+ *
+ * @param {object} [options]
+ * @return {function}
+ * @api public
+ */
+
+function text(options) {
+  options = options || {};
+
+  var defaultCharset = options.defaultCharset || 'utf-8'
+  var inflate = options.inflate !== false
+  var limit = typeof options.limit !== 'number'
+    ? bytes(options.limit || '100kb')
+    : options.limit
+  var type = options.type || 'text/plain'
+  var verify = options.verify || false
+
+  if (verify !== false && typeof verify !== 'function') {
+    throw new TypeError('option verify must be function')
+  }
+
+  function parse(buf) {
+    return buf
+  }
+
+  return function textParser(req, res, next) {
+    if (req._body) return next()
+    req.body = req.body || {}
+
+    if (!typeis(req, type)) return next()
+
+    // get charset
+    var charset = typer.parse(req).parameters.charset || defaultCharset
+
+    // read
+    read(req, res, next, parse, {
+      encoding: charset,
+      inflate: inflate,
+      limit: limit,
+      verify: verify
+    })
+  }
+}
diff --git a/lib/types/urlencoded.js b/lib/types/urlencoded.js
new file mode 100644
index 0000000..9d3e7e2
--- /dev/null
+++ b/lib/types/urlencoded.js
@@ -0,0 +1,109 @@
+/*!
+ * body-parser
+ * 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('urlencoded: explicitly specify "extended: true" for extended parsing')
+  }
+
+  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
+    ? parser('qs')
+    : parser('querystring')
+
+  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 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
+}
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..a086aee
--- /dev/null
+++ b/package.json
@@ -0,0 +1,34 @@
+{
+  "name": "body-parser",
+  "description": "Node.js body parsing middleware",
+  "version": "1.4.3",
+  "author": "Jonathan Ong <me at jongleberry.com> (http://jongleberry.com)",
+  "contributors": [
+    "Douglas Christopher Wilson <doug at somethingdoug.com>"
+  ],
+  "license": "MIT",
+  "repository": "expressjs/body-parser",
+  "dependencies": {
+    "bytes": "1.0.0",
+    "depd": "0.3.0",
+    "iconv-lite": "0.4.3",
+    "media-typer": "0.2.0",
+    "qs": "0.6.6",
+    "raw-body": "1.2.2",
+    "type-is": "1.3.1"
+  },
+  "devDependencies": {
+    "istanbul": "0.2.10",
+    "mocha": "~1.20.1",
+    "should": "~4.0.4",
+    "supertest": "~0.13.0"
+  },
+  "engines": {
+    "node": ">= 0.8"
+  },
+  "scripts": {
+    "test": "mocha --require should --require test/support/env --reporter spec --check-leaks --bail test/",
+    "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --require test/support/env --reporter dot --check-leaks test/",
+    "test-travis": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --require test/support/env --reporter spec --check-leaks test/"
+  }
+}
diff --git a/test/body-parser.js b/test/body-parser.js
new file mode 100644
index 0000000..7cd0ca4
--- /dev/null
+++ b/test/body-parser.js
@@ -0,0 +1,113 @@
+
+var assert = require('assert');
+var http = require('http');
+var request = require('supertest');
+
+var bodyParser = require('..');
+
+describe('bodyParser()', function(){
+  var server;
+  before(function(){
+    server = createServer()
+  })
+
+  it('should default to {}', function(done){
+    request(server)
+    .post('/')
+    .expect(200, '{}', done)
+  })
+
+  it('should parse JSON', function(done){
+    request(server)
+    .post('/')
+    .set('Content-Type', 'application/json')
+    .send('{"user":"tobi"}')
+    .expect(200, '{"user":"tobi"}', done)
+  })
+
+  it('should parse x-www-form-urlencoded', function(done){
+    request(server)
+    .post('/')
+    .set('Content-Type', 'application/x-www-form-urlencoded')
+    .send('user=tobi')
+    .expect(200, '{"user":"tobi"}', done)
+  })
+
+  it('should handle duplicated middleware', function(done){
+    var _bodyParser = bodyParser()
+    var server = http.createServer(function(req, res){
+      _bodyParser(req, res, function(err){
+        _bodyParser(req, res, function(err){
+          res.statusCode = err ? (err.status || 500) : 200;
+          res.end(err ? err.message : JSON.stringify(req.body));
+        })
+      })
+    })
+
+    request(server)
+    .post('/')
+    .set('Content-Type', 'application/json')
+    .send('{"user":"tobi"}')
+    .expect(200, '{"user":"tobi"}', done)
+  })
+
+  describe('with type option', function(){
+    var server;
+    before(function(){
+      server = createServer({ limit: '1mb', type: 'application/octet-stream' })
+    })
+
+    it('should parse JSON', function(done){
+      request(server)
+      .post('/')
+      .set('Content-Type', 'application/json')
+      .send('{"user":"tobi"}')
+      .expect(200, '{"user":"tobi"}', done)
+    })
+
+    it('should parse x-www-form-urlencoded', function(done){
+      request(server)
+      .post('/')
+      .set('Content-Type', 'application/x-www-form-urlencoded')
+      .send('user=tobi')
+      .expect(200, '{"user":"tobi"}', done)
+    })
+  })
+
+  describe('with verify option', function(){
+    it('should apply to json', function(done){
+      var server = createServer({verify: function(req, res, buf){
+        if (buf[0] === 0x20) throw new Error('no leading space')
+      }})
+
+      request(server)
+      .post('/')
+      .set('Content-Type', 'application/json')
+      .send(' {"user":"tobi"}')
+      .expect(403, 'no leading space', done)
+    })
+
+    it('should apply to urlencoded', function(done){
+      var server = createServer({verify: function(req, res, buf){
+        if (buf[0] === 0x20) throw new Error('no leading space')
+      }})
+
+      request(server)
+      .post('/')
+      .set('Content-Type', 'application/x-www-form-urlencoded')
+      .send(' user=tobi')
+      .expect(403, 'no leading space', done)
+    })
+  })
+})
+
+function createServer(opts){
+  var _bodyParser = bodyParser(opts)
+
+  return http.createServer(function(req, res){
+    _bodyParser(req, res, function(err){
+      res.statusCode = err ? (err.status || 500) : 200;
+      res.end(err ? err.message : JSON.stringify(req.body));
+    })
+  })
+}
diff --git a/test/json.js b/test/json.js
new file mode 100644
index 0000000..d6df309
--- /dev/null
+++ b/test/json.js
@@ -0,0 +1,460 @@
+
+var assert = require('assert');
+var http = require('http');
+var request = require('supertest');
+
+var bodyParser = require('..');
+
+describe('bodyParser.json()', function(){
+  it('should parse JSON', function(done){
+    var server = createServer({ limit: '1mb' })
+
+    request(server)
+    .post('/')
+    .set('Content-Type', 'application/json')
+    .send('{"user":"tobi"}')
+    .expect(200, '{"user":"tobi"}', done)
+  })
+
+  it('should fail gracefully', function(done){
+    var server = createServer({ limit: '1mb' })
+
+    request(server)
+    .post('/')
+    .set('Content-Type', 'application/json')
+    .send('{"user"')
+    .expect(400, 'Unexpected end of input', done)
+  })
+
+  it('should handle Content-Length: 0', function(done){
+    var server = createServer()
+
+    request(server)
+    .get('/')
+    .set('Content-Type', 'application/json')
+    .set('Content-Length', '0')
+    .expect(200, '{}', done)
+  })
+
+  it('should handle no message-body', function(done){
+    var server = createServer()
+
+    request(server)
+    .get('/')
+    .set('Content-Type', 'application/json')
+    .unset('Transfer-Encoding')
+    .expect(200, '{}', done)
+  })
+
+  it('should 400 on malformed JSON', function(done){
+    var server = createServer()
+
+    request(server)
+    .post('/')
+    .set('Content-Type', 'application/json')
+    .send('{"foo')
+    .expect(400, done);
+  })
+
+  it('should 400 when no body is given', function(done){
+    var server = createServer()
+
+    request(server)
+    .post('/')
+    .set('Content-Type', 'application/json')
+    .set('Transfer-Encoding', 'chunked')
+    .expect(400, 'invalid json, empty body', done)
+  })
+
+  it('should 400 when invalid content-length', function(done){
+    var server = createServer({ limit: '1kb' })
+
+    var test = request(server).post('/')
+    test.set('Content-Type', 'application/json')
+    test.set('Content-Length', '20')
+    test.set('Transfer-Encoding', 'chunked')
+    test.write('{"str":')
+    test.expect(400, /content length/, done)
+  })
+
+  it('should support all http methods', function(done){
+    var server = createServer()
+
+    request(server)
+    .get('/')
+    .set('Content-Type', 'application/json')
+    .set('Content-Length', '["foo"]'.length)
+    .send('["foo"]')
+    .expect(200, '["foo"]', done);
+  })
+
+  describe('when strict is false', function(){
+    it('should parse primitives', function(done){
+      var server = createServer({ strict: false })
+
+      request(server)
+      .post('/')
+      .set('Content-Type', 'application/json')
+      .send('true')
+      .expect(200, 'true', done);
+    })
+  })
+
+  describe('when strict is true', function(){
+    var server;
+    before(function(){
+      server = createServer({ strict: true })
+    })
+
+    it('should not parse primitives', function(done){
+      request(server)
+      .post('/')
+      .set('Content-Type', 'application/json')
+      .send('true')
+      .expect(400, 'invalid json', done)
+    })
+
+    it('should allow leading whitespaces in JSON', function(done){
+      request(server)
+      .post('/')
+      .set('Content-Type', 'application/json')
+      .send('   { "user": "tobi" }')
+      .expect(200, '{"user":"tobi"}', done)
+    })
+  })
+
+  describe('by default', function(){
+    it('should 400 on primitives', function(done){
+      var server = createServer()
+
+      request(server)
+      .post('/')
+      .set('Content-Type', 'application/json')
+      .send('true')
+      .expect(400, done);
+    })
+  })
+
+  describe('with limit option', function(){
+    it('should 413 when over limit with Content-Length', function(done){
+      var buf = new Buffer(1024)
+      var server = createServer({ limit: '1kb' })
+
+      buf.fill('.')
+
+      request(server)
+      .post('/')
+      .set('Content-Type', 'application/json')
+      .set('Content-Length', '1034')
+      .send(JSON.stringify({ str: buf.toString() }))
+      .expect(413, done)
+    })
+
+    it('should 413 when over limit with chunked encoding', function(done){
+      var buf = new Buffer(1024)
+      var server = createServer({ limit: '1kb' })
+
+      buf.fill('.')
+
+      var test = request(server).post('/')
+      test.set('Content-Type', 'application/json')
+      test.set('Transfer-Encoding', 'chunked')
+      test.write('{"str":')
+      test.write('"' + buf.toString() + '"}')
+      test.expect(413, done)
+    })
+
+    it('should accept number of bytes', function(done){
+      var buf = new Buffer(1024)
+      var server = createServer({ limit: 1024 })
+
+      buf.fill('.')
+
+      request(server)
+      .post('/')
+      .set('Content-Type', 'application/json')
+      .send(JSON.stringify({ str: buf.toString() }))
+      .expect(413, done)
+    })
+
+    it('should not change when options altered', function(done){
+      var buf = new Buffer(1024)
+      var options = { limit: '1kb' }
+      var server = createServer(options)
+
+      buf.fill('.')
+      options.limit = '100kb'
+
+      request(server)
+      .post('/')
+      .set('Content-Type', 'application/json')
+      .send(JSON.stringify({ str: buf.toString() }))
+      .expect(413, done)
+    })
+
+    it('should not hang response', function(done){
+      var buf = new Buffer(1024 * 10)
+      var server = createServer({ limit: '1kb' })
+
+      buf.fill('.')
+
+      var server = createServer({ limit: '8kb' })
+      var test = request(server).post('/')
+      test.set('Content-Type', 'application/json')
+      test.write(buf)
+      test.write(buf)
+      test.write(buf)
+      test.expect(413, done)
+    })
+  })
+
+  describe('with inflate option', function(){
+    describe('when false', function(){
+      var server;
+      before(function(){
+        server = createServer({ inflate: false })
+      })
+
+      it('should not accept content-encoding', function(done){
+        var test = request(server).post('/')
+        test.set('Content-Encoding', 'gzip')
+        test.set('Content-Type', 'application/json')
+        test.write(new Buffer('1f8b080000000000000bab56ca4bcc4d55b2527ab16e97522d00515be1cc0e000000', 'hex'))
+        test.expect(415, 'content encoding unsupported', done)
+      })
+    })
+
+    describe('when true', function(){
+      var server;
+      before(function(){
+        server = createServer({ inflate: true })
+      })
+
+      it('should accept content-encoding', function(done){
+        var test = request(server).post('/')
+        test.set('Content-Encoding', 'gzip')
+        test.set('Content-Type', 'application/json')
+        test.write(new Buffer('1f8b080000000000000bab56ca4bcc4d55b2527ab16e97522d00515be1cc0e000000', 'hex'))
+        test.expect(200, '{"name":"论"}', done)
+      })
+    })
+  })
+
+  describe('with type option', function(){
+    var server;
+    before(function(){
+      server = createServer({ type: 'application/vnd.api+json' })
+    })
+
+    it('should parse JSON for custom type', function(done){
+      request(server)
+      .post('/')
+      .set('Content-Type', 'application/vnd.api+json')
+      .send('{"user":"tobi"}')
+      .expect(200, '{"user":"tobi"}', done)
+    })
+
+    it('should ignore standard type', function(done){
+      request(server)
+      .post('/')
+      .set('Content-Type', 'application/json')
+      .send('{"user":"tobi"}')
+      .expect(200, '{}', done)
+    })
+  })
+
+  describe('with verify option', function(){
+    it('should assert value if function', function(){
+      var err;
+
+      try {
+        var server = createServer({ verify: 'lol' })
+      } catch (e) {
+        err = e;
+      }
+
+      assert.ok(err);
+      assert.equal(err.name, 'TypeError');
+    })
+
+    it('should error from verify', function(done){
+      var server = createServer({verify: function(req, res, buf){
+        if (buf[0] === 0x5b) throw new Error('no arrays')
+      }})
+
+      request(server)
+      .post('/')
+      .set('Content-Type', 'application/json')
+      .send('["tobi"]')
+      .expect(403, 'no arrays', done)
+    })
+
+    it('should allow custom codes', function(done){
+      var server = createServer({verify: function(req, res, buf){
+        if (buf[0] !== 0x5b) return
+        var err = new Error('no arrays')
+        err.status = 400
+        throw err
+      }})
+
+      request(server)
+      .post('/')
+      .set('Content-Type', 'application/json')
+      .send('["tobi"]')
+      .expect(400, 'no arrays', done)
+    })
+
+    it('should allow pass-through', function(done){
+      var server = createServer({verify: function(req, res, buf){
+        if (buf[0] === 0x5b) throw new Error('no arrays')
+      }})
+
+      request(server)
+      .post('/')
+      .set('Content-Type', 'application/json')
+      .send('{"user":"tobi"}')
+      .expect(200, '{"user":"tobi"}', done)
+    })
+
+    it('should work with different charsets', function(done){
+      var server = createServer({verify: function(req, res, buf){
+        if (buf[0] === 0x5b) throw new Error('no arrays')
+      }})
+
+      var test = request(server).post('/')
+      test.set('Content-Type', 'application/json; charset=utf-16')
+      test.write(new Buffer('feff007b0022006e0061006d00650022003a00228bba0022007d', 'hex'))
+      test.expect(200, '{"name":"论"}', done)
+    })
+
+  })
+
+  describe('charset', function(){
+    var server;
+    before(function(){
+      server = createServer()
+    })
+
+    it('should parse utf-8', function(done){
+      var test = request(server).post('/')
+      test.set('Content-Type', 'application/json; charset=utf-8')
+      test.write(new Buffer('7b226e616d65223a22e8aeba227d', 'hex'))
+      test.expect(200, '{"name":"论"}', done)
+    })
+
+    it('should parse utf-16', function(done){
+      var test = request(server).post('/')
+      test.set('Content-Type', 'application/json; charset=utf-16')
+      test.write(new Buffer('feff007b0022006e0061006d00650022003a00228bba0022007d', 'hex'))
+      test.expect(200, '{"name":"论"}', done)
+    })
+
+    it('should parse when content-length != char length', function(done){
+      var test = request(server).post('/')
+      test.set('Content-Type', 'application/json; charset=utf-8')
+      test.set('Content-Length', '13')
+      test.write(new Buffer('7b2274657374223a22c3a5227d', 'hex'))
+      test.expect(200, '{"test":"å"}', done)
+    })
+
+    it('should default to utf-8', function(done){
+      var test = request(server).post('/')
+      test.set('Content-Type', 'application/json')
+      test.write(new Buffer('7b226e616d65223a22e8aeba227d', 'hex'))
+      test.expect(200, '{"name":"论"}', done)
+    })
+
+    it('should fail on unknown charset', function(done){
+      var test = request(server).post('/')
+      test.set('Content-Type', 'application/json; charset=koi8-r')
+      test.write(new Buffer('7b226e616d65223a22cec5d4227d', 'hex'))
+      test.expect(415, 'unsupported charset', done)
+    })
+  })
+
+  describe('encoding', function(){
+    var server;
+    before(function(){
+      server = createServer({ limit: '1kb' })
+    })
+
+    it('should parse without encoding', function(done){
+      var test = request(server).post('/')
+      test.set('Content-Type', 'application/json')
+      test.write(new Buffer('7b226e616d65223a22e8aeba227d', 'hex'))
+      test.expect(200, '{"name":"论"}', done)
+    })
+
+    it('should support identity encoding', function(done){
+      var test = request(server).post('/')
+      test.set('Content-Encoding', 'identity')
+      test.set('Content-Type', 'application/json')
+      test.write(new Buffer('7b226e616d65223a22e8aeba227d', 'hex'))
+      test.expect(200, '{"name":"论"}', done)
+    })
+
+    it('should support gzip encoding', function(done){
+      var test = request(server).post('/')
+      test.set('Content-Encoding', 'gzip')
+      test.set('Content-Type', 'application/json')
+      test.write(new Buffer('1f8b080000000000000bab56ca4bcc4d55b2527ab16e97522d00515be1cc0e000000', 'hex'))
+      test.expect(200, '{"name":"论"}', done)
+    })
+
+    it('should support deflate encoding', function(done){
+      var test = request(server).post('/')
+      test.set('Content-Encoding', 'deflate')
+      test.set('Content-Type', 'application/json')
+      test.write(new Buffer('789cab56ca4bcc4d55b2527ab16e97522d00274505ac', 'hex'))
+      test.expect(200, '{"name":"论"}', done)
+    })
+
+    it('should check content-length correctly', function(done){
+      var test = request(server).post('/')
+      test.set('Content-Encoding', 'gzip')
+      test.set('Content-Length', '49')
+      test.set('Content-Type', 'application/json')
+      test.set('Transfer-Encoding', 'chunked')
+      test.write(new Buffer('1f8b080000000000000bab56ca4bcc4d55b2527ab16e97522d00515be1cc0e000000', 'hex'))
+      test.expect(200, '{"name":"论"}', done)
+    })
+
+    it('should 415 on unknown encoding', function(done){
+      var test = request(server).post('/')
+      test.set('Content-Encoding', 'nulls')
+      test.set('Content-Type', 'application/json')
+      test.write(new Buffer('000000000000', 'hex'))
+      test.expect(415, 'unsupported content encoding', done)
+    })
+
+    it('should 400 on malformed encoding', function(done){
+      var test = request(server).post('/')
+      test.set('Content-Encoding', 'gzip')
+      test.set('Content-Type', 'application/json')
+      test.write(new Buffer('1f8b080000000000000bab56cc4d55b2527ab16e97522d00515be1cc0e000000', 'hex'))
+      test.expect(400, done)
+    })
+
+    it('should 413 when inflated value exceeds limit', function(done){
+      // gzip'd data exceeds 1kb, but deflated below 1kb
+      var test = request(server).post('/')
+      test.set('Content-Encoding', 'gzip')
+      test.set('Content-Type', 'application/json')
+      test.write(new Buffer('1f8b080000000000000bedc1010d000000c2a0f74f6d0f071400000000000000', 'hex'))
+      test.write(new Buffer('0000000000000000000000000000000000000000000000000000000000000000', 'hex'))
+      test.write(new Buffer('0000000000000000004f0625b3b71650c30000', 'hex'))
+      test.expect(413, done)
+    })
+  })
+})
+
+function createServer(opts){
+  var _bodyParser = bodyParser.json(opts)
+
+  return http.createServer(function(req, res){
+    _bodyParser(req, res, function(err){
+      res.statusCode = err ? (err.status || 500) : 200;
+      res.end(err ? err.message : JSON.stringify(req.body));
+    })
+  })
+}
diff --git a/test/raw.js b/test/raw.js
new file mode 100644
index 0000000..3dfad00
--- /dev/null
+++ b/test/raw.js
@@ -0,0 +1,281 @@
+
+var assert = require('assert')
+var http = require('http')
+var request = require('supertest')
+
+var bodyParser = require('..')
+
+describe('bodyParser.raw()', function(){
+  var server
+  before(function(){
+    server = createServer()
+  })
+
+  it('should parse application/octet-stream', function(done){
+    request(server)
+    .post('/')
+    .set('Content-Type', 'application/octet-stream')
+    .send('the user is tobi')
+    .expect(200, 'buf:746865207573657220697320746f6269', done)
+  })
+
+  it('should 400 when invalid content-length', function(done){
+    var server = createServer({ limit: '1kb' })
+
+    var test = request(server).post('/')
+    test.set('Content-Type', 'application/octet-stream')
+    test.set('Content-Length', '20')
+    test.set('Transfer-Encoding', 'chunked')
+    test.write('stuff')
+    test.expect(400, /content length/, done)
+  })
+
+  it('should handle empty message-body', function(done){
+    request(server)
+    .post('/')
+    .set('Content-Type', 'application/octet-stream')
+    .set('Transfer-Encoding', 'chunked')
+    .send('')
+    .expect(200, 'buf:', done)
+  })
+
+  describe('with limit option', function(){
+    it('should 413 when over limit with Content-Length', function(done){
+      var buf = new Buffer(1028)
+      var server = createServer({ limit: '1kb' })
+
+      buf.fill('.')
+
+      var test = request(server).post('/')
+      test.set('Content-Type', 'application/octet-stream')
+      test.set('Content-Length', '1028')
+      test.write(buf)
+      test.expect(413, done)
+    })
+
+    it('should 413 when over limit with chunked encoding', function(done){
+      var buf = new Buffer(1028)
+      var server = createServer({ limit: '1kb' })
+
+      buf.fill('.')
+
+      var test = request(server).post('/')
+      test.set('Content-Type', 'application/octet-stream')
+      test.set('Transfer-Encoding', 'chunked')
+      test.write(buf)
+      test.expect(413, done)
+    })
+
+    it('should accept number of bytes', function(done){
+      var buf = new Buffer(1028)
+      var server = createServer({ limit: 1024 })
+
+      buf.fill('.')
+
+      var test = request(server).post('/')
+      test.set('Content-Type', 'application/octet-stream')
+      test.write(buf)
+      test.expect(413, done)
+    })
+
+    it('should not change when options altered', function(done){
+      var buf = new Buffer(1028)
+      var options = { limit: '1kb' }
+      var server = createServer(options)
+
+      buf.fill('.')
+      options.limit = '100kb'
+
+      var test = request(server).post('/')
+      test.set('Content-Type', 'application/octet-stream')
+      test.write(buf)
+      test.expect(413, done)
+    })
+
+    it('should not hang response', function(done){
+      var buf = new Buffer(1024 * 10)
+      var server = createServer({ limit: '1kb' })
+
+      buf.fill('.')
+
+      var server = createServer({ limit: '8kb' })
+      var test = request(server).post('/')
+      test.set('Content-Type', 'application/octet-stream')
+      test.write(buf)
+      test.write(buf)
+      test.write(buf)
+      test.expect(413, done)
+    })
+  })
+
+  describe('with inflate option', function(){
+    describe('when false', function(){
+      var server;
+      before(function(){
+        server = createServer({ inflate: false })
+      })
+
+      it('should not accept content-encoding', function(done){
+        var test = request(server).post('/')
+        test.set('Content-Encoding', 'gzip')
+        test.set('Content-Type', 'application/octet-stream')
+        test.write(new Buffer('1f8b080000000000000bcb4bcc4db57db16e170099a4bad608000000', 'hex'))
+        test.expect(415, 'content encoding unsupported', done)
+      })
+    })
+
+    describe('when true', function(){
+      var server;
+      before(function(){
+        server = createServer({ inflate: true })
+      })
+
+      it('should accept content-encoding', function(done){
+        var test = request(server).post('/')
+        test.set('Content-Encoding', 'gzip')
+        test.set('Content-Type', 'application/octet-stream')
+        test.write(new Buffer('1f8b080000000000000bcb4bcc4db57db16e170099a4bad608000000', 'hex'))
+        test.expect(200, 'buf:6e616d653de8aeba', done)
+      })
+    })
+  })
+
+  describe('with type option', function(){
+    var server;
+    before(function(){
+      server = createServer({ type: 'application/vnd+octets' })
+    })
+
+    it('should parse for custom type', function(done){
+      var test = request(server).post('/')
+      test.set('Content-Type', 'application/vnd+octets')
+      test.write(new Buffer('000102', 'hex'))
+      test.expect(200, 'buf:000102', done)
+    })
+
+    it('should ignore standard type', function(done){
+      var test = request(server).post('/')
+      test.set('Content-Type', 'application/octet-stream')
+      test.write(new Buffer('000102', 'hex'))
+      test.expect(200, '{}', done)
+    })
+  })
+
+  describe('with verify option', function(){
+    it('should assert value is function', function(){
+      var err;
+
+      try {
+        var server = createServer({ verify: 'lol' })
+      } catch (e) {
+        err = e;
+      }
+
+      assert.ok(err);
+      assert.equal(err.name, 'TypeError');
+    })
+
+    it('should error from verify', function(done){
+      var server = createServer({verify: function(req, res, buf){
+        if (buf[0] === 0x00) throw new Error('no leading null')
+      }})
+
+      var test = request(server).post('/')
+      test.set('Content-Type', 'application/octet-stream')
+      test.write(new Buffer('000102', 'hex'))
+      test.expect(403, 'no leading null', done)
+    })
+
+    it('should allow custom codes', function(done){
+      var server = createServer({verify: function(req, res, buf){
+        if (buf[0] !== 0x00) return
+        var err = new Error('no leading null')
+        err.status = 400
+        throw err
+      }})
+
+      var test = request(server).post('/')
+      test.set('Content-Type', 'application/octet-stream')
+      test.write(new Buffer('000102', 'hex'))
+      test.expect(400, 'no leading null', done)
+    })
+
+    it('should allow pass-through', function(done){
+      var server = createServer({verify: function(req, res, buf){
+        if (buf[0] === 0x00) throw new Error('no leading null')
+      }})
+
+      var test = request(server).post('/')
+      test.set('Content-Type', 'application/octet-stream')
+      test.write(new Buffer('0102', 'hex'))
+      test.expect(200, 'buf:0102', done)
+    })
+  })
+
+  describe('encoding', function(){
+    var server;
+    before(function(){
+      server = createServer({ limit: '10kb' })
+    })
+
+    it('should parse without encoding', function(done){
+      var test = request(server).post('/')
+      test.set('Content-Type', 'application/octet-stream')
+      test.write(new Buffer('6e616d653de8aeba', 'hex'))
+      test.expect(200, 'buf:6e616d653de8aeba', done)
+    })
+
+    it('should support identity encoding', function(done){
+      var test = request(server).post('/')
+      test.set('Content-Encoding', 'identity')
+      test.set('Content-Type', 'application/octet-stream')
+      test.write(new Buffer('6e616d653de8aeba', 'hex'))
+      test.expect(200, 'buf:6e616d653de8aeba', done)
+    })
+
+    it('should support gzip encoding', function(done){
+      var test = request(server).post('/')
+      test.set('Content-Encoding', 'gzip')
+      test.set('Content-Type', 'application/octet-stream')
+      test.write(new Buffer('1f8b080000000000000bcb4bcc4db57db16e170099a4bad608000000', 'hex'))
+      test.expect(200, 'buf:6e616d653de8aeba', done)
+    })
+
+    it('should support deflate encoding', function(done){
+      var test = request(server).post('/')
+      test.set('Content-Encoding', 'deflate')
+      test.set('Content-Type', 'application/octet-stream')
+      test.write(new Buffer('789ccb4bcc4db57db16e17001068042f', 'hex'))
+      test.expect(200, 'buf:6e616d653de8aeba', done)
+    })
+
+    it('should fail on unknown encoding', function(done){
+      var test = request(server).post('/')
+      test.set('Content-Encoding', 'nulls')
+      test.set('Content-Type', 'application/octet-stream')
+      test.write(new Buffer('000000000000', 'hex'))
+      test.expect(415, 'unsupported content encoding', done)
+    })
+  })
+})
+
+function createServer(opts){
+  var _bodyParser = bodyParser.raw(opts)
+
+  return http.createServer(function(req, res){
+    _bodyParser(req, res, function(err){
+      if (err) {
+        res.statusCode = err.status || 500
+        res.end(err.message)
+        return
+      }
+
+      if (Buffer.isBuffer(req.body)) {
+        res.end('buf:' + req.body.toString('hex'))
+        return
+      }
+
+      res.end(JSON.stringify(req.body))
+    })
+  })
+}
diff --git a/test/support/env.js b/test/support/env.js
new file mode 100644
index 0000000..323eba2
--- /dev/null
+++ b/test/support/env.js
@@ -0,0 +1,2 @@
+
+process.env.NO_DEPRECATION = 'body-parser'
diff --git a/test/text.js b/test/text.js
new file mode 100644
index 0000000..7f4b74a
--- /dev/null
+++ b/test/text.js
@@ -0,0 +1,324 @@
+
+var assert = require('assert')
+var http = require('http')
+var request = require('supertest')
+
+var bodyParser = require('..')
+
+describe('bodyParser.text()', function(){
+  var server
+  before(function(){
+    server = createServer()
+  })
+
+  it('should parse text/plain', function(done){
+    request(server)
+    .post('/')
+    .set('Content-Type', 'text/plain')
+    .send('user is tobi')
+    .expect(200, '"user is tobi"', done)
+  })
+
+  it('should 400 when invalid content-length', function(done){
+    var server = createServer({ limit: '1kb' })
+
+    var test = request(server).post('/')
+    test.set('Content-Type', 'text/plain')
+    test.set('Content-Length', '20')
+    test.set('Transfer-Encoding', 'chunked')
+    test.write('user')
+    test.expect(400, /content length/, done)
+  })
+
+  it('should handle empty message-body', function(done){
+    var server = createServer({ limit: '1kb' })
+
+    request(server)
+    .post('/')
+    .set('Content-Type', 'text/plain')
+    .set('Transfer-Encoding', 'chunked')
+    .send('')
+    .expect(200, '""', done)
+  })
+
+  describe('with limit option', function(){
+    it('should 413 when over limit with Content-Length', function(done){
+      var buf = new Buffer(1028)
+      var server = createServer({ limit: '1kb' })
+
+      buf.fill('.')
+
+      request(server)
+      .post('/')
+      .set('Content-Type', 'text/plain')
+      .set('Content-Length', '1028')
+      .send(buf.toString())
+      .expect(413, done)
+    })
+
+    it('should 413 when over limit with chunked encoding', function(done){
+      var buf = new Buffer(1028)
+      var server = createServer({ limit: '1kb' })
+
+      buf.fill('.')
+
+      var test = request(server).post('/')
+      test.set('Content-Type', 'text/plain')
+      test.set('Transfer-Encoding', 'chunked')
+      test.write(buf.toString())
+      test.expect(413, done)
+    })
+
+    it('should accept number of bytes', function(done){
+      var buf = new Buffer(1028)
+      var server = createServer({ limit: 1024 })
+
+      buf.fill('.')
+
+      request(server)
+      .post('/')
+      .set('Content-Type', 'text/plain')
+      .send(buf.toString())
+      .expect(413, done)
+    })
+
+    it('should not change when options altered', function(done){
+      var buf = new Buffer(1028)
+      var options = { limit: '1kb' }
+      var server = createServer(options)
+
+      buf.fill('.')
+      options.limit = '100kb'
+
+      request(server)
+      .post('/')
+      .set('Content-Type', 'text/plain')
+      .send(buf.toString())
+      .expect(413, done)
+    })
+
+    it('should not hang response', function(done){
+      var buf = new Buffer(1024 * 10)
+      var server = createServer({ limit: '1kb' })
+
+      buf.fill('.')
+
+      var server = createServer({ limit: '8kb' })
+      var test = request(server).post('/')
+      test.set('Content-Type', 'text/plain')
+      test.write(buf)
+      test.write(buf)
+      test.write(buf)
+      test.expect(413, done)
+    })
+  })
+
+  describe('with inflate option', function(){
+    describe('when false', function(){
+      var server;
+      before(function(){
+        server = createServer({ inflate: false })
+      })
+
+      it('should not accept content-encoding', function(done){
+        var test = request(server).post('/')
+        test.set('Content-Encoding', 'gzip')
+        test.set('Content-Type', 'text/plain')
+        test.write(new Buffer('1f8b080000000000000bcb4bcc4d55c82c5678b16e170072b3e0200b000000', 'hex'))
+        test.expect(415, 'content encoding unsupported', done)
+      })
+    })
+
+    describe('when true', function(){
+      var server;
+      before(function(){
+        server = createServer({ inflate: true })
+      })
+
+      it('should accept content-encoding', function(done){
+        var test = request(server).post('/')
+        test.set('Content-Encoding', 'gzip')
+        test.set('Content-Type', 'text/plain')
+      test.write(new Buffer('1f8b080000000000000bcb4bcc4d55c82c5678b16e170072b3e0200b000000', 'hex'))
+      test.expect(200, '"name is 论"', done)
+      })
+    })
+  })
+
+  describe('with type option', function(){
+    var server;
+    before(function(){
+      server = createServer({ type: 'text/html' })
+    })
+
+    it('should parse for custom type', function(done){
+      request(server)
+      .post('/')
+      .set('Content-Type', 'text/html')
+      .send('<b>tobi</b>')
+      .expect(200, '"<b>tobi</b>"', done)
+    })
+
+    it('should ignore standard type', function(done){
+      request(server)
+      .post('/')
+      .set('Content-Type', 'text/plain')
+      .send('user is tobi')
+      .expect(200, '{}', done)
+    })
+  })
+
+  describe('with verify option', function(){
+    it('should assert value is function', function(){
+      var err;
+
+      try {
+        var server = createServer({ verify: 'lol' })
+      } catch (e) {
+        err = e;
+      }
+
+      assert.ok(err);
+      assert.equal(err.name, 'TypeError');
+    })
+
+    it('should error from verify', function(done){
+      var server = createServer({verify: function(req, res, buf){
+        if (buf[0] === 0x20) throw new Error('no leading space')
+      }})
+
+      request(server)
+      .post('/')
+      .set('Content-Type', 'text/plain')
+      .send(' user is tobi')
+      .expect(403, 'no leading space', done)
+    })
+
+    it('should allow custom codes', function(done){
+      var server = createServer({verify: function(req, res, buf){
+        if (buf[0] !== 0x20) return
+        var err = new Error('no leading space')
+        err.status = 400
+        throw err
+      }})
+
+      request(server)
+      .post('/')
+      .set('Content-Type', 'text/plain')
+      .send(' user is tobi')
+      .expect(400, 'no leading space', done)
+    })
+
+    it('should allow pass-through', function(done){
+      var server = createServer({verify: function(req, res, buf){
+        if (buf[0] === 0x20) throw new Error('no leading space')
+      }})
+
+      request(server)
+      .post('/')
+      .set('Content-Type', 'text/plain')
+      .send('user is tobi')
+      .expect(200, '"user is tobi"', done)
+    })
+  })
+
+  describe('charset', function(){
+    var server;
+    before(function(){
+      server = createServer()
+    })
+
+    it('should parse utf-8', function(done){
+      var test = request(server).post('/')
+      test.set('Content-Type', 'text/plain; charset=utf-8')
+      test.write(new Buffer('6e616d6520697320e8aeba', 'hex'))
+      test.expect(200, '"name is 论"', done)
+    })
+
+    it('should parse codepage charsets', function(done){
+      var test = request(server).post('/')
+      test.set('Content-Type', 'text/plain; charset=koi8-r')
+      test.write(new Buffer('6e616d6520697320cec5d4', 'hex'))
+      test.expect(200, '"name is нет"', done)
+    })
+
+    it('should parse when content-length != char length', function(done){
+      var test = request(server).post('/')
+      test.set('Content-Type', 'text/plain; charset=utf-8')
+      test.set('Content-Length', '11')
+      test.write(new Buffer('6e616d6520697320e8aeba', 'hex'))
+      test.expect(200, '"name is 论"', done)
+    })
+
+    it('should default to utf-8', function(done){
+      var test = request(server).post('/')
+      test.set('Content-Type', 'text/plain')
+      test.write(new Buffer('6e616d6520697320e8aeba', 'hex'))
+      test.expect(200, '"name is 论"', done)
+    })
+
+    it('should 415 on unknown charset', function(done){
+      var test = request(server).post('/')
+      test.set('Content-Type', 'text/plain; charset=x-bogus')
+      test.write(new Buffer('00000000', 'hex'))
+      test.expect(415, /encoding/, done)
+    })
+  })
+
+  describe('encoding', function(){
+    var server;
+    before(function(){
+      server = createServer({ limit: '10kb' })
+    })
+
+    it('should parse without encoding', function(done){
+      var test = request(server).post('/')
+      test.set('Content-Type', 'text/plain')
+      test.write(new Buffer('6e616d6520697320e8aeba', 'hex'))
+      test.expect(200, '"name is 论"', done)
+    })
+
+    it('should support identity encoding', function(done){
+      var test = request(server).post('/')
+      test.set('Content-Encoding', 'identity')
+      test.set('Content-Type', 'text/plain')
+      test.write(new Buffer('6e616d6520697320e8aeba', 'hex'))
+      test.expect(200, '"name is 论"', done)
+    })
+
+    it('should support gzip encoding', function(done){
+      var test = request(server).post('/')
+      test.set('Content-Encoding', 'gzip')
+      test.set('Content-Type', 'text/plain')
+      test.write(new Buffer('1f8b080000000000000bcb4bcc4d55c82c5678b16e170072b3e0200b000000', 'hex'))
+      test.expect(200, '"name is 论"', done)
+    })
+
+    it('should support deflate encoding', function(done){
+      var test = request(server).post('/')
+      test.set('Content-Encoding', 'deflate')
+      test.set('Content-Type', 'text/plain')
+      test.write(new Buffer('789ccb4bcc4d55c82c5678b16e17001a6f050e', 'hex'))
+      test.expect(200, '"name is 论"', done)
+    })
+
+    it('should fail on unknown encoding', function(done){
+      var test = request(server).post('/')
+      test.set('Content-Encoding', 'nulls')
+      test.set('Content-Type', 'text/plain')
+      test.write(new Buffer('000000000000', 'hex'))
+      test.expect(415, 'unsupported content encoding', done)
+    })
+  })
+})
+
+function createServer(opts){
+  var _bodyParser = bodyParser.text(opts)
+
+  return http.createServer(function(req, res){
+    _bodyParser(req, res, function(err){
+      res.statusCode = err ? (err.status || 500) : 200;
+      res.end(err ? err.message : JSON.stringify(req.body));
+    })
+  })
+}
diff --git a/test/urlencoded.js b/test/urlencoded.js
new file mode 100644
index 0000000..c7fd88c
--- /dev/null
+++ b/test/urlencoded.js
@@ -0,0 +1,367 @@
+
+var assert = require('assert');
+var http = require('http');
+var request = require('supertest');
+
+var bodyParser = require('..');
+
+describe('bodyParser.urlencoded()', function(){
+  var server
+  before(function(){
+    server = createServer()
+  })
+
+  it('should support all http methods', function(done){
+    request(server)
+    .get('/')
+    .set('Content-Type', 'application/x-www-form-urlencoded')
+    .set('Content-Length', 'user=tobi'.length)
+    .send('user=tobi')
+    .expect(200, '{"user":"tobi"}', done)
+  })
+
+  it('should parse x-www-form-urlencoded', function(done){
+    request(server)
+    .post('/')
+    .set('Content-Type', 'application/x-www-form-urlencoded')
+    .send('user=tobi')
+    .expect(200, '{"user":"tobi"}', done)
+  })
+
+  it('should 400 when invalid content-length', function(done){
+    var server = createServer({ limit: '1kb' })
+
+    var test = request(server).post('/')
+    test.set('Content-Type', 'application/x-www-form-urlencoded')
+    test.set('Content-Length', '20')
+    test.set('Transfer-Encoding', 'chunked')
+    test.write('str=')
+    test.expect(400, /content length/, done)
+  })
+
+  it('should handle empty message-body', function(done){
+    var server = createServer({ limit: '1kb' })
+
+    request(server)
+    .post('/')
+    .set('Content-Type', 'application/x-www-form-urlencoded')
+    .set('Transfer-Encoding', 'chunked')
+    .send('')
+    .expect(200, '{}', done)
+  })
+
+  it('should parse extended syntax', function(done){
+    request(server)
+    .post('/')
+    .set('Content-Type', 'application/x-www-form-urlencoded')
+    .send('user[name][first]=Tobi')
+    .expect(200, '{"user":{"name":{"first":"Tobi"}}}', done)
+  })
+
+  describe('with extended option', function(){
+    describe('when false', function(){
+      var server;
+      before(function(){
+        server = createServer({ extended: false })
+      })
+
+      it('should not parse extended syntax', function(done){
+        request(server)
+        .post('/')
+        .set('Content-Type', 'application/x-www-form-urlencoded')
+        .send('user[name][first]=Tobi')
+        .expect(200, '{"user[name][first]":"Tobi"}', done)
+      })
+    })
+
+    describe('when true', function(){
+      var server;
+      before(function(){
+        server = createServer({ extended: true })
+      })
+
+      it('should parse extended syntax', function(done){
+        request(server)
+        .post('/')
+        .set('Content-Type', 'application/x-www-form-urlencoded')
+        .send('user[name][first]=Tobi')
+        .expect(200, '{"user":{"name":{"first":"Tobi"}}}', done)
+      })
+    })
+  })
+
+  describe('with inflate option', function(){
+    describe('when false', function(){
+      var server;
+      before(function(){
+        server = createServer({ inflate: false })
+      })
+
+      it('should not accept content-encoding', function(done){
+        var test = request(server).post('/')
+        test.set('Content-Encoding', 'gzip')
+        test.set('Content-Type', 'application/x-www-form-urlencoded')
+        test.write(new Buffer('1f8b080000000000000bcb4bcc4db57db16e170099a4bad608000000', 'hex'))
+        test.expect(415, 'content encoding unsupported', done)
+      })
+    })
+
+    describe('when true', function(){
+      var server;
+      before(function(){
+        server = createServer({ inflate: true })
+      })
+
+      it('should accept content-encoding', function(done){
+        var test = request(server).post('/')
+        test.set('Content-Encoding', 'gzip')
+        test.set('Content-Type', 'application/x-www-form-urlencoded')
+        test.write(new Buffer('1f8b080000000000000bcb4bcc4db57db16e170099a4bad608000000', 'hex'))
+        test.expect(200, '{"name":"论"}', done)
+      })
+    })
+  })
+
+  describe('with limit option', function(){
+    it('should 413 when over limit with Content-Length', function(done){
+      var buf = new Buffer(1024)
+      var server = createServer({ limit: '1kb' })
+
+      buf.fill('.')
+
+      request(server)
+      .post('/')
+      .set('Content-Type', 'application/x-www-form-urlencoded')
+      .set('Content-Length', '1028')
+      .send('str=' + buf.toString())
+      .expect(413, done)
+    })
+
+    it('should 413 when over limit with chunked encoding', function(done){
+      var buf = new Buffer(1024)
+      var server = createServer({ limit: '1kb' })
+
+      buf.fill('.')
+
+      var test = request(server).post('/')
+      test.set('Content-Type', 'application/x-www-form-urlencoded')
+      test.set('Transfer-Encoding', 'chunked')
+      test.write('str=')
+      test.write(buf.toString())
+      test.expect(413, done)
+    })
+
+    it('should accept number of bytes', function(done){
+      var buf = new Buffer(1024)
+      var server = createServer({ limit: 1024 })
+
+      buf.fill('.')
+
+      request(server)
+      .post('/')
+      .set('Content-Type', 'application/x-www-form-urlencoded')
+      .send('str=' + buf.toString())
+      .expect(413, done)
+    })
+
+    it('should not change when options altered', function(done){
+      var buf = new Buffer(1024)
+      var options = { limit: '1kb' }
+      var server = createServer(options)
+
+      buf.fill('.')
+      options.limit = '100kb'
+
+      request(server)
+      .post('/')
+      .set('Content-Type', 'application/x-www-form-urlencoded')
+      .send('str=' + buf.toString())
+      .expect(413, done)
+    })
+
+    it('should not hang response', function(done){
+      var buf = new Buffer(1024 * 10)
+      var server = createServer({ limit: '1kb' })
+
+      buf.fill('.')
+
+      var server = createServer({ limit: '8kb' })
+      var test = request(server).post('/')
+      test.set('Content-Type', 'application/x-www-form-urlencoded')
+      test.write(buf)
+      test.write(buf)
+      test.write(buf)
+      test.expect(413, done)
+    })
+  })
+
+  describe('with type option', function(){
+    var server;
+    before(function(){
+      server = createServer({ type: 'application/vnd+x-www-form-urlencoded' })
+    })
+
+    it('should parse for custom type', function(done){
+      request(server)
+      .post('/')
+      .set('Content-Type', 'application/vnd+x-www-form-urlencoded')
+      .send('user=tobi')
+      .expect(200, '{"user":"tobi"}', done)
+    })
+
+    it('should ignore standard type', function(done){
+      request(server)
+      .post('/')
+      .set('Content-Type', 'application/x-www-form-urlencoded')
+      .send('user=tobi')
+      .expect(200, '{}', done)
+    })
+  })
+
+  describe('with verify option', function(){
+    it('should assert value if function', function(){
+      var err;
+
+      try {
+        var server = createServer({ verify: 'lol' })
+      } catch (e) {
+        err = e;
+      }
+
+      assert.ok(err);
+      assert.equal(err.name, 'TypeError');
+    })
+
+    it('should error from verify', function(done){
+      var server = createServer({verify: function(req, res, buf){
+        if (buf[0] === 0x20) throw new Error('no leading space')
+      }})
+
+      request(server)
+      .post('/')
+      .set('Content-Type', 'application/x-www-form-urlencoded')
+      .send(' user=tobi')
+      .expect(403, 'no leading space', done)
+    })
+
+    it('should allow custom codes', function(done){
+      var server = createServer({verify: function(req, res, buf){
+        if (buf[0] !== 0x20) return
+        var err = new Error('no leading space')
+        err.status = 400
+        throw err
+      }})
+
+      request(server)
+      .post('/')
+      .set('Content-Type', 'application/x-www-form-urlencoded')
+      .send(' user=tobi')
+      .expect(400, 'no leading space', done)
+    })
+
+    it('should allow pass-through', function(done){
+      var server = createServer({verify: function(req, res, buf){
+        if (buf[0] === 0x5b) throw new Error('no arrays')
+      }})
+
+      request(server)
+      .post('/')
+      .set('Content-Type', 'application/x-www-form-urlencoded')
+      .send('user=tobi')
+      .expect(200, '{"user":"tobi"}', done)
+    })
+  })
+
+  describe('charset', function(){
+    var server;
+    before(function(){
+      server = createServer()
+    })
+
+    it('should parse utf-8', function(done){
+      var test = request(server).post('/')
+      test.set('Content-Type', 'application/x-www-form-urlencoded; charset=utf-8')
+      test.write(new Buffer('6e616d653de8aeba', 'hex'))
+      test.expect(200, '{"name":"论"}', done)
+    })
+
+    it('should parse when content-length != char length', function(done){
+      var test = request(server).post('/')
+      test.set('Content-Type', 'application/x-www-form-urlencoded; charset=utf-8')
+      test.set('Content-Length', '7')
+      test.write(new Buffer('746573743dc3a5', 'hex'))
+      test.expect(200, '{"test":"å"}', done)
+    })
+
+    it('should default to utf-8', function(done){
+      var test = request(server).post('/')
+      test.set('Content-Type', 'application/x-www-form-urlencoded')
+      test.write(new Buffer('6e616d653de8aeba', 'hex'))
+      test.expect(200, '{"name":"论"}', done)
+    })
+
+    it('should fail on unknown charset', function(done){
+      var test = request(server).post('/')
+      test.set('Content-Type', 'application/x-www-form-urlencoded; charset=koi8-r')
+      test.write(new Buffer('6e616d653dcec5d4', 'hex'))
+      test.expect(415, 'unsupported charset', done)
+    })
+  })
+
+  describe('encoding', function(){
+    var server;
+    before(function(){
+      server = createServer({ limit: '10kb' })
+    })
+
+    it('should parse without encoding', function(done){
+      var test = request(server).post('/')
+      test.set('Content-Type', 'application/x-www-form-urlencoded')
+      test.write(new Buffer('6e616d653de8aeba', 'hex'))
+      test.expect(200, '{"name":"论"}', done)
+    })
+
+    it('should support identity encoding', function(done){
+      var test = request(server).post('/')
+      test.set('Content-Encoding', 'identity')
+      test.set('Content-Type', 'application/x-www-form-urlencoded')
+      test.write(new Buffer('6e616d653de8aeba', 'hex'))
+      test.expect(200, '{"name":"论"}', done)
+    })
+
+    it('should support gzip encoding', function(done){
+      var test = request(server).post('/')
+      test.set('Content-Encoding', 'gzip')
+      test.set('Content-Type', 'application/x-www-form-urlencoded')
+      test.write(new Buffer('1f8b080000000000000bcb4bcc4db57db16e170099a4bad608000000', 'hex'))
+      test.expect(200, '{"name":"论"}', done)
+    })
+
+    it('should support deflate encoding', function(done){
+      var test = request(server).post('/')
+      test.set('Content-Encoding', 'deflate')
+      test.set('Content-Type', 'application/x-www-form-urlencoded')
+      test.write(new Buffer('789ccb4bcc4db57db16e17001068042f', 'hex'))
+      test.expect(200, '{"name":"论"}', done)
+    })
+
+    it('should fail on unknown encoding', function(done){
+      var test = request(server).post('/')
+      test.set('Content-Encoding', 'nulls')
+      test.set('Content-Type', 'application/x-www-form-urlencoded')
+      test.write(new Buffer('000000000000', 'hex'))
+      test.expect(415, 'unsupported content encoding', done)
+    })
+  })
+})
+
+function createServer(opts){
+  var _bodyParser = bodyParser.urlencoded(opts)
+
+  return http.createServer(function(req, res){
+    _bodyParser(req, res, function(err){
+      res.statusCode = err ? (err.status || 500) : 200;
+      res.end(err ? err.message : JSON.stringify(req.body));
+    })
+  })
+}

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/node-body-parser.git



More information about the Pkg-javascript-commits mailing list