[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