From f316637ef863cca5a8ca3369694c79830aa9a462 Mon Sep 17 00:00:00 2001 From: Phillip Barta Date: Wed, 16 Oct 2024 17:53:38 +0200 Subject: [PATCH 01/22] fix: update engines field to reflect supported node versions (#541) closes #540 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index cc6f7ab7..10368ed4 100644 --- a/package.json +++ b/package.json @@ -43,7 +43,7 @@ "index.js" ], "engines": { - "node": ">= 0.10" + "node": ">=18" }, "scripts": { "lint": "eslint .", From cd985a855405abd66c33bd33d941fc6ff7a7826e Mon Sep 17 00:00:00 2001 From: Phillip Barta Date: Thu, 17 Oct 2024 17:37:21 +0200 Subject: [PATCH 02/22] fix: remove brotli support check (#542) with the minimum supported node version set to v18 we can remove the brotli support check as it was added in v11.7.0 and v10.16.0 --- lib/read.js | 14 +++----------- test/json.js | 14 +------------- test/raw.js | 14 +------------- test/text.js | 14 +------------- test/urlencoded.js | 14 +------------- 5 files changed, 7 insertions(+), 63 deletions(-) diff --git a/lib/read.js b/lib/read.js index a4bd446d..da3dbc9b 100644 --- a/lib/read.js +++ b/lib/read.js @@ -25,12 +25,6 @@ var zlib = require('zlib') module.exports = read -/** - * @const - * whether current node version has brotli support - */ -var hasBrotliSupport = 'createBrotliDecompress' in zlib - /** * Read a request into a buffer and parse. * @@ -181,11 +175,9 @@ function contentstream (req, debug, inflate) { stream.length = length break case 'br': - if (hasBrotliSupport) { - stream = zlib.createBrotliDecompress() - debug('brotli decompress body') - req.pipe(stream) - } + stream = zlib.createBrotliDecompress() + debug('brotli decompress body') + req.pipe(stream) break } diff --git a/test/json.js b/test/json.js index 3dcfd9c0..6a36eada 100644 --- a/test/json.js +++ b/test/json.js @@ -12,10 +12,6 @@ var describeAsyncHooks = typeof asyncHooks.AsyncLocalStorage === 'function' ? describe : describe.skip -var hasBrotliSupport = 'createBrotliDecompress' in require('zlib') -var brotlit = hasBrotliSupport ? it : it.skip -var nobrotlit = !hasBrotliSupport ? it : it.skip - describe('bodyParser.json()', function () { it('should parse JSON', function (done) { request(createServer()) @@ -687,7 +683,7 @@ describe('bodyParser.json()', function () { test.expect(200, '{"name":"论"}', done) }) - brotlit('should support brotli encoding', function (done) { + it('should support brotli encoding', function (done) { var test = request(this.server).post('/') test.set('Content-Encoding', 'br') test.set('Content-Type', 'application/json') @@ -695,14 +691,6 @@ describe('bodyParser.json()', function () { test.expect(200, '{"name":"论"}', done) }) - nobrotlit('should throw 415 if there\'s no brotli support', function (done) { - var test = request(this.server).post('/') - test.set('Content-Encoding', 'br') - test.set('Content-Type', 'application/json') - test.write(Buffer.from('8b06807b226e616d65223a22e8aeba227d03', 'hex')) - test.expect(415, 'unsupported content encoding "br"', done) - }) - it('should be case-insensitive', function (done) { var test = request(this.server).post('/') test.set('Content-Encoding', 'GZIP') diff --git a/test/raw.js b/test/raw.js index bd0b564c..0afcdcab 100644 --- a/test/raw.js +++ b/test/raw.js @@ -12,10 +12,6 @@ var describeAsyncHooks = typeof asyncHooks.AsyncLocalStorage === 'function' ? describe : describe.skip -var hasBrotliSupport = 'createBrotliDecompress' in require('zlib') -var brotlit = hasBrotliSupport ? it : it.skip -var nobrotlit = !hasBrotliSupport ? it : it.skip - describe('bodyParser.raw()', function () { before(function () { this.server = createServer() @@ -459,7 +455,7 @@ describe('bodyParser.raw()', function () { test.expect(200, 'buf:6e616d653de8aeba', done) }) - brotlit('should support brotli encoding', function (done) { + it('should support brotli encoding', function (done) { var test = request(this.server).post('/') test.set('Content-Encoding', 'br') test.set('Content-Type', 'application/octet-stream') @@ -467,14 +463,6 @@ describe('bodyParser.raw()', function () { test.expect(200, 'buf:6e616d653de8aeba', done) }) - nobrotlit('should throw 415 if there\'s no brotli support', function (done) { - var test = request(this.server).post('/') - test.set('Content-Encoding', 'br') - test.set('Content-Type', 'application/octet-stream') - test.write(Buffer.from('8b03806e616d653de8aeba03', 'hex')) - test.expect(415, 'unsupported content encoding "br"', done) - }) - it('should be case-insensitive', function (done) { var test = request(this.server).post('/') test.set('Content-Encoding', 'GZIP') diff --git a/test/text.js b/test/text.js index 4eae37ac..f581e651 100644 --- a/test/text.js +++ b/test/text.js @@ -12,10 +12,6 @@ var describeAsyncHooks = typeof asyncHooks.AsyncLocalStorage === 'function' ? describe : describe.skip -var hasBrotliSupport = 'createBrotliDecompress' in require('zlib') -var brotlit = hasBrotliSupport ? it : it.skip -var nobrotlit = !hasBrotliSupport ? it : it.skip - describe('bodyParser.text()', function () { before(function () { this.server = createServer() @@ -529,7 +525,7 @@ describe('bodyParser.text()', function () { test.expect(200, '"name is 论"', done) }) - brotlit('should support brotli encoding', function (done) { + it('should support brotli encoding', function (done) { var test = request(this.server).post('/') test.set('Content-Encoding', 'br') test.set('Content-Type', 'text/plain') @@ -537,14 +533,6 @@ describe('bodyParser.text()', function () { test.expect(200, '"name is 论"', done) }) - nobrotlit('should throw 415 if there\'s no brotli support', function (done) { - var test = request(this.server).post('/') - test.set('Content-Encoding', 'br') - test.set('Content-Type', 'text/plain') - test.write(Buffer.from('0b05806e616d6520697320e8aeba03', 'hex')) - test.expect(415, 'unsupported content encoding "br"', done) - }) - it('should be case-insensitive', function (done) { var test = request(this.server).post('/') test.set('Content-Encoding', 'GZIP') diff --git a/test/urlencoded.js b/test/urlencoded.js index 4ff9ab56..761dfa31 100644 --- a/test/urlencoded.js +++ b/test/urlencoded.js @@ -12,10 +12,6 @@ var describeAsyncHooks = typeof asyncHooks.AsyncLocalStorage === 'function' ? describe : describe.skip -var hasBrotliSupport = 'createBrotliDecompress' in require('zlib') -var brotlit = hasBrotliSupport ? it : it.skip -var nobrotlit = !hasBrotliSupport ? it : it.skip - describe('bodyParser.urlencoded()', function () { before(function () { this.server = createServer() @@ -907,7 +903,7 @@ describe('bodyParser.urlencoded()', function () { test.expect(200, '{"name":"论"}', done) }) - brotlit('should support brotli encoding', function (done) { + it('should support brotli encoding', function (done) { var test = request(this.server).post('/') test.set('Content-Encoding', 'br') test.set('Content-Type', 'application/x-www-form-urlencoded') @@ -915,14 +911,6 @@ describe('bodyParser.urlencoded()', function () { test.expect(200, '{"name":"论"}', done) }) - nobrotlit('should throw 415 if there\'s no brotli support', function (done) { - var test = request(this.server).post('/') - test.set('Content-Encoding', 'br') - test.set('Content-Type', 'application/x-www-form-urlencoded') - test.write(Buffer.from('789ccb4bcc4db57db16e17001068042f', 'hex')) - test.expect(415, 'unsupported content encoding "br"', done) - }) - it('should be case-insensitive', function (done) { var test = request(this.server).post('/') test.set('Content-Encoding', 'GZIP') From 012330ef2543bc053745afa035e4bdc58539095a Mon Sep 17 00:00:00 2001 From: Phillip Barta Date: Tue, 22 Oct 2024 13:05:48 +0200 Subject: [PATCH 03/22] refactor: remove `unpipe` package and use native `unpipe()` method (#543) --- HISTORY.md | 5 +++++ lib/read.js | 3 +-- package.json | 3 +-- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/HISTORY.md b/HISTORY.md index 8fb680fd..afd9c78d 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,3 +1,8 @@ +unreleased +========================= + +* remove `unpipe` package and use native `unpipe()` method + 2.0.1 / 2024-09-10 ========================= diff --git a/lib/read.js b/lib/read.js index da3dbc9b..4fd9d406 100644 --- a/lib/read.js +++ b/lib/read.js @@ -16,7 +16,6 @@ var destroy = require('destroy') var getBody = require('raw-body') var iconv = require('iconv-lite') var onFinished = require('on-finished') -var unpipe = require('unpipe') var zlib = require('zlib') /** @@ -90,7 +89,7 @@ function read (req, res, next, parse, debug, options) { // unpipe from stream and destroy if (stream !== req) { - unpipe(req) + req.unpipe() destroy(stream, true) } diff --git a/package.json b/package.json index 10368ed4..447bb860 100644 --- a/package.json +++ b/package.json @@ -18,8 +18,7 @@ "on-finished": "2.4.1", "qs": "6.13.0", "raw-body": "^3.0.0", - "type-is": "~1.6.18", - "unpipe": "1.0.0" + "type-is": "~1.6.18" }, "devDependencies": { "eslint": "8.34.0", From 1aad7507cd073a32252952910df91f291fd9d23a Mon Sep 17 00:00:00 2001 From: Phillip Barta Date: Tue, 22 Oct 2024 20:23:55 +0200 Subject: [PATCH 04/22] chore: remove unused devDependency `methods` (#548) --- package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/package.json b/package.json index 447bb860..a7ace491 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,6 @@ "eslint-plugin-node": "11.1.0", "eslint-plugin-promise": "6.1.1", "eslint-plugin-standard": "4.1.0", - "methods": "1.1.2", "mocha": "10.2.0", "nyc": "15.1.0", "safe-buffer": "5.2.1", From a5055dff4b8922f533403097a35abe967c91ae5a Mon Sep 17 00:00:00 2001 From: Phillip Barta Date: Tue, 22 Oct 2024 20:24:59 +0200 Subject: [PATCH 05/22] ci: updated github actions ci workflow (#546) --- .github/workflows/ci.yml | 126 ++++++++++++++------------------------- 1 file changed, 44 insertions(+), 82 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1169beb8..bafd918f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,108 +3,70 @@ on: push: branches: - master - - '2.x' paths-ignore: - '*.md' pull_request: paths-ignore: - '*.md' +permissions: + contents: read jobs: test: + name: Test - Node.js ${{ matrix.node-version }} runs-on: ubuntu-latest strategy: matrix: - name: - - Node.js 18.x - - Node.js 20.x - - Node.js 22.x - - include: - - name: Node.js 18.x - node-version: "18" - - - name: Node.js 20.x - node-version: "20" - - - name: Node.js 22.x - node-version: "22" + node-version: [18, 19, 20, 21, 22, 23] steps: - - uses: actions/checkout@v4 - - - name: Install Node.js ${{ matrix.node-version }} - shell: bash -eo pipefail -l {0} - run: | - nvm install --default ${{ matrix.node-version }} - dirname "$(nvm which ${{ matrix.node-version }})" >> "$GITHUB_PATH" - - - name: Configure npm - run: | - if [[ "$(npm config get package-lock)" == "true" ]]; then - npm config set package-lock false - else - npm config set shrinkwrap false - fi + - uses: actions/checkout@v4 - - name: Install Node.js dependencies - run: npm install + - uses: actions/setup-node@v4 + with: + node-version: ${{ matrix.node-version }} + check-latest: true - - name: List environment - id: list_env - shell: bash - run: | - echo "node@$(node -v)" - echo "npm@$(npm -v)" - npm -s ls ||: - (npm -s ls --depth=0 ||:) | awk -F'[ @]' 'NR>1 && $2 { print $2 "=" $3 }' >> "$GITHUB_OUTPUT" + - name: Install Node.js dependencies + run: npm install - - name: Run tests - shell: bash - run: | - npm run test-ci - cp coverage/lcov.info "coverage/${{ matrix.name }}.lcov" + - name: Run tests + run: npm run test-ci - - name: Lint code - if: steps.list_env.outputs.eslint != '' - run: npm run lint + - name: Lint code + run: npm run lint - - name: Collect code coverage - run: | - if [[ -d ./coverage ]]; then - mv ./coverage "./${{ matrix.name }}" - mkdir ./coverage - mv "./${{ matrix.name }}" "./coverage/${{ matrix.name }}" - fi - - - name: Upload code coverage - uses: actions/upload-artifact@v3 - with: - name: coverage - path: ./coverage - retention-days: 1 + - name: Upload code coverage + uses: actions/upload-artifact@v4 + with: + name: coverage-node-${{ matrix.node-version }} + path: ./coverage/lcov.info + retention-days: 1 coverage: needs: test runs-on: ubuntu-latest + permissions: + contents: read + checks: write steps: - - uses: actions/checkout@v4 - - - name: Install lcov - shell: bash - run: sudo apt-get -y install lcov - - - name: Collect coverage reports - uses: actions/download-artifact@v3 - with: - name: coverage - path: ./coverage - - - name: Merge coverage reports - shell: bash - run: find ./coverage -name lcov.info -exec printf '-a %q\n' {} \; | xargs lcov -o ./coverage/lcov.info - - - name: Upload coverage report - uses: coverallsapp/github-action@master - with: - github-token: ${{ secrets.GITHUB_TOKEN }} + - uses: actions/checkout@v4 + + - name: Install lcov + shell: bash + run: sudo apt-get -y install lcov + + - name: Collect coverage reports + uses: actions/download-artifact@v4 + with: + path: ./coverage + pattern: coverage-node-* + + - name: Merge coverage reports + shell: bash + run: find ./coverage -name lcov.info -exec printf '-a %q\n' {} \; | xargs lcov -o ./lcov.info + + - name: Upload coverage report + uses: coverallsapp/github-action@v2 + with: + file: ./lcov.info From a92da8cf97f82436def28cc13c7a3d52484f254a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ulises=20Gasc=C3=B3n?= Date: Thu, 31 Oct 2024 16:05:11 +0100 Subject: [PATCH 06/22] 2.0.2 PR-URL: https://github.com/expressjs/body-parser/pull/554 Signed-off-by: Ulises Gascon --- HISTORY.md | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/HISTORY.md b/HISTORY.md index afd9c78d..0579435b 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,4 +1,4 @@ -unreleased +2.0.2 / 2024-10-31 ========================= * remove `unpipe` package and use native `unpipe()` method diff --git a/package.json b/package.json index a7ace491..3e9d5219 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "body-parser", "description": "Node.js body parsing middleware", - "version": "2.0.1", + "version": "2.0.2", "contributors": [ "Douglas Christopher Wilson ", "Jonathan Ong (http://jongleberry.com)" From 51e90e71d7605f95a668b7c0a9559421c8d5dcf8 Mon Sep 17 00:00:00 2001 From: Phillip Barta Date: Thu, 31 Oct 2024 16:22:03 +0100 Subject: [PATCH 07/22] refactor: remove devDependency `safe-buffer` (#547) --- package.json | 1 - test/json.js | 1 - test/raw.js | 1 - test/text.js | 1 - test/urlencoded.js | 1 - 5 files changed, 5 deletions(-) diff --git a/package.json b/package.json index 3e9d5219..5b35fbf3 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,6 @@ "eslint-plugin-standard": "4.1.0", "mocha": "10.2.0", "nyc": "15.1.0", - "safe-buffer": "5.2.1", "supertest": "6.3.3" }, "files": [ diff --git a/test/json.js b/test/json.js index 6a36eada..756f7d86 100644 --- a/test/json.js +++ b/test/json.js @@ -2,7 +2,6 @@ var assert = require('assert') var asyncHooks = tryRequire('async_hooks') -var Buffer = require('safe-buffer').Buffer var http = require('http') var request = require('supertest') diff --git a/test/raw.js b/test/raw.js index 0afcdcab..23e537ac 100644 --- a/test/raw.js +++ b/test/raw.js @@ -2,7 +2,6 @@ var assert = require('assert') var asyncHooks = tryRequire('async_hooks') -var Buffer = require('safe-buffer').Buffer var http = require('http') var request = require('supertest') diff --git a/test/text.js b/test/text.js index f581e651..db9b21ee 100644 --- a/test/text.js +++ b/test/text.js @@ -2,7 +2,6 @@ var assert = require('assert') var asyncHooks = tryRequire('async_hooks') -var Buffer = require('safe-buffer').Buffer var http = require('http') var request = require('supertest') diff --git a/test/urlencoded.js b/test/urlencoded.js index 761dfa31..9590a00a 100644 --- a/test/urlencoded.js +++ b/test/urlencoded.js @@ -2,7 +2,6 @@ var assert = require('assert') var asyncHooks = tryRequire('async_hooks') -var Buffer = require('safe-buffer').Buffer var http = require('http') var request = require('supertest') From 80fbb762b1e326d9a7589df9285bf351d5685f35 Mon Sep 17 00:00:00 2001 From: Phillip Barta Date: Thu, 7 Nov 2024 16:43:13 +0100 Subject: [PATCH 08/22] test: remove AsyncLocalStorage check (#549) --- test/json.js | 18 +++--------------- test/raw.js | 18 +++--------------- test/text.js | 18 +++--------------- test/urlencoded.js | 18 +++--------------- 4 files changed, 12 insertions(+), 60 deletions(-) diff --git a/test/json.js b/test/json.js index 756f7d86..3b5cc653 100644 --- a/test/json.js +++ b/test/json.js @@ -1,16 +1,12 @@ 'use strict' var assert = require('assert') -var asyncHooks = tryRequire('async_hooks') +var AsyncLocalStorage = require('async_hooks').AsyncLocalStorage var http = require('http') var request = require('supertest') var bodyParser = require('..') -var describeAsyncHooks = typeof asyncHooks.AsyncLocalStorage === 'function' - ? describe - : describe.skip - describe('bodyParser.json()', function () { it('should parse JSON', function (done) { request(createServer()) @@ -511,13 +507,13 @@ describe('bodyParser.json()', function () { }) }) - describeAsyncHooks('async local storage', function () { + describe('async local storage', function () { before(function () { var jsonParser = bodyParser.json() var store = { foo: 'bar' } this.server = createServer(function (req, res, next) { - var asyncLocalStorage = new asyncHooks.AsyncLocalStorage() + var asyncLocalStorage = new AsyncLocalStorage() asyncLocalStorage.run(store, function () { jsonParser(req, res, function (err) { @@ -761,11 +757,3 @@ function shouldContainInBody (str) { 'expected \'' + res.text + '\' to contain \'' + str + '\'') } } - -function tryRequire (name) { - try { - return require(name) - } catch (e) { - return {} - } -} diff --git a/test/raw.js b/test/raw.js index 23e537ac..3f9a7284 100644 --- a/test/raw.js +++ b/test/raw.js @@ -1,16 +1,12 @@ 'use strict' var assert = require('assert') -var asyncHooks = tryRequire('async_hooks') +var AsyncLocalStorage = require('async_hooks').AsyncLocalStorage var http = require('http') var request = require('supertest') var bodyParser = require('..') -var describeAsyncHooks = typeof asyncHooks.AsyncLocalStorage === 'function' - ? describe - : describe.skip - describe('bodyParser.raw()', function () { before(function () { this.server = createServer() @@ -329,13 +325,13 @@ describe('bodyParser.raw()', function () { }) }) - describeAsyncHooks('async local storage', function () { + describe('async local storage', function () { before(function () { var rawParser = bodyParser.raw() var store = { foo: 'bar' } this.server = createServer(function (req, res, next) { - var asyncLocalStorage = new asyncHooks.AsyncLocalStorage() + var asyncLocalStorage = new AsyncLocalStorage() asyncLocalStorage.run(store, function () { rawParser(req, res, function (err) { @@ -502,11 +498,3 @@ function createServer (opts) { }) }) } - -function tryRequire (name) { - try { - return require(name) - } catch (e) { - return {} - } -} diff --git a/test/text.js b/test/text.js index db9b21ee..021612aa 100644 --- a/test/text.js +++ b/test/text.js @@ -1,16 +1,12 @@ 'use strict' var assert = require('assert') -var asyncHooks = tryRequire('async_hooks') +var AsyncLocalStorage = require('async_hooks').AsyncLocalStorage var http = require('http') var request = require('supertest') var bodyParser = require('..') -var describeAsyncHooks = typeof asyncHooks.AsyncLocalStorage === 'function' - ? describe - : describe.skip - describe('bodyParser.text()', function () { before(function () { this.server = createServer() @@ -370,13 +366,13 @@ describe('bodyParser.text()', function () { }) }) - describeAsyncHooks('async local storage', function () { + describe('async local storage', function () { before(function () { var textParser = bodyParser.text() var store = { foo: 'bar' } this.server = createServer(function (req, res, next) { - var asyncLocalStorage = new asyncHooks.AsyncLocalStorage() + var asyncLocalStorage = new AsyncLocalStorage() asyncLocalStorage.run(store, function () { textParser(req, res, function (err) { @@ -565,11 +561,3 @@ function createServer (opts) { }) }) } - -function tryRequire (name) { - try { - return require(name) - } catch (e) { - return {} - } -} diff --git a/test/urlencoded.js b/test/urlencoded.js index 9590a00a..dfe0eb9f 100644 --- a/test/urlencoded.js +++ b/test/urlencoded.js @@ -1,16 +1,12 @@ 'use strict' var assert = require('assert') -var asyncHooks = tryRequire('async_hooks') +var AsyncLocalStorage = require('async_hooks').AsyncLocalStorage var http = require('http') var request = require('supertest') var bodyParser = require('..') -var describeAsyncHooks = typeof asyncHooks.AsyncLocalStorage === 'function' - ? describe - : describe.skip - describe('bodyParser.urlencoded()', function () { before(function () { this.server = createServer() @@ -755,13 +751,13 @@ describe('bodyParser.urlencoded()', function () { }) }) - describeAsyncHooks('async local storage', function () { + describe('async local storage', function () { before(function () { var urlencodedParser = bodyParser.urlencoded() var store = { foo: 'bar' } this.server = createServer(function (req, res, next) { - var asyncLocalStorage = new asyncHooks.AsyncLocalStorage() + var asyncLocalStorage = new AsyncLocalStorage() asyncLocalStorage.run(store, function () { urlencodedParser(req, res, function (err) { @@ -968,11 +964,3 @@ function expectKeyCount (count) { assert.strictEqual(Object.keys(JSON.parse(res.text)).length, count) } } - -function tryRequire (name) { - try { - return require(name) - } catch (e) { - return {} - } -} From a45a451779377e33acc879ded83e06ef402ba610 Mon Sep 17 00:00:00 2001 From: Phillip Barta Date: Wed, 8 Jan 2025 14:42:43 +0100 Subject: [PATCH 09/22] fix: use the node require cache instead of custom caching (#562) --- index.js | 58 ++++---------------------------------------------------- 1 file changed, 4 insertions(+), 54 deletions(-) diff --git a/index.js b/index.js index 81fb9046..d722d0b2 100644 --- a/index.js +++ b/index.js @@ -6,13 +6,6 @@ 'use strict' -/** - * Cache of loaded parsers. - * @private - */ - -var parsers = Object.create(null) - /** * @typedef Parsers * @type {function} @@ -37,7 +30,7 @@ exports = module.exports = bodyParser Object.defineProperty(exports, 'json', { configurable: true, enumerable: true, - get: createParserGetter('json') + get: () => require('./lib/types/json') }) /** @@ -48,7 +41,7 @@ Object.defineProperty(exports, 'json', { Object.defineProperty(exports, 'raw', { configurable: true, enumerable: true, - get: createParserGetter('raw') + get: () => require('./lib/types/raw') }) /** @@ -59,7 +52,7 @@ Object.defineProperty(exports, 'raw', { Object.defineProperty(exports, 'text', { configurable: true, enumerable: true, - get: createParserGetter('text') + get: () => require('./lib/types/text') }) /** @@ -70,7 +63,7 @@ Object.defineProperty(exports, 'text', { Object.defineProperty(exports, 'urlencoded', { configurable: true, enumerable: true, - get: createParserGetter('urlencoded') + get: () => require('./lib/types/urlencoded') }) /** @@ -85,46 +78,3 @@ Object.defineProperty(exports, 'urlencoded', { function bodyParser () { throw new Error('The bodyParser() generic has been split into individual middleware to use instead.') } - -/** - * Create a getter for loading a parser. - * @private - */ - -function createParserGetter (name) { - return function get () { - return loadParser(name) - } -} - -/** - * Load a parser module. - * @private - */ - -function loadParser (parserName) { - var parser = parsers[parserName] - - if (parser !== undefined) { - return parser - } - - // this uses a switch for static require analysis - switch (parserName) { - case 'json': - parser = require('./lib/types/json') - break - case 'raw': - parser = require('./lib/types/raw') - break - case 'text': - parser = require('./lib/types/text') - break - case 'urlencoded': - parser = require('./lib/types/urlencoded') - break - } - - // store to prevent invoking require() - return (parsers[parserName] = parser) -} From ee8bd68d1af7ff2d57beb8e4f4ab2e874fa00f6c Mon Sep 17 00:00:00 2001 From: Phillip Barta Date: Wed, 8 Jan 2025 21:37:40 +0100 Subject: [PATCH 10/22] fix(ci): disable fail-fast in CI workflow (#565) --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bafd918f..9f6ada13 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,6 +16,7 @@ jobs: name: Test - Node.js ${{ matrix.node-version }} runs-on: ubuntu-latest strategy: + fail-fast: false matrix: node-version: [18, 19, 20, 21, 22, 23] From 23dc86799d6c86aaabbd7c11b80f8068ed79486d Mon Sep 17 00:00:00 2001 From: Phillip9587 Date: Mon, 13 Jan 2025 16:19:57 +0100 Subject: [PATCH 11/22] chore(deps): update `type-is` to v2.0.0 --- HISTORY.md | 5 +++++ package.json | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/HISTORY.md b/HISTORY.md index 0579435b..5e001b7e 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,3 +1,8 @@ +unreleased +========================= + +* deps: type-is@^2.0.0 + 2.0.2 / 2024-10-31 ========================= diff --git a/package.json b/package.json index 5b35fbf3..ebb2bdf1 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,7 @@ "on-finished": "2.4.1", "qs": "6.13.0", "raw-body": "^3.0.0", - "type-is": "~1.6.18" + "type-is": "^2.0.0" }, "devDependencies": { "eslint": "8.34.0", From 91c9199689a20d05432179cd07dd9956af19be61 Mon Sep 17 00:00:00 2001 From: Phillip9587 Date: Tue, 14 Jan 2025 20:59:09 +0100 Subject: [PATCH 12/22] refactor: prefix built-in node module imports Align with changes introduced in expressjs/express#6236 by prefixing all built-in Node.js module imports with 'node:'. Reference: https://github.com/expressjs/express/pull/6236 --- HISTORY.md | 1 + lib/read.js | 2 +- test/body-parser.js | 2 +- test/json.js | 6 +++--- test/raw.js | 6 +++--- test/text.js | 6 +++--- test/urlencoded.js | 6 +++--- 7 files changed, 15 insertions(+), 14 deletions(-) diff --git a/HISTORY.md b/HISTORY.md index 5e001b7e..3a538624 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -2,6 +2,7 @@ unreleased ========================= * deps: type-is@^2.0.0 +* refactor: prefix built-in node module imports 2.0.2 / 2024-10-31 ========================= diff --git a/lib/read.js b/lib/read.js index 4fd9d406..341e4aa3 100644 --- a/lib/read.js +++ b/lib/read.js @@ -16,7 +16,7 @@ var destroy = require('destroy') var getBody = require('raw-body') var iconv = require('iconv-lite') var onFinished = require('on-finished') -var zlib = require('zlib') +var zlib = require('node:zlib') /** * Module exports. diff --git a/test/body-parser.js b/test/body-parser.js index 0297471c..fcdde650 100644 --- a/test/body-parser.js +++ b/test/body-parser.js @@ -1,6 +1,6 @@ 'use strict' -var assert = require('assert') +var assert = require('node:assert') var bodyParser = require('..') diff --git a/test/json.js b/test/json.js index 3b5cc653..e679ac57 100644 --- a/test/json.js +++ b/test/json.js @@ -1,8 +1,8 @@ 'use strict' -var assert = require('assert') -var AsyncLocalStorage = require('async_hooks').AsyncLocalStorage -var http = require('http') +var assert = require('node:assert') +var AsyncLocalStorage = require('node:async_hooks').AsyncLocalStorage +var http = require('node:http') var request = require('supertest') var bodyParser = require('..') diff --git a/test/raw.js b/test/raw.js index 3f9a7284..033a97cb 100644 --- a/test/raw.js +++ b/test/raw.js @@ -1,8 +1,8 @@ 'use strict' -var assert = require('assert') -var AsyncLocalStorage = require('async_hooks').AsyncLocalStorage -var http = require('http') +var assert = require('node:assert') +var AsyncLocalStorage = require('node:async_hooks').AsyncLocalStorage +var http = require('node:http') var request = require('supertest') var bodyParser = require('..') diff --git a/test/text.js b/test/text.js index 021612aa..2b67aa95 100644 --- a/test/text.js +++ b/test/text.js @@ -1,8 +1,8 @@ 'use strict' -var assert = require('assert') -var AsyncLocalStorage = require('async_hooks').AsyncLocalStorage -var http = require('http') +var assert = require('node:assert') +var AsyncLocalStorage = require('node:async_hooks').AsyncLocalStorage +var http = require('node:http') var request = require('supertest') var bodyParser = require('..') diff --git a/test/urlencoded.js b/test/urlencoded.js index dfe0eb9f..9911bc5a 100644 --- a/test/urlencoded.js +++ b/test/urlencoded.js @@ -1,8 +1,8 @@ 'use strict' -var assert = require('assert') -var AsyncLocalStorage = require('async_hooks').AsyncLocalStorage -var http = require('http') +var assert = require('node:assert') +var AsyncLocalStorage = require('node:async_hooks').AsyncLocalStorage +var http = require('node:http') var request = require('supertest') var bodyParser = require('..') From 07a8f5991f24e55f9f1d3652eeb1d2d7fe2ddb8e Mon Sep 17 00:00:00 2001 From: Phillip9587 Date: Mon, 13 Jan 2025 16:08:18 +0100 Subject: [PATCH 13/22] fix: remove obsolete dependency `destroy` The [`destroy`](https://www.npmjs.com/package/destroy) package was was used to handle stream destruction across legacy Node.js versions (>=0.8), addressing bugs in specific versions. Since we now officially support only Node.js 18 and newer, we can safely remove this dependency and replace it with a direct call to `stream.destroy()`. --- lib/read.js | 3 +-- package.json | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/read.js b/lib/read.js index 341e4aa3..b9edc95d 100644 --- a/lib/read.js +++ b/lib/read.js @@ -12,7 +12,6 @@ */ var createError = require('http-errors') -var destroy = require('destroy') var getBody = require('raw-body') var iconv = require('iconv-lite') var onFinished = require('on-finished') @@ -90,7 +89,7 @@ function read (req, res, next, parse, debug, options) { // unpipe from stream and destroy if (stream !== req) { req.unpipe() - destroy(stream, true) + stream.destroy() } // read off entire request diff --git a/package.json b/package.json index ebb2bdf1..b99d6c6c 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,6 @@ "bytes": "3.1.2", "content-type": "~1.0.5", "debug": "3.1.0", - "destroy": "1.2.0", "http-errors": "2.0.0", "iconv-lite": "0.5.2", "on-finished": "2.4.1", From 17c3999b59a2da6a6de9d235a532b05a148a63b3 Mon Sep 17 00:00:00 2001 From: Phillip9587 Date: Mon, 13 Jan 2025 15:34:24 +0100 Subject: [PATCH 14/22] cleanup: remove obsolete test env file The `test/support/env.js` file contained the definition of an environment variable which was only used to silence [`depd`](https://www.npmjs.com/package/depd) during tests. Since `depd` is not used anymore, we can safely remove the file. --- package.json | 2 +- test/support/env.js | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) delete mode 100644 test/support/env.js diff --git a/package.json b/package.json index b99d6c6c..068dfa99 100644 --- a/package.json +++ b/package.json @@ -43,7 +43,7 @@ }, "scripts": { "lint": "eslint .", - "test": "mocha --require test/support/env --reporter spec --check-leaks --bail test/", + "test": "mocha --reporter spec --check-leaks --bail test/", "test-ci": "nyc --reporter=lcov --reporter=text npm test", "test-cov": "nyc --reporter=html --reporter=text npm test" } diff --git a/test/support/env.js b/test/support/env.js deleted file mode 100644 index 323eba20..00000000 --- a/test/support/env.js +++ /dev/null @@ -1,2 +0,0 @@ - -process.env.NO_DEPRECATION = 'body-parser' From e0f261e34d736e60b6fcb2623897b763e527a8f9 Mon Sep 17 00:00:00 2001 From: Phillip9587 Date: Fri, 6 Dec 2024 15:20:50 +0100 Subject: [PATCH 15/22] Refactor decompression stream creation to remove code duplication --- lib/read.js | 49 ++++++++++++++++++++++++++----------------------- 1 file changed, 26 insertions(+), 23 deletions(-) diff --git a/lib/read.js b/lib/read.js index b9edc95d..eee8b111 100644 --- a/lib/read.js +++ b/lib/read.js @@ -146,7 +146,6 @@ function read (req, res, next, parse, debug, options) { function contentstream (req, debug, inflate) { var encoding = (req.headers['content-encoding'] || 'identity').toLowerCase() var length = req.headers['content-length'] - var stream debug('content-encoding "%s"', encoding) @@ -157,36 +156,40 @@ function contentstream (req, debug, inflate) { }) } + if (encoding === 'identity') { + req.length = length + return req + } + + var stream = createDecompressionStream(encoding, debug) + req.pipe(stream) + return stream +} + +/** + * Create a decompression stream for the given encoding. + * @param {string} encoding + * @param {function} debug + * @return {object} + * @api private + */ +function createDecompressionStream (encoding, debug) { switch (encoding) { case 'deflate': - stream = zlib.createInflate() debug('inflate body') - req.pipe(stream) - break + return zlib.createInflate() case 'gzip': - stream = zlib.createGunzip() debug('gunzip body') - req.pipe(stream) - break - case 'identity': - stream = req - stream.length = length - break + return zlib.createGunzip() case 'br': - stream = zlib.createBrotliDecompress() debug('brotli decompress body') - req.pipe(stream) - break - } - - if (stream === undefined) { - throw createError(415, 'unsupported content encoding "' + encoding + '"', { - encoding: encoding, - type: 'encoding.unsupported' - }) + return zlib.createBrotliDecompress() + default: + throw createError(415, 'unsupported content encoding "' + encoding + '"', { + encoding: encoding, + type: 'encoding.unsupported' + }) } - - return stream } /** From 41abe6de8a1fe89ea4ccd35c48d01bd10a330b84 Mon Sep 17 00:00:00 2001 From: Mauricio Guzman Date: Fri, 25 Oct 2024 16:38:56 -0400 Subject: [PATCH 16/22] Add caret for body-parser dependencies --- package.json | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/package.json b/package.json index 068dfa99..75339f04 100644 --- a/package.json +++ b/package.json @@ -9,15 +9,16 @@ "license": "MIT", "repository": "expressjs/body-parser", "dependencies": { - "bytes": "3.1.2", - "content-type": "~1.0.5", - "debug": "3.1.0", - "http-errors": "2.0.0", - "iconv-lite": "0.5.2", - "on-finished": "2.4.1", - "qs": "6.13.0", + "bytes": "^3.1.2", + "content-type": "^1.0.5", + "debug": "^3.1.0", + "destroy": "^1.2.0", + "http-errors": "^2.0.0", + "iconv-lite": "^0.5.2", + "on-finished": "^2.4.1", + "qs": "^6.14.0", "raw-body": "^3.0.0", - "type-is": "^2.0.0" + "type-is": "^1.6.18" }, "devDependencies": { "eslint": "8.34.0", From 732a7cc61a3d7b10c35e0cdb66cd02babd673dd7 Mon Sep 17 00:00:00 2001 From: Sebastian Beltran Date: Sun, 3 Nov 2024 21:07:00 -0500 Subject: [PATCH 17/22] ci: add CodeQL (SAST) --- .github/workflows/codeql.yml | 66 ++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 .github/workflows/codeql.yml diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 00000000..cd411926 --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,66 @@ +# For most projects, this workflow file will not need changing; you simply need +# to commit it to your repository. +# +# You may wish to alter this file to override the set of languages analyzed, +# or to provide custom queries or build logic. +# +# ******** NOTE ******** +# We have attempted to detect the languages in your repository. Please check +# the `language` matrix defined below to confirm you have the correct set of +# supported CodeQL languages. +# +name: "CodeQL" + +on: + push: + branches: ["master"] + pull_request: + # The branches below must be a subset of the branches above + branches: ["master"] + schedule: + - cron: "0 0 * * 1" + +permissions: + contents: read + +jobs: + analyze: + name: Analyze + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + security-events: write + + steps: + - name: Checkout repository + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@662472033e021d55d94146f66f6058822b0b39fd # v3.27.0 + with: + languages: javascript + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + + # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). + # If this step fails, then you should remove it and run the build manually (see below) + # - name: Autobuild + # uses: github/codeql-action/autobuild@662472033e021d55d94146f66f6058822b0b39fd # v3.27.0 + + # ℹ️ Command-line programs to run using the OS shell. + # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun + + # If the Autobuild fails above, remove it and uncomment the following three lines. + # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. + + # - run: | + # echo "Run, Build Application using script" + # ./location_of_script_within_repo/buildscript.sh + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@662472033e021d55d94146f66f6058822b0b39fd # v3.27.0 + with: + category: "/language:javascript" \ No newline at end of file From f1380f5524f7c2c8e1cbac9b03ec448dd91f708b Mon Sep 17 00:00:00 2001 From: Wes Todd Date: Thu, 23 Jan 2025 09:36:32 -0600 Subject: [PATCH 18/22] fix: fix type-is incorrect conflict resolution --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 75339f04..773dd4d7 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,7 @@ "on-finished": "^2.4.1", "qs": "^6.14.0", "raw-body": "^3.0.0", - "type-is": "^1.6.18" + "type-is": "^2.0.0" }, "devDependencies": { "eslint": "8.34.0", From 2fd8701543dcac9b3e80faf1ac86c171f38fc8f9 Mon Sep 17 00:00:00 2001 From: Wes Todd Date: Thu, 23 Jan 2025 09:39:06 -0600 Subject: [PATCH 19/22] fix: cleanup history.md --- HISTORY.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/HISTORY.md b/HISTORY.md index 3a538624..6b46f52d 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,8 +1,11 @@ unreleased ========================= -* deps: type-is@^2.0.0 +* deps: + * type-is@^2.0.0 + * Removed destroy * refactor: prefix built-in node module imports +* use the node require cache instead of custom caching 2.0.2 / 2024-10-31 ========================= From a7293977ddd1a2e976b85f76db06d24b1575b784 Mon Sep 17 00:00:00 2001 From: Wes Todd Date: Thu, 23 Jan 2025 17:11:47 -0600 Subject: [PATCH 20/22] fix: remove destroy after bad conflict resolution --- package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/package.json b/package.json index 773dd4d7..d96c037c 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,6 @@ "bytes": "^3.1.2", "content-type": "^1.0.5", "debug": "^3.1.0", - "destroy": "^1.2.0", "http-errors": "^2.0.0", "iconv-lite": "^0.5.2", "on-finished": "^2.4.1", From 2e4fe6b084c2b8747655a023947488ba88728a15 Mon Sep 17 00:00:00 2001 From: Phillip Barta Date: Mon, 10 Feb 2025 18:43:29 +0100 Subject: [PATCH 21/22] fix(deps): update `debug` to ^4.4.0 (#579) --- HISTORY.md | 1 + package.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/HISTORY.md b/HISTORY.md index 6b46f52d..f2b380bf 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -3,6 +3,7 @@ unreleased * deps: * type-is@^2.0.0 + * debug@^4.4.0 * Removed destroy * refactor: prefix built-in node module imports * use the node require cache instead of custom caching diff --git a/package.json b/package.json index d96c037c..3d4053b5 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "dependencies": { "bytes": "^3.1.2", "content-type": "^1.0.5", - "debug": "^3.1.0", + "debug": "^4.4.0", "http-errors": "^2.0.0", "iconv-lite": "^0.5.2", "on-finished": "^2.4.1", From eedea54b75cbea80eee2a00fdcd6a58d61b0713e Mon Sep 17 00:00:00 2001 From: Wes Todd Date: Thu, 23 Jan 2025 09:39:59 -0600 Subject: [PATCH 22/22] 2.1.0 --- HISTORY.md | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/HISTORY.md b/HISTORY.md index f2b380bf..f889cf1c 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,4 +1,4 @@ -unreleased +2.1.0 / 2025-02-10 ========================= * deps: diff --git a/package.json b/package.json index 3d4053b5..ef0f54d7 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "body-parser", "description": "Node.js body parsing middleware", - "version": "2.0.2", + "version": "2.1.0", "contributors": [ "Douglas Christopher Wilson ", "Jonathan Ong (http://jongleberry.com)"