pax_global_header00006660000000000000000000000064124032474710014516gustar00rootroot0000000000000052 comment=df508da4f4c37ae6553638f95333b0ac1e8365cf body-parser-1.8.1/000077500000000000000000000000001240324747100137545ustar00rootroot00000000000000body-parser-1.8.1/.gitignore000066400000000000000000000000461240324747100157440ustar00rootroot00000000000000coverage/ node_modules/ npm-debug.log body-parser-1.8.1/.travis.yml000066400000000000000000000003711240324747100160660ustar00rootroot00000000000000language: 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@2.10.0 && cat ./coverage/lcov.info | coveralls" body-parser-1.8.1/HISTORY.md000066400000000000000000000100731240324747100154400ustar00rootroot000000000000001.8.1 / 2014-09-07 ================== * deps: media-typer@0.3.0 * deps: type-is@~1.5.1 1.8.0 / 2014-09-05 ================== * make empty-body-handling consistent between chunked requests - empty `json` produces `{}` - empty `raw` produces `new Buffer(0)` - empty `text` produces `''` - empty `urlencoded` produces `{}` * deps: qs@2.2.3 - Fix issue where first empty value in array is discarded * deps: type-is@~1.5.0 - fix `hasbody` to be true for `content-length: 0` 1.7.0 / 2014-09-01 ================== * add `parameterLimit` option to `urlencoded` parser * change `urlencoded` extended array limit to 100 * respond with 415 when over `parameterLimit` in `urlencoded` 1.6.7 / 2014-08-29 ================== * deps: qs@2.2.2 - Remove unnecessary cloning 1.6.6 / 2014-08-27 ================== * deps: qs@2.2.0 - Array parsing fix - Performance improvements 1.6.5 / 2014-08-16 ================== * deps: on-finished@2.1.0 1.6.4 / 2014-08-14 ================== * deps: qs@1.2.2 1.6.3 / 2014-08-10 ================== * deps: qs@1.2.1 1.6.2 / 2014-08-07 ================== * deps: qs@1.2.0 - Fix parsing array of objects 1.6.1 / 2014-08-06 ================== * deps: qs@1.1.0 - Accept urlencoded square brackets - Accept empty values in implicit array notation 1.6.0 / 2014-08-05 ================== * deps: qs@1.0.2 - Complete rewrite - Limits array length to 20 - Limits object depth to 5 - Limits parameters to 1,000 1.5.2 / 2014-07-27 ================== * deps: depd@0.4.4 - Work-around v8 generating empty stack traces 1.5.1 / 2014-07-26 ================== * deps: depd@0.4.3 - Fix exception when global `Error.stackTraceLimit` is too low 1.5.0 / 2014-07-20 ================== * deps: depd@0.4.2 - Add `TRACE_DEPRECATION` environment variable - Remove non-standard grey color from color output - Support `--no-deprecation` argument - Support `--trace-deprecation` argument * deps: iconv-lite@0.4.4 - Added encoding UTF-7 * deps: raw-body@1.3.0 - deps: iconv-lite@0.4.4 - Added encoding UTF-7 - Fix `Cannot switch to old mode now` error on Node.js 0.10+ * deps: type-is@~1.3.2 1.4.3 / 2014-06-19 ================== * deps: type-is@1.3.1 - fix global variable leak 1.4.2 / 2014-06-19 ================== * deps: type-is@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@1.2.2 - Support all encodings from `iconv-lite` 1.3.1 / 2014-06-11 ================== * deps: type-is@1.2.1 - Switch dependency from mime to mime-types@1.0.0 1.3.0 / 2014-05-31 ================== * add `extended` option to urlencoded parser 1.2.2 / 2014-05-27 ================== * deps: raw-body@1.1.6 - assert stream encoding on node.js 0.8 - assert stream encoding on node.js < 0.10.6 - deps: bytes@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@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 body-parser-1.8.1/LICENSE000066400000000000000000000022171240324747100147630ustar00rootroot00000000000000(The MIT License) Copyright (c) 2014 Jonathan Ong Copyright (c) 2014 Douglas Christopher Wilson 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. body-parser-1.8.1/README.md000066400000000000000000000162761240324747100152470ustar00rootroot00000000000000# body-parser [![NPM Version][npm-image]][npm-url] [![NPM Downloads][downloads-image]][downloads-url] [![Build Status][travis-image]][travis-url] [![Test Coverage][coveralls-image]][coveralls-url] [![Gittip][gittip-image]][gittip-url] 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({ extended: false })) // 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>`) - `parameterLimit` - maximum number of parameters. (default: `1000`) - `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 experience with urlencoded. For more information, please [see the qs library](https://www.npmjs.org/package/qs#readme). The `parameterLimit` argument controls the maximum number of parameters that are allowed in the urlencoded data. If a request contains more parameters than this value, a 415 will be returned to the client. 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 [MIT](LICENSE) [npm-image]: https://img.shields.io/npm/v/body-parser.svg?style=flat [npm-url]: https://npmjs.org/package/body-parser [travis-image]: https://img.shields.io/travis/expressjs/body-parser.svg?style=flat [travis-url]: https://travis-ci.org/expressjs/body-parser [coveralls-image]: https://img.shields.io/coveralls/expressjs/body-parser.svg?style=flat [coveralls-url]: https://coveralls.io/r/expressjs/body-parser?branch=master [downloads-image]: https://img.shields.io/npm/dm/body-parser.svg?style=flat [downloads-url]: https://npmjs.org/package/body-parser [gittip-image]: https://img.shields.io/gittip/dougwilson.svg?style=flat [gittip-url]: https://www.gittip.com/dougwilson/ body-parser-1.8.1/index.js000066400000000000000000000027611240324747100154270ustar00rootroot00000000000000/*! * body-parser * Copyright(c) 2014 Douglas Christopher Wilson * 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); }); } } body-parser-1.8.1/lib/000077500000000000000000000000001240324747100145225ustar00rootroot00000000000000body-parser-1.8.1/lib/read.js000066400000000000000000000052161240324747100157770ustar00rootroot00000000000000/*! * body-parser * Copyright(c) 2014 Douglas Christopher Wilson * MIT Licensed */ /** * Module dependencies. */ var getBody = require('raw-body') var iconv = require('iconv-lite') var onFinished = require('on-finished') 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 // 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 // read body getBody(stream, options, function (err, body) { if (err) { if (!err.status) { err.status = 400 } // read off entire request stream.resume() onFinished(req, function onfinished() { 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) { if (!err.status) { err.body = body err.status = 400 } return next(err) } next() }) } /** * 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 } body-parser-1.8.1/lib/types/000077500000000000000000000000001240324747100156665ustar00rootroot00000000000000body-parser-1.8.1/lib/types/json.js000066400000000000000000000042561240324747100172040ustar00rootroot00000000000000/*! * body-parser * Copyright(c) 2014 Jonathan Ong * Copyright(c) 2014 Douglas Christopher Wilson * 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 (body.length === 0) { // special-case empty json body, as it's a common client-side mistake // TODO: maybe make this configurable or part of "strict" option return {} } 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) { var match = firstcharRegExp.exec(str) return match ? match[1] : '' } body-parser-1.8.1/lib/types/raw.js000066400000000000000000000021711240324747100170160ustar00rootroot00000000000000/*! * body-parser * Copyright(c) 2014 Douglas Christopher Wilson * 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 }) } } body-parser-1.8.1/lib/types/text.js000066400000000000000000000024521240324747100172130ustar00rootroot00000000000000/*! * body-parser * Copyright(c) 2014 Douglas Christopher Wilson * 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 }) } } body-parser-1.8.1/lib/types/urlencoded.js000066400000000000000000000077071240324747100203630ustar00rootroot00000000000000/*! * body-parser * Copyright(c) 2014 Jonathan Ong * Copyright(c) 2014 Douglas Christopher Wilson * 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('undefined extended: provide extended option') } 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 ? extendedparser(options) : simpleparser(options) 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 the extended query parser. * * @param {object} options */ function extendedparser(options) { var parameterLimit = options.parameterLimit !== undefined ? options.parameterLimit : 1000 var parse = parser('qs') if (isNaN(parameterLimit) || parameterLimit < 1) { throw new TypeError('option parameterLimit must be a positive number') } if (isFinite(parameterLimit)) { parameterLimit = parameterLimit | 0 } var opts = { arrayLimit: 100, parameterLimit: parameterLimit } return function queryparse(body) { if (overlimit(body, parameterLimit)) { var err = new Error('too many parameters') err.status = 413 throw err } return parse(body, opts) } } /** * Determine if the parameter count is over the limit. * * @param {string} body * @param {number} limit * @api private */ function overlimit(body, limit) { if (limit === Infinity) { return false } var count = 0 var index = 0 while ((index = body.indexOf('&', index)) !== -1) { count++ index++ if (count === limit) { return true } } return false } /** * 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 } /** * Get the simple query parser. * * @param {object} options */ function simpleparser(options) { var parameterLimit = options.parameterLimit !== undefined ? options.parameterLimit : 1000 var parse = parser('querystring') if (isNaN(parameterLimit) || parameterLimit < 1) { throw new TypeError('option parameterLimit must be a positive number') } if (isFinite(parameterLimit)) { parameterLimit = parameterLimit | 0 } return function queryparse(body) { if (overlimit(body, parameterLimit)) { var err = new Error('too many parameters') err.status = 413 throw err } return parse(body, undefined, undefined, {maxKeys: parameterLimit}) } } body-parser-1.8.1/package.json000066400000000000000000000022411240324747100162410ustar00rootroot00000000000000{ "name": "body-parser", "description": "Node.js body parsing middleware", "version": "1.8.1", "contributors": [ "Douglas Christopher Wilson ", "Jonathan Ong (http://jongleberry.com)" ], "license": "MIT", "repository": "expressjs/body-parser", "dependencies": { "bytes": "1.0.0", "depd": "0.4.4", "iconv-lite": "0.4.4", "media-typer": "0.3.0", "on-finished": "2.1.0", "qs": "2.2.3", "raw-body": "1.3.0", "type-is": "~1.5.1" }, "devDependencies": { "istanbul": "0.3.2", "mocha": "~1.21.4", "should": "~4.0.4", "supertest": "~0.13.0" }, "files": [ "lib/", "LICENSE", "HISTORY.md", "index.js" ], "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/" } } body-parser-1.8.1/test/000077500000000000000000000000001240324747100147335ustar00rootroot00000000000000body-parser-1.8.1/test/body-parser.js000066400000000000000000000057271240324747100175330ustar00rootroot00000000000000 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)); }) }) } body-parser-1.8.1/test/json.js000066400000000000000000000332521240324747100162470ustar00rootroot00000000000000 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 empty message-body', function(done){ var server = createServer() request(server) .get('/') .set('Content-Type', 'application/json') .set('Transfer-Encoding', 'chunked') .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 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)); }) }) } body-parser-1.8.1/test/raw.js000066400000000000000000000210571240324747100160670ustar00rootroot00000000000000 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 Content-Length: 0', function(done){ request(server) .post('/') .set('Content-Type', 'application/octet-stream') .set('Content-Length', '0') .expect(200, 'buf:', 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)) }) }) } body-parser-1.8.1/test/support/000077500000000000000000000000001240324747100164475ustar00rootroot00000000000000body-parser-1.8.1/test/support/env.js000066400000000000000000000000541240324747100175740ustar00rootroot00000000000000 process.env.NO_DEPRECATION = 'body-parser' body-parser-1.8.1/test/text.js000066400000000000000000000227531240324747100162660ustar00rootroot00000000000000 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 Content-Length: 0', function(done){ var server = createServer({ limit: '1kb' }) request(server) .post('/') .set('Content-Type', 'text/plain') .set('Content-Length', '0') .expect(200, '""', 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('tobi') .expect(200, '"tobi"', 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)); }) }) } body-parser-1.8.1/test/urlencoded.js000066400000000000000000000402061240324747100174170ustar00rootroot00000000000000 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 Content-Length: 0', function(done){ request(server) .post('/') .set('Content-Type', 'application/x-www-form-urlencoded') .set('Content-Length', '0') .send('') .expect(200, '{}', 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) }) it('should parse fully-encoded extended syntax', function(done){ request(server) .post('/') .set('Content-Type', 'application/x-www-form-urlencoded') .send('user%5Bname%5D%5Bfirst%5D=Tobi') .expect(200, '{"user":{"name":{"first":"Tobi"}}}', done) }) it('should parse array of objects syntax', function(done){ request(server) .post('/') .set('Content-Type', 'application/x-www-form-urlencoded') .send('foo[0][bar]=baz&foo[0][fizz]=buzz') .expect(200, '{"foo":[{"bar":"baz","fizz":"buzz"}]}', 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 parameterLimit option', function () { describe('with extended: false', function () { it('should reject 0', function () { assert.throws(createServer.bind(null, { extended: false, parameterLimit: 0 }), /option parameterLimit/) }) it('should reject string', function () { assert.throws(createServer.bind(null, { extended: false, parameterLimit: 'beep' }), /option parameterLimit/) }) it('should 415 if over limit', function (done) { request(createServer({ extended: false, parameterLimit: 10 })) .post('/') .set('Content-Type', 'application/x-www-form-urlencoded') .send(createManyParams(11)) .expect(413, /too many parameters/, done) }) it('should work when at the limit', function (done) { request(createServer({ extended: false, parameterLimit: 10 })) .post('/') .set('Content-Type', 'application/x-www-form-urlencoded') .send(createManyParams(10)) .expect(expectKeyCount(10)) .expect(200, done) }) it('should work if number is floating point', function (done) { request(createServer({ extended: false, parameterLimit: 10.1 })) .post('/') .set('Content-Type', 'application/x-www-form-urlencoded') .send(createManyParams(11)) .expect(413, /too many parameters/, done) }) it('should work with large limit', function (done) { request(createServer({ extended: false, parameterLimit: 5000 })) .post('/') .set('Content-Type', 'application/x-www-form-urlencoded') .send(createManyParams(5000)) .expect(expectKeyCount(5000)) .expect(200, done) }) it('should work with Infinity limit', function (done) { request(createServer({ extended: false, parameterLimit: Infinity })) .post('/') .set('Content-Type', 'application/x-www-form-urlencoded') .send(createManyParams(10000)) .expect(expectKeyCount(10000)) .expect(200, done) }) }) describe('with extended: true', function () { it('should reject 0', function () { assert.throws(createServer.bind(null, { extended: true, parameterLimit: 0 }), /option parameterLimit/) }) it('should reject string', function () { assert.throws(createServer.bind(null, { extended: true, parameterLimit: 'beep' }), /option parameterLimit/) }) it('should 415 if over limit', function (done) { request(createServer({ extended: true, parameterLimit: 10 })) .post('/') .set('Content-Type', 'application/x-www-form-urlencoded') .send(createManyParams(11)) .expect(413, /too many parameters/, done) }) it('should work when at the limit', function (done) { request(createServer({ extended: true, parameterLimit: 10 })) .post('/') .set('Content-Type', 'application/x-www-form-urlencoded') .send(createManyParams(10)) .expect(expectKeyCount(10)) .expect(200, done) }) it('should work if number is floating point', function (done) { request(createServer({ extended: true, parameterLimit: 10.1 })) .post('/') .set('Content-Type', 'application/x-www-form-urlencoded') .send(createManyParams(11)) .expect(413, /too many parameters/, done) }) it('should work with large limit', function (done) { request(createServer({ extended: true, parameterLimit: 5000 })) .post('/') .set('Content-Type', 'application/x-www-form-urlencoded') .send(createManyParams(5000)) .expect(expectKeyCount(5000)) .expect(200, done) }) it('should work with Infinity limit', function (done) { request(createServer({ extended: true, parameterLimit: Infinity })) .post('/') .set('Content-Type', 'application/x-www-form-urlencoded') .send(createManyParams(10000)) .expect(expectKeyCount(10000)) .expect(200, 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 createManyParams(count) { var str = '' if (count === 0) { return str } str += '0=0' for (var i = 1; i < count; i++) { var n = i.toString(36) str += '&' + n + '=' + n } return str } 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)); }) }) } function expectKeyCount(count) { return function (res) { assert.equal(Object.keys(JSON.parse(res.text)).length, count) } }