From 9eb5ab4697d2b48d5d1bae08ff320ceeac2dc739 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=8D=C3=B1igo=20Marqu=C3=ADnez=20Prado?= <25435858+inigomarquinez@users.noreply.github.com> Date: Tue, 14 May 2024 18:26:06 +0200 Subject: [PATCH 01/26] chore: add support for OSSF scorecard reporting (#522) PR-URL: https://github.com/expressjs/body-parser/pull/522 --- .github/workflows/scorecard.yml | 69 +++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 .github/workflows/scorecard.yml diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml new file mode 100644 index 00000000..39372a22 --- /dev/null +++ b/.github/workflows/scorecard.yml @@ -0,0 +1,69 @@ +# This workflow uses actions that are not certified by GitHub. They are provided +# by a third-party and are governed by separate terms of service, privacy +# policy, and support documentation. + +name: Scorecard supply-chain security +on: + # For Branch-Protection check. Only the default branch is supported. See + # https://github.com/ossf/scorecard/blob/main/docs/checks.md#branch-protection + branch_protection_rule: + # To guarantee Maintained check is occasionally updated. See + # https://github.com/ossf/scorecard/blob/main/docs/checks.md#maintained + schedule: + - cron: '16 21 * * 1' + push: + branches: [ "master" ] + +# Declare default permissions as read only. +permissions: read-all + +jobs: + analysis: + name: Scorecard analysis + runs-on: ubuntu-latest + permissions: + # Needed to upload the results to code-scanning dashboard. + security-events: write + # Needed to publish results and get a badge (see publish_results below). + id-token: write + + steps: + - name: "Checkout code" + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.2 + with: + persist-credentials: false + + - name: "Run analysis" + uses: ossf/scorecard-action@0864cf19026789058feabb7e87baa5f140aac736 # v2.3.1 + with: + results_file: results.sarif + results_format: sarif + # (Optional) "write" PAT token. Uncomment the `repo_token` line below if: + # - you want to enable the Branch-Protection check on a *public* repository, or + # - you are installing Scorecard on a *private* repository + # To create the PAT, follow the steps in https://github.com/ossf/scorecard-action#authentication-with-pat. + # repo_token: ${{ secrets.SCORECARD_TOKEN }} + + # Public repositories: + # - Publish results to OpenSSF REST API for easy access by consumers + # - Allows the repository to include the Scorecard badge. + # - See https://github.com/ossf/scorecard-action#publishing-results. + # For private repositories: + # - `publish_results` will always be set to `false`, regardless + # of the value entered here. + publish_results: true + + # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF + # format to the repository Actions tab. + - name: "Upload artifact" + uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 + with: + name: SARIF file + path: results.sarif + retention-days: 5 + + # Upload the results to GitHub's code scanning dashboard. + - name: "Upload to code-scanning" + uses: github/codeql-action/upload-sarif@2f93e4319b2f04a2efc38fa7f78bd681bc3f7b2f # v2.23.2 + with: + sarif_file: results.sarif From 1c2f923b0bdac9c38518ad8e9a1b1c15b0d311d4 Mon Sep 17 00:00:00 2001 From: Shawn Dellysse Date: Tue, 21 Nov 2017 11:36:28 -0500 Subject: [PATCH 02/26] Added support for external parsers to bodyParser.json() --- README.md | 9 +++++++-- lib/types/json.js | 9 +++++---- package.json | 2 +- test/json.js | 11 +++++++++++ 4 files changed, 24 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index c9cbf023..7f16822c 100644 --- a/README.md +++ b/README.md @@ -87,16 +87,21 @@ specifies the number of bytes; if it is a string, the value is passed to the [bytes](https://www.npmjs.com/package/bytes) library for parsing. Defaults to `'100kb'`. +##### parser + +The `parser` option is the function called against the request body to convert +it to a Javascript object. Defaults to `JSON.parse`. + ##### reviver -The `reviver` option is passed directly to `JSON.parse` as the second +The `reviver` option is passed directly to the `parser` 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). ##### strict When set to `true`, will only accept arrays and objects; when `false` will -accept anything `JSON.parse` accepts. Defaults to `true`. +accept anything the `parser` accepts. Defaults to `true`. ##### type diff --git a/lib/types/json.js b/lib/types/json.js index 30bf8cab..11756231 100644 --- a/lib/types/json.js +++ b/lib/types/json.js @@ -62,6 +62,7 @@ function json (options) { var strict = opts.strict !== false var type = opts.type || 'application/json' var verify = opts.verify || false + var parser = opts.parser || JSON.parse if (verify !== false && typeof verify !== 'function') { throw new TypeError('option verify must be function') @@ -84,13 +85,13 @@ function json (options) { if (first !== '{' && first !== '[') { debug('strict violation') - throw createStrictSyntaxError(body, first) + throw createStrictSyntaxError(parser, body, first) } } try { debug('parse json') - return JSON.parse(body, reviver) + return parser(body, reviver) } catch (e) { throw normalizeJsonSyntaxError(e, { message: e.message, @@ -156,7 +157,7 @@ function json (options) { * @private */ -function createStrictSyntaxError (str, char) { +function createStrictSyntaxError (parser, str, char) { var index = str.indexOf(char) var partial = '' @@ -169,7 +170,7 @@ function createStrictSyntaxError (str, char) { } try { - JSON.parse(partial); /* istanbul ignore next */ throw new SyntaxError('strict violation') + parser(partial); /* istanbul ignore next */ throw new SyntaxError('strict violation') } catch (e) { return normalizeJsonSyntaxError(e, { message: e.message.replace(JSON_SYNTAX_REGEXP, function (placeholder) { diff --git a/package.json b/package.json index 5201dea5..8b3b070d 100644 --- a/package.json +++ b/package.json @@ -51,4 +51,4 @@ "test-ci": "nyc --reporter=lcov --reporter=text npm test", "test-cov": "nyc --reporter=html --reporter=text npm test" } -} +} \ No newline at end of file diff --git a/test/json.js b/test/json.js index 1040d56b..da4d77a1 100644 --- a/test/json.js +++ b/test/json.js @@ -5,6 +5,7 @@ var asyncHooks = tryRequire('async_hooks') var Buffer = require('safe-buffer').Buffer var http = require('http') var request = require('supertest') +var JSONbig = require('json-bigint') var bodyParser = require('..') @@ -99,6 +100,16 @@ describe('bodyParser.json()', function () { .expect(200, '{"user":"tobi"}', done) }) + it('should use external parsers', function (done) { + request(createServer({ + parser: JSONbig({ storeAsString: true }).parse + })) + .post('/') + .set('Content-Type', 'application/json') + .send('{"user_id":1234567890123456789012345678901234567890123456789012345678901234567890}') + .expect(200, '{"user_id":"1234567890123456789012345678901234567890123456789012345678901234567890"}', done) + }) + describe('when JSON is invalid', function () { before(function () { this.server = createServer() From 2f4913cdf61e01c4bc909195c1478aed1f5be648 Mon Sep 17 00:00:00 2001 From: Shawn Dellysse Date: Tue, 21 Nov 2017 11:54:20 -0500 Subject: [PATCH 03/26] removed test dependency on json-bigint --- package.json | 2 +- test/json.js | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 8b3b070d..c9b07949 100644 --- a/package.json +++ b/package.json @@ -1,4 +1,4 @@ -{ +j{ "name": "body-parser", "description": "Node.js body parsing middleware", "version": "2.0.0-beta.2", diff --git a/test/json.js b/test/json.js index da4d77a1..510faf7c 100644 --- a/test/json.js +++ b/test/json.js @@ -5,7 +5,6 @@ var asyncHooks = tryRequire('async_hooks') var Buffer = require('safe-buffer').Buffer var http = require('http') var request = require('supertest') -var JSONbig = require('json-bigint') var bodyParser = require('..') @@ -102,12 +101,14 @@ describe('bodyParser.json()', function () { it('should use external parsers', function (done) { request(createServer({ - parser: JSONbig({ storeAsString: true }).parse + parser: function (body) { + return { foo: "bar" } + } })) .post('/') .set('Content-Type', 'application/json') - .send('{"user_id":1234567890123456789012345678901234567890123456789012345678901234567890}') - .expect(200, '{"user_id":"1234567890123456789012345678901234567890123456789012345678901234567890"}', done) + .send('{"str":') + .expect(200, '{"foo":"bar"}', done) }) describe('when JSON is invalid', function () { From 6daefb5df6e3273f021cdef7bb496d2475a511c1 Mon Sep 17 00:00:00 2001 From: Shawn Dellysse Date: Tue, 21 Nov 2017 15:43:42 -0500 Subject: [PATCH 04/26] reworked doc to describe json parser() func better --- README.md | 12 +++++++++--- lib/types/json.js | 6 +++--- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 7f16822c..83d00507 100644 --- a/README.md +++ b/README.md @@ -90,12 +90,18 @@ to `'100kb'`. ##### parser The `parser` option is the function called against the request body to convert -it to a Javascript object. Defaults to `JSON.parse`. +it to a Javascript object. If a `reviver` is supplied, it is supplied as the +second argument to this function. + +```javascript +parser(body, reviver) -> req.body +``` + +Defaults to `JSON.parse`. ##### reviver -The `reviver` option is passed directly to the `parser` as the second -argument. You can find more information on this 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). ##### strict diff --git a/lib/types/json.js b/lib/types/json.js index 11756231..9332fcc8 100644 --- a/lib/types/json.js +++ b/lib/types/json.js @@ -85,7 +85,7 @@ function json (options) { if (first !== '{' && first !== '[') { debug('strict violation') - throw createStrictSyntaxError(parser, body, first) + throw createStrictSyntaxError(parser, reviver, body, first) } } @@ -157,7 +157,7 @@ function json (options) { * @private */ -function createStrictSyntaxError (parser, str, char) { +function createStrictSyntaxError (parser, reviver, str, char) { var index = str.indexOf(char) var partial = '' @@ -170,7 +170,7 @@ function createStrictSyntaxError (parser, str, char) { } try { - parser(partial); /* istanbul ignore next */ throw new SyntaxError('strict violation') + parser(partial, reviver); /* istanbul ignore next */ throw new SyntaxError('strict violation') } catch (e) { return normalizeJsonSyntaxError(e, { message: e.message.replace(JSON_SYNTAX_REGEXP, function (placeholder) { From b7402957988cbfea43ec0975570bda277e6d1110 Mon Sep 17 00:00:00 2001 From: Shawn Dellysse Date: Tue, 21 Nov 2017 15:45:41 -0500 Subject: [PATCH 05/26] added parser() option and doc for .text() --- README.md | 9 +++++++++ lib/types/text.js | 7 ++++++- test/text.js | 10 ++++++++++ 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 83d00507..ffad259a 100644 --- a/README.md +++ b/README.md @@ -220,6 +220,15 @@ The `verify` option, 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. +##### parser + +The `parser` option, if supplied, is used to transform the body of a request +before being set to `req.body`. + +```javascript +parser(body) -> req.body +``` + ### bodyParser.urlencoded([options]) Returns middleware that only parses `urlencoded` bodies and only looks at diff --git a/lib/types/text.js b/lib/types/text.js index b153931b..b2f57423 100644 --- a/lib/types/text.js +++ b/lib/types/text.js @@ -41,6 +41,7 @@ function text (options) { : opts.limit var type = opts.type || 'text/plain' var verify = opts.verify || false + var parser = opts.parser || defaultParser if (verify !== false && typeof verify !== 'function') { throw new TypeError('option verify must be function') @@ -52,7 +53,7 @@ function text (options) { : type function parse (buf) { - return buf + return parser(buf) } return function textParser (req, res, next) { @@ -95,6 +96,10 @@ function text (options) { } } +function defaultParser (buf) { + return buf; +} + /** * Get the charset of a request. * diff --git a/test/text.js b/test/text.js index ec35d9b4..61705e27 100644 --- a/test/text.js +++ b/test/text.js @@ -25,6 +25,16 @@ describe('bodyParser.text()', function () { .expect(200, '"user is tobi"', done) }) + it('should parse text/plain with a custom parser', function (done) { + request(createServer({ + parser: function (input) { return input.toUpperCase() } + })) + .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 textParser = bodyParser.text() var server = createServer(function (req, res, next) { From cf3a8e37a2e69becbf65d885381a5c31262e6e50 Mon Sep 17 00:00:00 2001 From: Shawn Dellysse Date: Tue, 21 Nov 2017 15:51:22 -0500 Subject: [PATCH 06/26] added parser() option and doc for .raw() --- README.md | 9 +++++++++ lib/types/raw.js | 7 ++++++- test/raw.js | 10 ++++++++++ 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index ffad259a..a07cff5f 100644 --- a/README.md +++ b/README.md @@ -171,6 +171,15 @@ The `verify` option, 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. +##### parser + +The `parser` option, if supplied, is used to transform the body of a request +before being set to `req.body`. + +```javascript +parser(body) -> req.body +``` + ### bodyParser.text([options]) Returns middleware that parses all bodies as a string and only looks at diff --git a/lib/types/raw.js b/lib/types/raw.js index bfe274cf..c1951a5f 100644 --- a/lib/types/raw.js +++ b/lib/types/raw.js @@ -39,6 +39,7 @@ function raw (options) { : opts.limit var type = opts.type || 'application/octet-stream' var verify = opts.verify || false + var parser = opts.parser || defaultParser if (verify !== false && typeof verify !== 'function') { throw new TypeError('option verify must be function') @@ -50,7 +51,7 @@ function raw (options) { : type function parse (buf) { - return buf + return parser(buf) } return function rawParser (req, res, next) { @@ -90,6 +91,10 @@ function raw (options) { } } +function defaultParser (buf) { + return buf; +} + /** * Get the simple type checker. * diff --git a/test/raw.js b/test/raw.js index fd2f3326..3e34e4a2 100644 --- a/test/raw.js +++ b/test/raw.js @@ -25,6 +25,16 @@ describe('bodyParser.raw()', function () { .expect(200, 'buf:746865207573657220697320746f6269', done) }) + it('should parse application/octet-stream with a custom parser', function (done) { + request(createServer({ + parser: function (body) { return body.toString("utf8") } + })) + .post('/') + .set('Content-Type', 'application/octet-stream') + .send('the user is tobi') + .expect(200, '"the user is tobi"', done) + }) + it('should 400 when invalid content-length', function (done) { var rawParser = bodyParser.raw() var server = createServer(function (req, res, next) { From 2468f724ce616ec7f200a22cb7c1a0ee398cf6e3 Mon Sep 17 00:00:00 2001 From: Shawn Dellysse Date: Tue, 21 Nov 2017 16:05:23 -0500 Subject: [PATCH 07/26] added parser() option and doc for .urlencoded() --- README.md | 10 ++++++++++ lib/types/urlencoded.js | 6 ++++-- test/urlencoded.js | 10 ++++++++++ 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index a07cff5f..f87b3ab9 100644 --- a/README.md +++ b/README.md @@ -302,6 +302,16 @@ The `verify` option, 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. +##### parser + +The `parser` option, if supplied, is used to in place of the default parser to +convert the request body into a Javascript object. If this option is supplied, +both the `extended` and `parameterLimit` options are ignored. + +```javascript +parser(body) -> req.body +``` + ## Errors The middlewares provided by this module create errors using the diff --git a/lib/types/urlencoded.js b/lib/types/urlencoded.js index f4ba2cd0..0cda49d5 100644 --- a/lib/types/urlencoded.js +++ b/lib/types/urlencoded.js @@ -56,9 +56,11 @@ function urlencoded (options) { } // create the appropriate query parser - var queryparse = extended + var parser = opts.parser || ( + extended ? extendedparser(opts) : simpleparser(opts) + ) // create the appropriate type checking function var shouldParse = typeof type !== 'function' @@ -67,7 +69,7 @@ function urlencoded (options) { function parse (body) { return body.length - ? queryparse(body) + ? parser(body) : {} } diff --git a/test/urlencoded.js b/test/urlencoded.js index 8be8a5a0..2475a1a7 100644 --- a/test/urlencoded.js +++ b/test/urlencoded.js @@ -25,6 +25,16 @@ describe('bodyParser.urlencoded()', function () { .expect(200, '{"user":"tobi"}', done) }) + it('should parse x-www-form-urlencoded with custom parser', function (done) { + request(createServer({ + parser: function (input) { return input.toUpperCase() } + })) + .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 urlencodedParser = bodyParser.urlencoded() var server = createServer(function (req, res, next) { From d75adee7c38df803bc60a2808acb97863eced8d4 Mon Sep 17 00:00:00 2001 From: Shawn Dellysse Date: Tue, 21 Nov 2017 16:10:37 -0500 Subject: [PATCH 08/26] cleanup to satisfy linter --- README.md | 8 ++++---- lib/types/raw.js | 2 +- lib/types/text.js | 2 +- test/json.js | 2 +- test/raw.js | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index f87b3ab9..ed94f1aa 100644 --- a/README.md +++ b/README.md @@ -93,7 +93,7 @@ The `parser` option is the function called against the request body to convert it to a Javascript object. If a `reviver` is supplied, it is supplied as the second argument to this function. -```javascript +``` parser(body, reviver) -> req.body ``` @@ -176,7 +176,7 @@ encoding of the request. The parsing can be aborted by throwing an error. The `parser` option, if supplied, is used to transform the body of a request before being set to `req.body`. -```javascript +``` parser(body) -> req.body ``` @@ -234,7 +234,7 @@ encoding of the request. The parsing can be aborted by throwing an error. The `parser` option, if supplied, is used to transform the body of a request before being set to `req.body`. -```javascript +``` parser(body) -> req.body ``` @@ -308,7 +308,7 @@ The `parser` option, if supplied, is used to in place of the default parser to convert the request body into a Javascript object. If this option is supplied, both the `extended` and `parameterLimit` options are ignored. -```javascript +``` parser(body) -> req.body ``` diff --git a/lib/types/raw.js b/lib/types/raw.js index c1951a5f..5710705e 100644 --- a/lib/types/raw.js +++ b/lib/types/raw.js @@ -92,7 +92,7 @@ function raw (options) { } function defaultParser (buf) { - return buf; + return buf } /** diff --git a/lib/types/text.js b/lib/types/text.js index b2f57423..e34d05b1 100644 --- a/lib/types/text.js +++ b/lib/types/text.js @@ -97,7 +97,7 @@ function text (options) { } function defaultParser (buf) { - return buf; + return buf } /** diff --git a/test/json.js b/test/json.js index 510faf7c..c2f82d56 100644 --- a/test/json.js +++ b/test/json.js @@ -102,7 +102,7 @@ describe('bodyParser.json()', function () { it('should use external parsers', function (done) { request(createServer({ parser: function (body) { - return { foo: "bar" } + return { foo: 'bar' } } })) .post('/') diff --git a/test/raw.js b/test/raw.js index 3e34e4a2..2734aed2 100644 --- a/test/raw.js +++ b/test/raw.js @@ -27,7 +27,7 @@ describe('bodyParser.raw()', function () { it('should parse application/octet-stream with a custom parser', function (done) { request(createServer({ - parser: function (body) { return body.toString("utf8") } + parser: function (body) { return body.toString('utf8') } })) .post('/') .set('Content-Type', 'application/octet-stream') From 8224cda5a24a81a8174d0c7c8fab6dc583f78afa Mon Sep 17 00:00:00 2001 From: Shawn Dellysse Date: Tue, 21 Nov 2017 18:07:58 -0500 Subject: [PATCH 09/26] added generic parser --- lib/generic-parser.js | 156 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 156 insertions(+) create mode 100644 lib/generic-parser.js diff --git a/lib/generic-parser.js b/lib/generic-parser.js new file mode 100644 index 00000000..858303d8 --- /dev/null +++ b/lib/generic-parser.js @@ -0,0 +1,156 @@ +/*! + * body-parser + * Copyright(c) 2014 Jonathan Ong + * Copyright(c) 2014-2015 Douglas Christopher Wilson + * MIT Licensed + */ + +'use strict' + +/** + * Module dependencies. + * @private + */ + +var bytes = require('bytes') +var contentType = require('content-type') +var createError = require('http-errors') +var debug = require('debug')('body-parser:generic') +var read = require('./read') +var typeis = require('type-is') + +/** + * Module exports. + */ + +module.exports = generic + + +/** + * Create a middleware to parse JSON bodies. + * + * @param {object} [options] + * @return {function} + * @public + */ + +function generic (options) { + var opts = options || {} + + var limit = typeof opts.limit !== 'number' + ? bytes.parse(opts.limit || '100kb') + : opts.limit + var charset = opts.charset + var inflate = opts.inflate !== false + var verify = opts.verify || false + var parse = opts.parse || defaultParse + var defaultReqCharset = opts.defaultCharset || 'utf-8' + var type = opts.type + + if (verify !== false && typeof verify !== 'function') { + throw new TypeError('option verify must be function') + } + + // create the appropriate type checking function + var shouldParse = typeof type !== 'function' + ? typeChecker(type) + : type + + // create the appropriate charset validating function + var validCharset = typeof charset !== "function" + ? charsetValidator(charset) + : charset + + return function genericParser (req, res, next) { + if (req._body) { + debug('body already parsed') + next() + return + } + + req.body = req.body || {} + + // skip requests without bodies + if (!typeis.hasBody(req)) { + debug('skip empty body') + next() + return + } + + debug('content-type %j', req.headers['content-type']) + + // determine if request should be parsed + if (!shouldParse(req)) { + debug('skip parsing') + next() + return + } + + // assert charset per RFC 7159 sec 8.1 + var reqCharset = null + if (charset !== undefined) { + reqCharset = getCharset(req) || defaultReqCharset + if (!validCharset(reqCharset)) { + debug('invalid charset') + next(createError(415, 'unsupported charset "' + reqCharset.toUpperCase() + '"', { + charset: reqCharset, + type: 'charset.unsupported' + })) + return + } + } + + // read + read(req, res, next, parse, debug, { + encoding: reqCharset, + inflate: inflate, + limit: limit, + verify: verify + }) + } +} + +function defaultParse (buf) { + return buf +} + +/** + * Get the charset of a request. + * + * @param {object} req + * @api private + */ + +function getCharset (req) { + try { + return (contentType.parse(req).parameters.charset || '').toLowerCase() + } catch (e) { + return undefined + } +} + +/** + * Get the simple type checker. + * + * @param {string} type + * @return {function} + */ + +function typeChecker (type) { + return function checkType (req) { + return Boolean(typeis(req, type)) + } +} + +/** + * Get the simple charset validator. + * + * @param {string} type + * @return {function} + */ + +function charsetValidator (charset) { + return function validateCharset (reqCharset) { + return charset === reqCharset + } +} From a5adc8213259fe8d8c51874fc82489bb4bfc0c70 Mon Sep 17 00:00:00 2001 From: Shawn Dellysse Date: Tue, 21 Nov 2017 18:08:56 -0500 Subject: [PATCH 10/26] converted json parser to use generic parser --- lib/types/json.js | 146 +++++++++------------------------------------- 1 file changed, 26 insertions(+), 120 deletions(-) diff --git a/lib/types/json.js b/lib/types/json.js index 9332fcc8..2220524e 100644 --- a/lib/types/json.js +++ b/lib/types/json.js @@ -12,13 +12,9 @@ * @private */ -var bytes = require('bytes') -var contentType = require('content-type') -var createError = require('http-errors') +var assign = require('object-assign') +var genericParser = require('../generic-parser') var debug = require('debug')('body-parser:json') -var isFinished = require('on-finished').isFinished -var read = require('../read') -var typeis = require('type-is') /** * Module exports. @@ -51,101 +47,39 @@ var JSON_SYNTAX_REGEXP = /#+/g * @public */ -function json (options) { +function json(options) { var opts = options || {} - var limit = typeof opts.limit !== 'number' - ? bytes.parse(opts.limit || '100kb') - : opts.limit - var inflate = opts.inflate !== false var reviver = opts.reviver var strict = opts.strict !== false - var type = opts.type || 'application/json' - var verify = opts.verify || false var parser = opts.parser || JSON.parse + var type = opts.type || 'application/json' - if (verify !== false && typeof verify !== 'function') { - throw new TypeError('option verify must be function') - } - - // create the appropriate type checking function - var shouldParse = typeof type !== 'function' - ? typeChecker(type) - : type - - 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 {} - } + return genericParser(assign({}, opts, { + type: type, - if (strict) { - var first = firstchar(body) + charset: function validateCharset(charset) { + return charset.slice(0, 4) === 'utf-' + }, - if (first !== '{' && first !== '[') { - debug('strict violation') - throw createStrictSyntaxError(parser, reviver, body, first) + parse: function parse(buf) { + if (buf.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 {} } - } - - try { - debug('parse json') - return parser(body, reviver) - } catch (e) { - throw normalizeJsonSyntaxError(e, { - message: e.message, - stack: e.stack - }) - } - } - return function jsonParser (req, res, next) { - if (isFinished(req)) { - debug('body already parsed') - next() - return - } - - if (!('body' in req)) { - req.body = undefined - } - - // skip requests without bodies - if (!typeis.hasBody(req)) { - debug('skip empty body') - next() - return - } - - debug('content-type %j', req.headers['content-type']) - - // determine if request should be parsed - if (!shouldParse(req)) { - debug('skip parsing') - next() - return - } - - // assert charset per RFC 7159 sec 8.1 - var charset = getCharset(req) || 'utf-8' - if (charset.slice(0, 4) !== 'utf-') { - debug('invalid charset') - next(createError(415, 'unsupported charset "' + charset.toUpperCase() + '"', { - charset: charset, - type: 'charset.unsupported' - })) - return + try { + debug('parse json') + return parser(body, reviver) + } catch (e) { + throw normalizeJsonSyntaxError(e, { + message: e.message, + stack: e.stack + }) + } } - - // read - read(req, res, next, parse, debug, { - encoding: charset, - inflate: inflate, - limit: limit, - verify: verify - }) - } + })) } /** @@ -157,7 +91,7 @@ function json (options) { * @private */ -function createStrictSyntaxError (parser, reviver, str, char) { +function createStrictSyntaxError(parser, reviver, str, char) { var index = str.indexOf(char) var partial = '' @@ -197,21 +131,6 @@ function firstchar (str) { : undefined } -/** - * Get the charset of a request. - * - * @param {object} req - * @api private - */ - -function getCharset (req) { - try { - return (contentType.parse(req).parameters.charset || '').toLowerCase() - } catch (e) { - return undefined - } -} - /** * Normalize a SyntaxError for JSON.parse. * @@ -220,7 +139,7 @@ function getCharset (req) { * @return {SyntaxError} */ -function normalizeJsonSyntaxError (error, obj) { +function normalizeJsonSyntaxError(error, obj) { var keys = Object.getOwnPropertyNames(error) for (var i = 0; i < keys.length; i++) { @@ -236,16 +155,3 @@ function normalizeJsonSyntaxError (error, obj) { return error } - -/** - * Get the simple type checker. - * - * @param {string} type - * @return {function} - */ - -function typeChecker (type) { - return function checkType (req) { - return Boolean(typeis(req, type)) - } -} From c572330a554941183614b1692f48182ffaa3899a Mon Sep 17 00:00:00 2001 From: Shawn Dellysse Date: Tue, 21 Nov 2017 18:10:01 -0500 Subject: [PATCH 11/26] converted raw parser to use generic parser --- lib/generic-parser.js | 7 ++-- lib/types/raw.js | 81 +++---------------------------------------- test/raw.js | 10 ------ 3 files changed, 10 insertions(+), 88 deletions(-) diff --git a/lib/generic-parser.js b/lib/generic-parser.js index 858303d8..92dab429 100644 --- a/lib/generic-parser.js +++ b/lib/generic-parser.js @@ -16,6 +16,7 @@ var bytes = require('bytes') var contentType = require('content-type') var createError = require('http-errors') var debug = require('debug')('body-parser:generic') +var isFinished = require('on-finished').isFinished var read = require('./read') var typeis = require('type-is') @@ -62,13 +63,15 @@ function generic (options) { : charset return function genericParser (req, res, next) { - if (req._body) { + if (isFinished(req)) { debug('body already parsed') next() return } - req.body = req.body || {} + if (!('body' in req)) { + req.body = undefined + } // skip requests without bodies if (!typeis.hasBody(req)) { diff --git a/lib/types/raw.js b/lib/types/raw.js index 5710705e..0e8b359c 100644 --- a/lib/types/raw.js +++ b/lib/types/raw.js @@ -10,11 +10,8 @@ * Module dependencies. */ -var bytes = require('bytes') -var debug = require('debug')('body-parser:raw') -var isFinished = require('on-finished').isFinished -var read = require('../read') -var typeis = require('type-is') +var assign = require('object-assign') +var genericParser = require('../generic-parser') /** * Module exports. @@ -33,77 +30,9 @@ module.exports = raw function raw (options) { var opts = options || {} - var inflate = opts.inflate !== false - var limit = typeof opts.limit !== 'number' - ? bytes.parse(opts.limit || '100kb') - : opts.limit var type = opts.type || 'application/octet-stream' - var verify = opts.verify || false - var parser = opts.parser || defaultParser - if (verify !== false && typeof verify !== 'function') { - throw new TypeError('option verify must be function') - } - - // create the appropriate type checking function - var shouldParse = typeof type !== 'function' - ? typeChecker(type) - : type - - function parse (buf) { - return parser(buf) - } - - return function rawParser (req, res, next) { - if (isFinished(req)) { - debug('body already parsed') - next() - return - } - - if (!('body' in req)) { - req.body = undefined - } - - // skip requests without bodies - if (!typeis.hasBody(req)) { - debug('skip empty body') - next() - return - } - - debug('content-type %j', req.headers['content-type']) - - // determine if request should be parsed - if (!shouldParse(req)) { - debug('skip parsing') - next() - return - } - - // read - read(req, res, next, parse, debug, { - encoding: null, - inflate: inflate, - limit: limit, - verify: verify - }) - } -} - -function defaultParser (buf) { - return buf -} - -/** - * Get the simple type checker. - * - * @param {string} type - * @return {function} - */ - -function typeChecker (type) { - return function checkType (req) { - return Boolean(typeis(req, type)) - } + return genericParser(assign({}, opts, { + type: type + })) } diff --git a/test/raw.js b/test/raw.js index 2734aed2..fd2f3326 100644 --- a/test/raw.js +++ b/test/raw.js @@ -25,16 +25,6 @@ describe('bodyParser.raw()', function () { .expect(200, 'buf:746865207573657220697320746f6269', done) }) - it('should parse application/octet-stream with a custom parser', function (done) { - request(createServer({ - parser: function (body) { return body.toString('utf8') } - })) - .post('/') - .set('Content-Type', 'application/octet-stream') - .send('the user is tobi') - .expect(200, '"the user is tobi"', done) - }) - it('should 400 when invalid content-length', function (done) { var rawParser = bodyParser.raw() var server = createServer(function (req, res, next) { From 7390c89b5cc6bfb6e4a49ac556d1427e8ab6768f Mon Sep 17 00:00:00 2001 From: Shawn Dellysse Date: Tue, 21 Nov 2017 18:10:46 -0500 Subject: [PATCH 12/26] converted text parser to use generic parser --- lib/types/text.js | 102 ++++------------------------------------------ test/text.js | 10 ----- 2 files changed, 7 insertions(+), 105 deletions(-) diff --git a/lib/types/text.js b/lib/types/text.js index e34d05b1..2956684e 100644 --- a/lib/types/text.js +++ b/lib/types/text.js @@ -10,12 +10,8 @@ * Module dependencies. */ -var bytes = require('bytes') -var contentType = require('content-type') -var debug = require('debug')('body-parser:text') -var isFinished = require('on-finished').isFinished -var read = require('../read') -var typeis = require('type-is') +var assign = require('object-assign') +var genericParser = require('../generic-parser') /** * Module exports. @@ -35,95 +31,11 @@ function text (options) { var opts = options || {} var defaultCharset = opts.defaultCharset || 'utf-8' - var inflate = opts.inflate !== false - var limit = typeof opts.limit !== 'number' - ? bytes.parse(opts.limit || '100kb') - : opts.limit var type = opts.type || 'text/plain' - var verify = opts.verify || false - var parser = opts.parser || defaultParser - if (verify !== false && typeof verify !== 'function') { - throw new TypeError('option verify must be function') - } - - // create the appropriate type checking function - var shouldParse = typeof type !== 'function' - ? typeChecker(type) - : type - - function parse (buf) { - return parser(buf) - } - - return function textParser (req, res, next) { - if (isFinished(req)) { - debug('body already parsed') - next() - return - } - - if (!('body' in req)) { - req.body = undefined - } - - // skip requests without bodies - if (!typeis.hasBody(req)) { - debug('skip empty body') - next() - return - } - - debug('content-type %j', req.headers['content-type']) - - // determine if request should be parsed - if (!shouldParse(req)) { - debug('skip parsing') - next() - return - } - - // get charset - var charset = getCharset(req) || defaultCharset - - // read - read(req, res, next, parse, debug, { - encoding: charset, - inflate: inflate, - limit: limit, - verify: verify - }) - } -} - -function defaultParser (buf) { - return buf -} - -/** - * Get the charset of a request. - * - * @param {object} req - * @api private - */ - -function getCharset (req) { - try { - return (contentType.parse(req).parameters.charset || '').toLowerCase() - } catch (e) { - return undefined - } -} - -/** - * Get the simple type checker. - * - * @param {string} type - * @return {function} - */ - -function typeChecker (type) { - return function checkType (req) { - return Boolean(typeis(req, type)) - } + return genericParser(assign({}, opts, { + type: type, + charset: function validateCharset () { return true }, + defaultCharset: defaultCharset + })) } diff --git a/test/text.js b/test/text.js index 61705e27..ec35d9b4 100644 --- a/test/text.js +++ b/test/text.js @@ -25,16 +25,6 @@ describe('bodyParser.text()', function () { .expect(200, '"user is tobi"', done) }) - it('should parse text/plain with a custom parser', function (done) { - request(createServer({ - parser: function (input) { return input.toUpperCase() } - })) - .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 textParser = bodyParser.text() var server = createServer(function (req, res, next) { From f4f9d843e1051c68bbce3825b9cc5de3516d4453 Mon Sep 17 00:00:00 2001 From: Shawn Dellysse Date: Tue, 21 Nov 2017 18:11:47 -0500 Subject: [PATCH 13/26] converted urlencoded parser to use generic parser --- lib/types/urlencoded.js | 94 ++++++----------------------------------- 1 file changed, 12 insertions(+), 82 deletions(-) diff --git a/lib/types/urlencoded.js b/lib/types/urlencoded.js index 0cda49d5..ffcd765e 100644 --- a/lib/types/urlencoded.js +++ b/lib/types/urlencoded.js @@ -12,13 +12,10 @@ * @private */ -var bytes = require('bytes') -var contentType = require('content-type') +var assign = require('object-assign') var createError = require('http-errors') var debug = require('debug')('body-parser:urlencoded') -var isFinished = require('on-finished').isFinished -var read = require('../read') -var typeis = require('type-is') +var genericParser = require('../generic-parser.js') /** * Module exports. @@ -39,7 +36,6 @@ var parsers = Object.create(null) * @return {function} * @public */ - function urlencoded (options) { var opts = options || {} @@ -49,77 +45,24 @@ function urlencoded (options) { ? bytes.parse(opts.limit || '100kb') : opts.limit var type = opts.type || 'application/x-www-form-urlencoded' - var verify = opts.verify || false - - if (verify !== false && typeof verify !== 'function') { - throw new TypeError('option verify must be function') - } + var charset = opts.charset || 'utf-8' - // create the appropriate query parser - var parser = opts.parser || ( + var queryparse = opts.parser || ( extended ? extendedparser(opts) : simpleparser(opts) ) - // create the appropriate type checking function - var shouldParse = typeof type !== 'function' - ? typeChecker(type) - : type - - function parse (body) { - return body.length - ? parser(body) - : {} - } - - return function urlencodedParser (req, res, next) { - if (isFinished(req)) { - debug('body already parsed') - next() - return - } + return genericParser(assign({}, opts, { + type: type, + charset: charset, - if (!('body' in req)) { - req.body = undefined + parse: function parse (buf) { + return buf.length + ? queryparse(buf) + : {} } - - // skip requests without bodies - if (!typeis.hasBody(req)) { - debug('skip empty body') - next() - return - } - - debug('content-type %j', req.headers['content-type']) - - // determine if request should be parsed - if (!shouldParse(req)) { - debug('skip parsing') - next() - return - } - - // assert charset - var charset = getCharset(req) || 'utf-8' - if (charset !== 'utf-8') { - debug('invalid charset') - next(createError(415, 'unsupported charset "' + charset.toUpperCase() + '"', { - charset: charset, - type: 'charset.unsupported' - })) - return - } - - // read - read(req, res, next, parse, debug, { - debug: debug, - encoding: charset, - inflate: inflate, - limit: limit, - verify: verify - }) - } + })) } /** @@ -268,16 +211,3 @@ function simpleparser (options) { return parse(body, undefined, undefined, { maxKeys: parameterLimit }) } } - -/** - * Get the simple type checker. - * - * @param {string} type - * @return {function} - */ - -function typeChecker (type) { - return function checkType (req) { - return Boolean(typeis(req, type)) - } -} From 10eb0af5dad77bc80770617bdbe84e041d291965 Mon Sep 17 00:00:00 2001 From: Shawn Dellysse Date: Tue, 21 Nov 2017 18:13:11 -0500 Subject: [PATCH 14/26] cleanup / fix linter warnings --- lib/generic-parser.js | 3 +-- lib/types/urlencoded.js | 15 --------------- 2 files changed, 1 insertion(+), 17 deletions(-) diff --git a/lib/generic-parser.js b/lib/generic-parser.js index 92dab429..8ddc52d4 100644 --- a/lib/generic-parser.js +++ b/lib/generic-parser.js @@ -26,7 +26,6 @@ var typeis = require('type-is') module.exports = generic - /** * Create a middleware to parse JSON bodies. * @@ -58,7 +57,7 @@ function generic (options) { : type // create the appropriate charset validating function - var validCharset = typeof charset !== "function" + var validCharset = typeof charset !== 'function' ? charsetValidator(charset) : charset diff --git a/lib/types/urlencoded.js b/lib/types/urlencoded.js index ffcd765e..f8f17094 100644 --- a/lib/types/urlencoded.js +++ b/lib/types/urlencoded.js @@ -107,21 +107,6 @@ function extendedparser (options) { } } -/** - * Get the charset of a request. - * - * @param {object} req - * @api private - */ - -function getCharset (req) { - try { - return (contentType.parse(req).parameters.charset || '').toLowerCase() - } catch (e) { - return undefined - } -} - /** * Count the number of parameters, stopping once limit reached * From 67060cac3d3f76f1c5bd34d14b269b274c55a2d1 Mon Sep 17 00:00:00 2001 From: Shawn Dellysse Date: Tue, 21 Nov 2017 18:15:15 -0500 Subject: [PATCH 15/26] removed items from README --- README.md | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/README.md b/README.md index ed94f1aa..60528082 100644 --- a/README.md +++ b/README.md @@ -171,15 +171,6 @@ The `verify` option, 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. -##### parser - -The `parser` option, if supplied, is used to transform the body of a request -before being set to `req.body`. - -``` -parser(body) -> req.body -``` - ### bodyParser.text([options]) Returns middleware that parses all bodies as a string and only looks at @@ -229,15 +220,6 @@ The `verify` option, 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. -##### parser - -The `parser` option, if supplied, is used to transform the body of a request -before being set to `req.body`. - -``` -parser(body) -> req.body -``` - ### bodyParser.urlencoded([options]) Returns middleware that only parses `urlencoded` bodies and only looks at From e6f600468e3928dc3dee97dfff9bd854e3d553f0 Mon Sep 17 00:00:00 2001 From: Shawn Dellysse Date: Tue, 21 Nov 2017 18:18:10 -0500 Subject: [PATCH 16/26] added bodyParser.generic() getter --- index.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/index.js b/index.js index 81fb9046..18b81d70 100644 --- a/index.js +++ b/index.js @@ -73,6 +73,17 @@ Object.defineProperty(exports, 'urlencoded', { get: createParserGetter('urlencoded') }) +/** + * Generic parser used to build parsers. + * @public + */ + +Object.defineProperty(exports, 'generic', { + configurable: true, + enumerable: true, + get: createParserGetter('generic') +}) + /** * Create a middleware to parse json and urlencoded bodies. * @@ -123,6 +134,9 @@ function loadParser (parserName) { case 'urlencoded': parser = require('./lib/types/urlencoded') break + case 'generic': + parser = require('./lib/generic-parser') + break } // store to prevent invoking require() From 07e0602599f29025abaea86712ab869037915716 Mon Sep 17 00:00:00 2001 From: Shawn Dellysse Date: Tue, 21 Nov 2017 18:24:16 -0500 Subject: [PATCH 17/26] cleanup / fix linter warnings --- index.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/index.js b/index.js index 18b81d70..b6bdf9f9 100644 --- a/index.js +++ b/index.js @@ -134,9 +134,9 @@ function loadParser (parserName) { case 'urlencoded': parser = require('./lib/types/urlencoded') break - case 'generic': - parser = require('./lib/generic-parser') - break + case 'generic': + parser = require('./lib/generic-parser') + break } // store to prevent invoking require() From bb7697a39a8797b271d7f80e75eedbc975e66c9d Mon Sep 17 00:00:00 2001 From: S Dellysse Date: Thu, 16 Apr 2020 23:38:37 -0400 Subject: [PATCH 18/26] fixed tests after rebase --- lib/types/json.js | 11 ++++++++++- package.json | 4 ++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/lib/types/json.js b/lib/types/json.js index 2220524e..2261d88d 100644 --- a/lib/types/json.js +++ b/lib/types/json.js @@ -69,9 +69,18 @@ function json(options) { return {} } + if (strict) { + var first = firstchar(buf) + + if (first !== '{' && first !== '[') { + debug('strict violation') + throw createStrictSyntaxError(parser, reviver, buf, first) + } + } + try { debug('parse json') - return parser(body, reviver) + return parser(buf, reviver) } catch (e) { throw normalizeJsonSyntaxError(e, { message: e.message, diff --git a/package.json b/package.json index c9b07949..5201dea5 100644 --- a/package.json +++ b/package.json @@ -1,4 +1,4 @@ -j{ +{ "name": "body-parser", "description": "Node.js body parsing middleware", "version": "2.0.0-beta.2", @@ -51,4 +51,4 @@ j{ "test-ci": "nyc --reporter=lcov --reporter=text npm test", "test-cov": "nyc --reporter=html --reporter=text npm test" } -} \ No newline at end of file +} From 6a7c24daa17133616b367ad9e1b63bc6f99b47ea Mon Sep 17 00:00:00 2001 From: S Dellysse Date: Thu, 16 Apr 2020 23:50:44 -0400 Subject: [PATCH 19/26] satisfying linter --- lib/types/json.js | 10 +++++----- lib/types/urlencoded.js | 4 ++-- package.json | 2 +- test/json.js | 8 ++++---- test/urlencoded.js | 8 ++++---- 5 files changed, 16 insertions(+), 16 deletions(-) diff --git a/lib/types/json.js b/lib/types/json.js index 2261d88d..f949382f 100644 --- a/lib/types/json.js +++ b/lib/types/json.js @@ -47,7 +47,7 @@ var JSON_SYNTAX_REGEXP = /#+/g * @public */ -function json(options) { +function json (options) { var opts = options || {} var reviver = opts.reviver @@ -58,11 +58,11 @@ function json(options) { return genericParser(assign({}, opts, { type: type, - charset: function validateCharset(charset) { + charset: function validateCharset (charset) { return charset.slice(0, 4) === 'utf-' }, - parse: function parse(buf) { + parse: function parse (buf) { if (buf.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 @@ -100,7 +100,7 @@ function json(options) { * @private */ -function createStrictSyntaxError(parser, reviver, str, char) { +function createStrictSyntaxError (parser, reviver, str, char) { var index = str.indexOf(char) var partial = '' @@ -148,7 +148,7 @@ function firstchar (str) { * @return {SyntaxError} */ -function normalizeJsonSyntaxError(error, obj) { +function normalizeJsonSyntaxError (error, obj) { var keys = Object.getOwnPropertyNames(error) for (var i = 0; i < keys.length; i++) { diff --git a/lib/types/urlencoded.js b/lib/types/urlencoded.js index f8f17094..a9e9bc97 100644 --- a/lib/types/urlencoded.js +++ b/lib/types/urlencoded.js @@ -49,8 +49,8 @@ function urlencoded (options) { var queryparse = opts.parser || ( extended - ? extendedparser(opts) - : simpleparser(opts) + ? extendedparser(opts) + : simpleparser(opts) ) return genericParser(assign({}, opts, { diff --git a/package.json b/package.json index 5201dea5..8b3b070d 100644 --- a/package.json +++ b/package.json @@ -51,4 +51,4 @@ "test-ci": "nyc --reporter=lcov --reporter=text npm test", "test-cov": "nyc --reporter=html --reporter=text npm test" } -} +} \ No newline at end of file diff --git a/test/json.js b/test/json.js index c2f82d56..0a069c1f 100644 --- a/test/json.js +++ b/test/json.js @@ -105,10 +105,10 @@ describe('bodyParser.json()', function () { return { foo: 'bar' } } })) - .post('/') - .set('Content-Type', 'application/json') - .send('{"str":') - .expect(200, '{"foo":"bar"}', done) + .post('/') + .set('Content-Type', 'application/json') + .send('{"str":') + .expect(200, '{"foo":"bar"}', done) }) describe('when JSON is invalid', function () { diff --git a/test/urlencoded.js b/test/urlencoded.js index 2475a1a7..c22bab71 100644 --- a/test/urlencoded.js +++ b/test/urlencoded.js @@ -29,10 +29,10 @@ describe('bodyParser.urlencoded()', function () { request(createServer({ parser: function (input) { return input.toUpperCase() } })) - .post('/') - .set('Content-Type', 'application/x-www-form-urlencoded') - .send('user=tobi') - .expect(200, '"USER=TOBI"', done) + .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) { From bc7454b5e26b548ec2dd9ac69764ce9203ebe8ba Mon Sep 17 00:00:00 2001 From: S Dellysse Date: Thu, 16 Apr 2020 23:57:49 -0400 Subject: [PATCH 20/26] Ref'd genParser via the bodyparser getter to signal how third party parsers should import genParser' --- lib/types/json.js | 2 +- lib/types/raw.js | 2 +- lib/types/text.js | 2 +- lib/types/urlencoded.js | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/types/json.js b/lib/types/json.js index f949382f..e8b233af 100644 --- a/lib/types/json.js +++ b/lib/types/json.js @@ -13,7 +13,7 @@ */ var assign = require('object-assign') -var genericParser = require('../generic-parser') +var genericParser = require('../..').generic var debug = require('debug')('body-parser:json') /** diff --git a/lib/types/raw.js b/lib/types/raw.js index 0e8b359c..f6120aaa 100644 --- a/lib/types/raw.js +++ b/lib/types/raw.js @@ -11,7 +11,7 @@ */ var assign = require('object-assign') -var genericParser = require('../generic-parser') +var genericParser = require('../..').generic /** * Module exports. diff --git a/lib/types/text.js b/lib/types/text.js index 2956684e..36405a1a 100644 --- a/lib/types/text.js +++ b/lib/types/text.js @@ -11,7 +11,7 @@ */ var assign = require('object-assign') -var genericParser = require('../generic-parser') +var genericParser = require('../..').generic /** * Module exports. diff --git a/lib/types/urlencoded.js b/lib/types/urlencoded.js index a9e9bc97..b101069b 100644 --- a/lib/types/urlencoded.js +++ b/lib/types/urlencoded.js @@ -15,7 +15,7 @@ var assign = require('object-assign') var createError = require('http-errors') var debug = require('debug')('body-parser:urlencoded') -var genericParser = require('../generic-parser.js') +var genericParser = require('../..').generic /** * Module exports. From 519f306a649b677b77cd4467b332bc64c364b3fb Mon Sep 17 00:00:00 2001 From: S Dellysse Date: Fri, 17 Apr 2020 00:40:36 -0400 Subject: [PATCH 21/26] removed dep on object-assign, which didnt support node < 0.10 --- lib/generic-parser.js | 17 +++++++++++++++-- lib/types/json.js | 5 ++--- lib/types/raw.js | 5 ++--- lib/types/text.js | 5 ++--- lib/types/urlencoded.js | 5 ++--- 5 files changed, 23 insertions(+), 14 deletions(-) diff --git a/lib/generic-parser.js b/lib/generic-parser.js index 8ddc52d4..24c3563e 100644 --- a/lib/generic-parser.js +++ b/lib/generic-parser.js @@ -34,8 +34,21 @@ module.exports = generic * @public */ -function generic (options) { - var opts = options || {} +function generic (parserOptions, parserOverrides) { + var opts = {} + + // Squash the options and the overrides down into one object + var squashKey + for (squashKey in (parserOptions || {})) { + if (Object.prototype.hasOwnProperty.call(parserOptions, squashKey)) { + opts[squashKey] = parserOptions[squashKey] + } + } + for (squashKey in (parserOverrides || {})) { + if (Object.prototype.hasOwnProperty.call(parserOverrides, squashKey)) { + opts[squashKey] = parserOverrides[squashKey] + } + } var limit = typeof opts.limit !== 'number' ? bytes.parse(opts.limit || '100kb') diff --git a/lib/types/json.js b/lib/types/json.js index e8b233af..ae1af796 100644 --- a/lib/types/json.js +++ b/lib/types/json.js @@ -12,7 +12,6 @@ * @private */ -var assign = require('object-assign') var genericParser = require('../..').generic var debug = require('debug')('body-parser:json') @@ -55,7 +54,7 @@ function json (options) { var parser = opts.parser || JSON.parse var type = opts.type || 'application/json' - return genericParser(assign({}, opts, { + return genericParser(opts, { type: type, charset: function validateCharset (charset) { @@ -88,7 +87,7 @@ function json (options) { }) } } - })) + }) } /** diff --git a/lib/types/raw.js b/lib/types/raw.js index f6120aaa..b40cfd5d 100644 --- a/lib/types/raw.js +++ b/lib/types/raw.js @@ -10,7 +10,6 @@ * Module dependencies. */ -var assign = require('object-assign') var genericParser = require('../..').generic /** @@ -32,7 +31,7 @@ function raw (options) { var type = opts.type || 'application/octet-stream' - return genericParser(assign({}, opts, { + return genericParser(opts, { type: type - })) + }) } diff --git a/lib/types/text.js b/lib/types/text.js index 36405a1a..87e65793 100644 --- a/lib/types/text.js +++ b/lib/types/text.js @@ -10,7 +10,6 @@ * Module dependencies. */ -var assign = require('object-assign') var genericParser = require('../..').generic /** @@ -33,9 +32,9 @@ function text (options) { var defaultCharset = opts.defaultCharset || 'utf-8' var type = opts.type || 'text/plain' - return genericParser(assign({}, opts, { + return genericParser(opts, { type: type, charset: function validateCharset () { return true }, defaultCharset: defaultCharset - })) + }) } diff --git a/lib/types/urlencoded.js b/lib/types/urlencoded.js index b101069b..1b2e2878 100644 --- a/lib/types/urlencoded.js +++ b/lib/types/urlencoded.js @@ -12,7 +12,6 @@ * @private */ -var assign = require('object-assign') var createError = require('http-errors') var debug = require('debug')('body-parser:urlencoded') var genericParser = require('../..').generic @@ -53,7 +52,7 @@ function urlencoded (options) { : simpleparser(opts) ) - return genericParser(assign({}, opts, { + return genericParser(opts, { type: type, charset: charset, @@ -62,7 +61,7 @@ function urlencoded (options) { ? queryparse(buf) : {} } - })) + }) } /** From cdf46f0aac846ce25ad0f9e618be9ac690667bb5 Mon Sep 17 00:00:00 2001 From: S Dellysse Date: Fri, 17 Apr 2020 00:43:41 -0400 Subject: [PATCH 22/26] minor text cleanup --- lib/generic-parser.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/generic-parser.js b/lib/generic-parser.js index 24c3563e..3c88628b 100644 --- a/lib/generic-parser.js +++ b/lib/generic-parser.js @@ -27,7 +27,7 @@ var typeis = require('type-is') module.exports = generic /** - * Create a middleware to parse JSON bodies. + * Use this to create a middleware that parses request bodies * * @param {object} [options] * @return {function} From 8ac04fd32d80d59b190f35a9b7cb18ed2c3f84c5 Mon Sep 17 00:00:00 2001 From: ctcpip Date: Fri, 24 May 2024 15:29:01 -0500 Subject: [PATCH 23/26] =?UTF-8?q?=F0=9F=94=A7=20add=20debug=20script?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 8b3b070d..aa64b77a 100644 --- a/package.json +++ b/package.json @@ -49,6 +49,7 @@ "lint": "eslint .", "test": "mocha --require test/support/env --reporter spec --check-leaks --bail test/", "test-ci": "nyc --reporter=lcov --reporter=text npm test", - "test-cov": "nyc --reporter=html --reporter=text npm test" + "test-cov": "nyc --reporter=html --reporter=text npm test", + "test-debug": "npm test -- --timeout 0" } } \ No newline at end of file From 1a43910c95eac9337fd2db3638cd3c925785d45e Mon Sep 17 00:00:00 2001 From: ctcpip Date: Fri, 24 May 2024 16:52:59 -0500 Subject: [PATCH 24/26] =?UTF-8?q?=F0=9F=90=9B=20fix=20object=20merging?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/generic-parser.js | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/lib/generic-parser.js b/lib/generic-parser.js index 3c88628b..deb96d10 100644 --- a/lib/generic-parser.js +++ b/lib/generic-parser.js @@ -35,20 +35,9 @@ module.exports = generic */ function generic (parserOptions, parserOverrides) { - var opts = {} - // Squash the options and the overrides down into one object - var squashKey - for (squashKey in (parserOptions || {})) { - if (Object.prototype.hasOwnProperty.call(parserOptions, squashKey)) { - opts[squashKey] = parserOptions[squashKey] - } - } - for (squashKey in (parserOverrides || {})) { - if (Object.prototype.hasOwnProperty.call(parserOverrides, squashKey)) { - opts[squashKey] = parserOverrides[squashKey] - } - } + var opts = Object.create(parserOptions) + Object.assign(opts, parserOverrides) var limit = typeof opts.limit !== 'number' ? bytes.parse(opts.limit || '100kb') From 86804fe1a7dd48882796e75b68e41017a4bd76a5 Mon Sep 17 00:00:00 2001 From: ctcpip Date: Fri, 24 May 2024 18:07:18 -0500 Subject: [PATCH 25/26] =?UTF-8?q?=F0=9F=94=A5=20clean=20up?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/types/urlencoded.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/lib/types/urlencoded.js b/lib/types/urlencoded.js index 1b2e2878..c9362757 100644 --- a/lib/types/urlencoded.js +++ b/lib/types/urlencoded.js @@ -39,10 +39,6 @@ function urlencoded (options) { var opts = options || {} var extended = Boolean(opts.extended) - var inflate = opts.inflate !== false - var limit = typeof opts.limit !== 'number' - ? bytes.parse(opts.limit || '100kb') - : opts.limit var type = opts.type || 'application/x-www-form-urlencoded' var charset = opts.charset || 'utf-8' From 88f84bd5a76f7fe536e255d63bc7b6f11006202c Mon Sep 17 00:00:00 2001 From: ctcpip Date: Fri, 24 May 2024 18:25:29 -0500 Subject: [PATCH 26/26] =?UTF-8?q?=F0=9F=92=9A=20remove=20node=20<=204=20fr?= =?UTF-8?q?om=20CI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/ci.yml | 29 ++--------------------------- 1 file changed, 2 insertions(+), 27 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index dd2e145b..a72a7f93 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,11 +10,6 @@ jobs: strategy: matrix: name: - - Node.js 0.10 - - Node.js 0.12 - - io.js 1.x - - io.js 2.x - - io.js 3.x - Node.js 4.x - Node.js 5.x - Node.js 6.x @@ -33,26 +28,6 @@ jobs: - Node.js 19.x include: - - name: Node.js 0.10 - node-version: "0.10" - npm-i: mocha@3.5.3 nyc@10.3.2 supertest@2.0.0 - - - name: Node.js 0.12 - node-version: "0.12" - npm-i: mocha@3.5.3 nyc@10.3.2 supertest@2.0.0 - - - name: io.js 1.x - node-version: "1.8" - npm-i: mocha@3.5.3 nyc@10.3.2 supertest@2.0.0 - - - name: io.js 2.x - node-version: "2.5" - npm-i: mocha@3.5.3 nyc@10.3.2 supertest@2.0.0 - - - name: io.js 3.x - node-version: "3.3" - npm-i: mocha@3.5.3 nyc@10.3.2 supertest@2.0.0 - - name: Node.js 4.x node-version: "4.9" npm-i: mocha@5.2.0 nyc@11.9.0 supertest@3.4.2 @@ -71,11 +46,11 @@ jobs: - name: Node.js 8.x node-version: "8.17" - npm-i: mocha@7.2.0 + npm-i: mocha@6.2.2 nyc@14.1.1 supertest@6.1.6 - name: Node.js 9.x node-version: "9.11" - npm-i: mocha@7.2.0 + npm-i: mocha@6.2.2 nyc@14.1.1 supertest@6.1.6 - name: Node.js 10.x node-version: "10.24"