From 714ac8b3d3b116650e8581551e923039f6ecefc7 Mon Sep 17 00:00:00 2001 From: Arun Kumar Mohan Date: Sat, 16 Nov 2019 19:11:51 -0500 Subject: [PATCH 01/29] Fix typo: ads -> adds --- Readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Readme.md b/Readme.md index e9195bd..8971f69 100644 --- a/Readme.md +++ b/Readme.md @@ -217,7 +217,7 @@ form.append( 'my_file', fs.createReadStream('/foo/bar.jpg'), {filename: 'bar.jpg ``` #### _Headers_ getHeaders( [**Headers** _userHeaders_] ) -This method ads the correct `content-type` header to the provided array of `userHeaders`. +This method adds the correct `content-type` header to the provided array of `userHeaders`. #### _String_ getBoundary() Return the boundary of the formData. A boundary consists of 26 `-` followed by 24 numbers From 55d90ce4a4c22b0ea0647991d85cb946dfb7395b Mon Sep 17 00:00:00 2001 From: Charlie Saunders Date: Tue, 2 Jun 2020 02:34:49 -0400 Subject: [PATCH 02/29] feat: add setBoundary method --- Readme.md | 7 ++++++- index.d.ts | 1 + lib/form_data.js | 4 ++++ test/integration/test-set-boundary.js | 23 +++++++++++++++++++++++ 4 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 test/integration/test-set-boundary.js diff --git a/Readme.md b/Readme.md index 8971f69..7bfea3e 100644 --- a/Readme.md +++ b/Readme.md @@ -189,6 +189,7 @@ form.submit({ - [_Void_ append( **String** _field_, **Mixed** _value_ [, **Mixed** _options_] )](https://github.com/form-data/form-data#void-append-string-field-mixed-value--mixed-options-). - [_Headers_ getHeaders( [**Headers** _userHeaders_] )](https://github.com/form-data/form-data#array-getheaders-array-userheaders-) - [_String_ getBoundary()](https://github.com/form-data/form-data#string-getboundary) +- [_Void_ setBoundary()](https://github.com/form-data/form-data#void-setboundary) - [_Buffer_ getBuffer()](https://github.com/form-data/form-data#buffer-getbuffer) - [_Integer_ getLengthSync()](https://github.com/form-data/form-data#integer-getlengthsync) - [_Integer_ getLength( **function** _callback_ )](https://github.com/form-data/form-data#integer-getlength-function-callback-) @@ -220,11 +221,15 @@ form.append( 'my_file', fs.createReadStream('/foo/bar.jpg'), {filename: 'bar.jpg This method adds the correct `content-type` header to the provided array of `userHeaders`. #### _String_ getBoundary() -Return the boundary of the formData. A boundary consists of 26 `-` followed by 24 numbers +Return the boundary of the formData. By default, the boundary consists of 26 `-` followed by 24 numbers for example: ```javascript --------------------------515890814546601021194782 ``` + +#### _Void_ setBoundary(String _boundary_) +Set the boundary string, overriding the default behavior described above. + _Note: The boundary must be unique and may not appear in the data._ #### _Buffer_ getBuffer() diff --git a/index.d.ts b/index.d.ts index 6e52045..295e9e9 100644 --- a/index.d.ts +++ b/index.d.ts @@ -36,6 +36,7 @@ declare class FormData extends stream.Readable { callback?: (error: Error | null, response: http.IncomingMessage) => void ): http.ClientRequest; getBuffer(): Buffer; + setBoundary(boundary: string): void; getBoundary(): string; getLength(callback: (err: Error | null, length: number) => void): void; getLengthSync(): number; diff --git a/lib/form_data.js b/lib/form_data.js index ddfae2e..cf836b0 100644 --- a/lib/form_data.js +++ b/lib/form_data.js @@ -305,6 +305,10 @@ FormData.prototype.getHeaders = function(userHeaders) { return formHeaders; }; +FormData.prototype.setBoundary = function(boundary) { + this._boundary = boundary; +}; + FormData.prototype.getBoundary = function() { if (!this._boundary) { this._generateBoundary(); diff --git a/test/integration/test-set-boundary.js b/test/integration/test-set-boundary.js new file mode 100644 index 0000000..f1d8820 --- /dev/null +++ b/test/integration/test-set-boundary.js @@ -0,0 +1,23 @@ +var common = require('../common'); +var assert = common.assert; + +var FormData = require(common.dir.lib + '/form_data'); + +(function testSetBoundary() { + var userBoundary = '---something'; + var form = new FormData(); + form.setBoundary(userBoundary); + + assert.equal(form.getBoundary(), userBoundary); +})(); + +(function testUniqueBoundaryPerFormAfterSet() { + var userBoundary = '---something'; + var formA = new FormData(); + formA.setBoundary(userBoundary); + + var formB = new FormData(); + + assert.equal(formA.getBoundary(), userBoundary); + assert.notEqual(formA.getBoundary(), formB.getBoundary()); +})(); From c72ad6728ae394e55c0f7a025864429edd656879 Mon Sep 17 00:00:00 2001 From: niftylettuce Date: Mon, 15 Feb 2021 11:33:21 -0600 Subject: [PATCH 03/29] 3.0.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6f1ebf0..a2fcb88 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "author": "Felix Geisendörfer (http://debuggable.com/)", "name": "form-data", "description": "A library to create readable \"multipart/form-data\" streams. Can be used to submit forms and file uploads to other web applications.", - "version": "3.0.0", + "version": "3.0.1", "repository": { "type": "git", "url": "git://github.com/form-data/form-data.git" From edb555a811f6f7e4668db4831551cf41c1de1cac Mon Sep 17 00:00:00 2001 From: marco-ippolito Date: Tue, 30 Apr 2024 09:08:39 +0200 Subject: [PATCH 04/29] fix: move util.isArray to Array.isArray (#564) --- lib/form_data.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/form_data.js b/lib/form_data.js index cf836b0..9316442 100644 --- a/lib/form_data.js +++ b/lib/form_data.js @@ -60,7 +60,7 @@ FormData.prototype.append = function(field, value, options) { } // https://github.com/felixge/node-form-data/issues/38 - if (util.isArray(value)) { + if (Array.isArray(value)) { // Please convert your array into string // the way web server expects it this._error(new Error('Arrays are not supported.')); From fed02210dbb2b44cbb8a798a508b3e79d0b9a511 Mon Sep 17 00:00:00 2001 From: Jaikanth J <31009437+jaikanthjay46@users.noreply.github.com> Date: Tue, 19 Apr 2022 00:39:40 +0530 Subject: [PATCH 05/29] fix (npmignore): ignore temporary build files (#532) They increase the size of the package and don't add any value --- .npmignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.npmignore b/.npmignore index 31fcb79..f6eab27 100644 --- a/.npmignore +++ b/.npmignore @@ -7,3 +7,6 @@ sftp-config.json coverage/ node_modules/ test/ + +yarn.lock +README.md.bak From 3217b3ded8e382e51171d5c74c6038a21cc54440 Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Thu, 19 Sep 2024 17:38:37 -0700 Subject: [PATCH 06/29] [eslint] clean up ignores --- .eslintignore | 2 -- .eslintrc | 7 ++++++- package.json | 2 +- 3 files changed, 7 insertions(+), 4 deletions(-) delete mode 100644 .eslintignore diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index 510731c..0000000 --- a/.eslintignore +++ /dev/null @@ -1,2 +0,0 @@ -node_modules/* -index.d.ts diff --git a/.eslintrc b/.eslintrc index 63de477..111719d 100644 --- a/.eslintrc +++ b/.eslintrc @@ -39,5 +39,10 @@ }, "env": { "node": true - } + }, + "ignorePatterns": [ + "node_modules/*", + "index.d.ts", + "coverage", + ] } diff --git a/package.json b/package.json index a2fcb88..45939b5 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ "pretest": "rimraf coverage test/tmp", "test": "istanbul cover test/run.js", "posttest": "istanbul report lcov text", - "lint": "eslint lib/*.js test/*.js test/integration/*.js", + "lint": "eslint --ext=js,mjs .", "report": "istanbul report lcov text", "ci-lint": "is-node-modern 8 && npm run lint || is-node-not-modern 8", "ci-test": "npm run test && npm run browser && npm run report", From 8fdb3bc6b5d001f8909a9fca391d1d1d97ef1d79 Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Fri, 20 Sep 2024 22:01:47 -0700 Subject: [PATCH 07/29] [Tests] migrate from travis to GHA --- .github/workflows/node-aught.yml | 14 +++++++++ .github/workflows/node-pretest.yml | 10 +++++++ .github/workflows/node-tens.yml | 14 +++++++++ .github/workflows/rebase.yml | 22 ++++++++++++++ .github/workflows/require-allow-edits.yml | 18 ++++++++++++ .travis.yml | 35 ----------------------- package.json | 11 ++++--- 7 files changed, 85 insertions(+), 39 deletions(-) create mode 100644 .github/workflows/node-aught.yml create mode 100644 .github/workflows/node-pretest.yml create mode 100644 .github/workflows/node-tens.yml create mode 100644 .github/workflows/rebase.yml create mode 100644 .github/workflows/require-allow-edits.yml delete mode 100644 .travis.yml diff --git a/.github/workflows/node-aught.yml b/.github/workflows/node-aught.yml new file mode 100644 index 0000000..d0f17ab --- /dev/null +++ b/.github/workflows/node-aught.yml @@ -0,0 +1,14 @@ +name: 'Tests: node.js < 10' + +on: [pull_request, push] + +permissions: + contents: read + +jobs: + tests: + uses: ljharb/actions/.github/workflows/node.yml@main + with: + range: '>= 6 < 10' + type: minors + command: npm run ci-test diff --git a/.github/workflows/node-pretest.yml b/.github/workflows/node-pretest.yml new file mode 100644 index 0000000..88d49f9 --- /dev/null +++ b/.github/workflows/node-pretest.yml @@ -0,0 +1,10 @@ +name: 'Tests: pretest/posttest' + +on: [pull_request, push] + +permissions: + contents: read + +jobs: + tests: + uses: ljharb/actions/.github/workflows/pretest.yml@main diff --git a/.github/workflows/node-tens.yml b/.github/workflows/node-tens.yml new file mode 100644 index 0000000..f39714e --- /dev/null +++ b/.github/workflows/node-tens.yml @@ -0,0 +1,14 @@ +name: 'Tests: node.js >= 10' + +on: [pull_request, push] + +permissions: + contents: read + +jobs: + tests: + uses: ljharb/actions/.github/workflows/node.yml@main + with: + range: '>= 10' + type: minors + command: npm run ci-test diff --git a/.github/workflows/rebase.yml b/.github/workflows/rebase.yml new file mode 100644 index 0000000..1818191 --- /dev/null +++ b/.github/workflows/rebase.yml @@ -0,0 +1,22 @@ +name: Automatic Rebase + +on: [pull_request_target] + +permissions: + contents: read + +jobs: + _: + permissions: + contents: write # for ljharb/rebase to push code to rebase + pull-requests: read # for ljharb/rebase to get info about PR + + name: "Automatic Rebase" + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - uses: ljharb/rebase@master + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/require-allow-edits.yml b/.github/workflows/require-allow-edits.yml new file mode 100644 index 0000000..a685b8a --- /dev/null +++ b/.github/workflows/require-allow-edits.yml @@ -0,0 +1,18 @@ +name: Require “Allow Edits” + +on: [pull_request_target] + +permissions: + contents: read + +jobs: + _: + permissions: + pull-requests: read # for ljharb/require-allow-edits to check 'allow edits' on PR + + name: "Require “Allow Edits”" + + runs-on: ubuntu-latest + + steps: + - uses: ljharb/require-allow-edits@main diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index f22a5d9..0000000 --- a/.travis.yml +++ /dev/null @@ -1,35 +0,0 @@ -sudo: false - -language: node_js -node_js: - - "6" - - "8" - - "10" - - "12" - -os: -- osx -- linux -- windows - -install: - - travis_retry npm install - -script: - - uname -a - - node --version - - npm --version - - if [ "$TRAVIS_OS_NAME" != "windows" ]; then npm run ci-lint; fi - - if [ "$TRAVIS_OS_NAME" = "windows" ]; then npm run test; else npm run ci-test; fi - - npm run check - -after_success: - - "cat coverage/lcov.info | ./node_modules/.bin/coveralls" - -notifications: - webhooks: - urls: - - "https://webhooks.gitter.im/e/3569d7edff0d38f93cd7" - on_success: always - on_failure: always - on_start: false diff --git a/package.json b/package.json index 45939b5..218a424 100644 --- a/package.json +++ b/package.json @@ -11,13 +11,16 @@ "browser": "./lib/browser", "typings": "./index.d.ts", "scripts": { - "pretest": "rimraf coverage test/tmp", - "test": "istanbul cover test/run.js", - "posttest": "istanbul report lcov text", + "pretest": "npm run lint", + "pretests-only": "rimraf coverage test/tmp", + "tests-only": "istanbul cover test/run.js", + "posttests-only": "istanbul report lcov text", + "test": "npm run tests-only", + "posttest": "npx npm@'>=10.2' audit --production", "lint": "eslint --ext=js,mjs .", "report": "istanbul report lcov text", "ci-lint": "is-node-modern 8 && npm run lint || is-node-not-modern 8", - "ci-test": "npm run test && npm run browser && npm run report", + "ci-test": "npm run tests-only && npm run browser && npm run report", "predebug": "rimraf coverage test/tmp", "debug": "verbose=1 ./test/run.js", "browser": "browserify -t browserify-istanbul test/run-browser.js | obake --coverage", From f06b0d85d10bc942b3bf586b01ace6e874ac61b3 Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Thu, 10 Oct 2024 12:48:34 +0900 Subject: [PATCH 08/29] v3.0.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 218a424..9ced458 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "author": "Felix Geisendörfer (http://debuggable.com/)", "name": "form-data", "description": "A library to create readable \"multipart/form-data\" streams. Can be used to submit forms and file uploads to other web applications.", - "version": "3.0.1", + "version": "3.0.2", "repository": { "type": "git", "url": "git://github.com/form-data/form-data.git" From b82f59093cdbadb4b7ec0922d33ae7ab048b82ff Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Fri, 14 Feb 2025 12:18:12 -0800 Subject: [PATCH 09/29] Only apps should have lockfiles --- .gitignore | 5 +++++ .npmrc | 1 + 2 files changed, 6 insertions(+) create mode 100644 .npmrc diff --git a/.gitignore b/.gitignore index 5790d18..6d8a802 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,8 @@ package-lock.json coverage/ node_modules/ test/tmp/ + +# Only apps should have lockfiles +npm-shrinkwrap.json +package-lock.json +yarn.lock diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..43c97e7 --- /dev/null +++ b/.npmrc @@ -0,0 +1 @@ +package-lock=false From 8261fcb8bf5944d30ae3bd04b91b71d6a9932ef4 Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Fri, 14 Feb 2025 13:59:27 -0800 Subject: [PATCH 10/29] [Dev Deps] update `@types/node`, `browserify`, `coveralls`, `cross-spawn`, `eslint`, `formidable`, `in-publish`, `pkgfiles`, `pre-commit`, `puppeteer`, `request`, `tape`, `typescript` --- package.json | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/package.json b/package.json index 9ced458..ddbfdb1 100644 --- a/package.json +++ b/package.json @@ -46,26 +46,26 @@ "mime-types": "^2.1.12" }, "devDependencies": { - "@types/node": "^12.0.10", - "browserify": "^13.1.1", + "@types/node": "^12.20.55", + "browserify": "^13.3.0", "browserify-istanbul": "^2.0.0", - "coveralls": "^3.0.4", - "cross-spawn": "^6.0.5", - "eslint": "^6.0.1", + "coveralls": "^3.1.1", + "cross-spawn": "^6.0.6", + "eslint": "^6.8.0", "fake": "^0.2.2", "far": "^0.0.7", - "formidable": "^1.0.17", - "in-publish": "^2.0.0", + "formidable": "^1.2.6", + "in-publish": "^2.0.1", "is-node-modern": "^1.0.0", "istanbul": "^0.4.5", "obake": "^0.1.2", - "puppeteer": "^1.19.0", - "pkgfiles": "^2.3.0", - "pre-commit": "^1.1.3", - "request": "^2.88.0", + "pkgfiles": "^2.3.2", + "pre-commit": "^1.2.2", + "puppeteer": "^1.20.0", + "request": "^2.88.2", "rimraf": "^2.7.1", - "tape": "^4.6.2", - "typescript": "^3.5.2" + "tape": "^5.9.0", + "typescript": "^3.9.10" }, "license": "MIT" } From 5a5bafee894fead10da49e1fa2b084e17f2e1034 Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Fri, 14 Feb 2025 14:02:36 -0800 Subject: [PATCH 11/29] [Deps] update `mime-types` --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ddbfdb1..82a523e 100644 --- a/package.json +++ b/package.json @@ -43,7 +43,7 @@ "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" + "mime-types": "^2.1.35" }, "devDependencies": { "@types/node": "^12.20.55", From 7fecefe4ba8f775634aff86a698776ad95ecffb5 Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Fri, 14 Feb 2025 11:46:18 -0800 Subject: [PATCH 12/29] [Refactor] use `Object.prototype.hasOwnProperty.call` --- lib/form_data.js | 42 ++++++++++---------- test/common.js | 19 +++++---- test/integration/test-custom-content-type.js | 15 ++++--- test/integration/test-pipe.js | 15 ++++--- test/integration/test-ranged-filestream.js | 20 +++++----- 5 files changed, 53 insertions(+), 58 deletions(-) diff --git a/lib/form_data.js b/lib/form_data.js index 9316442..b28bf16 100644 --- a/lib/form_data.js +++ b/lib/form_data.js @@ -101,7 +101,7 @@ FormData.prototype._trackLength = function(header, value, options) { FormData.LINE_BREAK.length; // empty or either doesn't have path or not an http response - if (!value || ( !value.path && !(value.readable && value.hasOwnProperty('httpVersion')) )) { + if (!value || ( !value.path && !(value.readable && Object.prototype.hasOwnProperty.call(value, 'httpVersion')) )) { return; } @@ -112,8 +112,7 @@ FormData.prototype._trackLength = function(header, value, options) { }; FormData.prototype._lengthRetriever = function(value, callback) { - - if (value.hasOwnProperty('fd')) { + if (Object.prototype.hasOwnProperty.call(value, 'fd')) { // take read range into a account // `end` = Infinity –> read file till the end @@ -148,11 +147,11 @@ FormData.prototype._lengthRetriever = function(value, callback) { } // or http response - } else if (value.hasOwnProperty('httpVersion')) { + } else if (Object.prototype.hasOwnProperty.call(value, 'httpVersion')) { callback(null, +value.headers['content-length']); // or request stream http://github.com/mikeal/request - } else if (value.hasOwnProperty('httpModule')) { + } else if (Object.prototype.hasOwnProperty.call(value, 'httpModule')) { // wait till response come back value.on('response', function(response) { value.pause(); @@ -192,22 +191,23 @@ FormData.prototype._multiPartHeader = function(field, value, options) { var header; for (var prop in headers) { - if (!headers.hasOwnProperty(prop)) continue; - header = headers[prop]; + if (Object.prototype.hasOwnProperty.call(headers, prop)) { + header = headers[prop]; - // skip nullish headers. - if (header == null) { - continue; - } + // skip nullish headers. + if (header == null) { + continue; + } - // convert all headers to arrays. - if (!Array.isArray(header)) { - header = [header]; - } + // convert all headers to arrays. + if (!Array.isArray(header)) { + header = [header]; + } - // add non-empty headers. - if (header.length) { - contents += prop + ': ' + header.join('; ') + FormData.LINE_BREAK; + // add non-empty headers. + if (header.length) { + contents += prop + ': ' + header.join('; ') + FormData.LINE_BREAK; + } } } @@ -228,7 +228,7 @@ FormData.prototype._getContentDisposition = function(value, options) { // formidable and the browser add a name property // fs- and request- streams have path property filename = path.basename(options.filename || value.name || value.path); - } else if (value.readable && value.hasOwnProperty('httpVersion')) { + } else if (value.readable && Object.prototype.hasOwnProperty.call(value, 'httpVersion')) { // or try http response filename = path.basename(value.client._httpMessage.path || ''); } @@ -256,7 +256,7 @@ FormData.prototype._getContentType = function(value, options) { } // or if it's http-reponse - if (!contentType && value.readable && value.hasOwnProperty('httpVersion')) { + if (!contentType && value.readable && Object.prototype.hasOwnProperty.call(value, 'httpVersion')) { contentType = value.headers['content-type']; } @@ -297,7 +297,7 @@ FormData.prototype.getHeaders = function(userHeaders) { }; for (header in userHeaders) { - if (userHeaders.hasOwnProperty(header)) { + if (Object.prototype.hasOwnProperty.call(userHeaders, header)) { formHeaders[header.toLowerCase()] = userHeaders[header]; } } diff --git a/test/common.js b/test/common.js index 7da855c..f3d6371 100644 --- a/test/common.js +++ b/test/common.js @@ -40,7 +40,7 @@ common.testFields = function (FIELDS, callback) { var incomingForm = new IncomingForm({uploadDir: common.dir.tmp}); incomingForm.parse(req); - + common.actions.checkForm(incomingForm, FIELDS, function (fieldsChecked) { // keep track of number of the processed fields callback(fieldsPassed - fieldsChecked); @@ -55,18 +55,17 @@ common.testFields = function (FIELDS, callback) { common.actions = {}; // generic form field population -common.actions.populateFields = function(form, fields) -{ +common.actions.populateFields = function (form, fields) { var field; for (var name in fields) { - if (!fields.hasOwnProperty(name)) { continue; } - - field = fields[name]; - // important to append ReadStreams within the same tick - if ((typeof field.value == 'function')) { - field.value = field.value(); + if (Object.prototype.hasOwnProperty.call(fields, name)) { + field = fields[name]; + // important to append ReadStreams within the same tick + if ((typeof field.value == 'function')) { + field.value = field.value(); + } + form.append(name, field.value); } - form.append(name, field.value); } }; diff --git a/test/integration/test-custom-content-type.js b/test/integration/test-custom-content-type.js index d8c1b76..534fdfb 100644 --- a/test/integration/test-custom-content-type.js +++ b/test/integration/test-custom-content-type.js @@ -67,16 +67,15 @@ server.listen(common.port, function() { var form = new FormData(); - var field; for (var name in FIELDS) { - if (!FIELDS.hasOwnProperty(name)) { continue; } - - field = FIELDS[name]; - // important to append ReadStreams within the same tick - if ((typeof field.value == 'function')) { - field.value = field.value(); + if (Object.prototype.hasOwnProperty.call(FIELDS, name)) { + var field = FIELDS[name]; + // important to append ReadStreams within the same tick + if ((typeof field.value == 'function')) { + field.value = field.value(); + } + form.append(name, field.value, field.options); } - form.append(name, field.value, field.options); } // custom params object passed to submit diff --git a/test/integration/test-pipe.js b/test/integration/test-pipe.js index c3360ef..1b41a02 100644 --- a/test/integration/test-pipe.js +++ b/test/integration/test-pipe.js @@ -49,16 +49,15 @@ server.listen(common.port, function() { var form = new FormData(); - var field; for (var name in FIELDS) { - if (!FIELDS.hasOwnProperty(name)) { continue; } - - field = FIELDS[name]; - // important to append ReadStreams within the same tick - if ((typeof field.value == 'function')) { - field.value = field.value(); + if (Object.prototype.hasOwnProperty.call(FIELDS, name)) { + var field = FIELDS[name]; + // important to append ReadStreams within the same tick + if ((typeof field.value == 'function')) { + field.value = field.value(); + } + form.append(name, field.value); } - form.append(name, field.value); } var req = http.request({ diff --git a/test/integration/test-ranged-filestream.js b/test/integration/test-ranged-filestream.js index bac1d25..8fa0caf 100644 --- a/test/integration/test-ranged-filestream.js +++ b/test/integration/test-ranged-filestream.js @@ -80,20 +80,18 @@ server.listen(common.port, function() { // add test subjects to the form for (name in testSubjects) { - if (!testSubjects.hasOwnProperty(name)) { - continue; - } - - options = {encoding: 'utf8'}; + if (Object.prototype.hasOwnProperty.call(testSubjects, name)) { + options = {encoding: 'utf8'}; - if (testSubjects[name].start) { options.start = testSubjects[name].start; } - if (testSubjects[name].end) { options.end = testSubjects[name].end; } + if (testSubjects[name].start) { options.start = testSubjects[name].start; } + if (testSubjects[name].end) { options.end = testSubjects[name].end; } - form.append(name, testSubjects[name].fsStream = fs.createReadStream(common.dir.fixture + '/' + testSubjects[name].file, options)); + form.append(name, testSubjects[name].fsStream = fs.createReadStream(common.dir.fixture + '/' + testSubjects[name].file, options)); - // calculate data size - testSubjects[name].readSize = 0; - testSubjects[name].fsStream.on('data', readSizeAccumulator.bind(testSubjects[name])); + // calculate data size + testSubjects[name].readSize = 0; + testSubjects[name].fsStream.on('data', readSizeAccumulator.bind(testSubjects[name])); + } } form.submit('http://localhost:' + common.port + '/', function(err, res) { From 84ca1d6006d65abe7b73c3e99b023aeb353e1e12 Mon Sep 17 00:00:00 2001 From: ExE Boss Date: Thu, 13 Feb 2025 19:00:00 +0100 Subject: [PATCH 13/29] =?UTF-8?q?[Fix]=20set=C2=A0`Symbol.toStringTag`=20w?= =?UTF-8?q?hen=C2=A0available=20(#573)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes #396 --- lib/form_data.js | 2 ++ package.json | 1 + 2 files changed, 3 insertions(+) diff --git a/lib/form_data.js b/lib/form_data.js index b28bf16..39222e5 100644 --- a/lib/form_data.js +++ b/lib/form_data.js @@ -7,6 +7,7 @@ var parseUrl = require('url').parse; var fs = require('fs'); var mime = require('mime-types'); var asynckit = require('asynckit'); +var setToStringTag = require('es-set-tostringtag'); var populate = require('./populate.js'); // Public API @@ -496,3 +497,4 @@ FormData.prototype._error = function(err) { FormData.prototype.toString = function () { return '[object FormData]'; }; +setToStringTag(FormData, 'FormData'); diff --git a/package.json b/package.json index 82a523e..64721e6 100644 --- a/package.json +++ b/package.json @@ -43,6 +43,7 @@ "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", "mime-types": "^2.1.35" }, "devDependencies": { From e5df7f24383342264bd73dee3274818a40d04065 Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Fri, 14 Feb 2025 13:25:13 -0800 Subject: [PATCH 14/29] [Dev Deps] pin `request` which via `tough-cookie` ^2.4 depends on `psl` See https://github.com/lupomontero/psl/issues/341 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 64721e6..d7937a3 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,7 @@ "pkgfiles": "^2.3.2", "pre-commit": "^1.2.2", "puppeteer": "^1.20.0", - "request": "^2.88.2", + "request": "~2.87.0", "rimraf": "^2.7.1", "tape": "^5.9.0", "typescript": "^3.9.10" From e46f09bb5338bff090f5cceea5119a8b37c9b147 Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Fri, 14 Feb 2025 14:59:35 -0800 Subject: [PATCH 15/29] v3.0.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d7937a3..37fb8a9 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "author": "Felix Geisendörfer (http://debuggable.com/)", "name": "form-data", "description": "A library to create readable \"multipart/form-data\" streams. Can be used to submit forms and file uploads to other web applications.", - "version": "3.0.2", + "version": "3.0.3", "repository": { "type": "git", "url": "git://github.com/form-data/form-data.git" From f5e7eb024bc3fc7e2074ff80f143a4f4cbc1dbda Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Wed, 16 Jul 2025 22:11:15 -0700 Subject: [PATCH 16/29] [eslint] update linting config --- .eslintrc | 49 +--- lib/browser.js | 4 +- lib/form_data.js | 242 ++++++++++-------- lib/populate.js | 7 +- package.json | 3 +- test/common.js | 38 +-- test/integration/test-custom-content-type.js | 50 ++-- test/integration/test-custom-filename.js | 65 ++--- .../integration/test-custom-headers-object.js | 24 +- .../integration/test-custom-headers-string.js | 28 +- test/integration/test-errors.js | 28 +- test/integration/test-form-get-length-sync.js | 33 +-- test/integration/test-form-get-length.js | 33 +-- test/integration/test-get-boundary.js | 6 +- test/integration/test-get-buffer.js | 35 +-- test/integration/test-http-response.js | 29 ++- .../test-last_boundary-line_break.js | 8 +- test/integration/test-options-override.js | 4 +- test/integration/test-pipe.js | 45 ++-- test/integration/test-ranged-filestream.js | 63 ++--- test/integration/test-request.js | 30 ++- test/integration/test-return-http-request.js | 37 +-- test/integration/test-set-boundary.js | 6 +- test/integration/test-submit-custom-header.js | 43 ++-- test/integration/test-submit-custom.js | 36 +-- test/integration/test-submit-https.js | 19 +- .../test-submit-multi-nocallback.js | 22 +- test/integration/test-submit-multi.js | 28 +- test/integration/test-submit-url-parsing.js | 9 +- test/integration/test-submit.js | 33 +-- test/integration/test-to-string.js | 6 +- test/run-browser.js | 5 +- test/run.js | 30 ++- test/static.js | 8 +- 34 files changed, 577 insertions(+), 529 deletions(-) diff --git a/.eslintrc b/.eslintrc index 111719d..6863003 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,41 +1,18 @@ { + "extends": "@ljharb/eslint-config/node/0.4", "rules": { + "callback-return": "warn", + "camelcase": "warn", + "func-style": "warn", + "eqeqeq": ["error", "always", { "null": "ignore" }], + "id-length": "warn", + "max-lines": "off", + "no-invalid-this": "warn", + "no-param-reassign": "warn", + "no-underscore-dangle": "warn", + "sort-keys": "warn", + "indent": [2, 2, {"SwitchCase": 1}], - "quotes": [2, "single"], - "linebreak-style": [2, "unix"], - "semi": [2, "always"], - "curly": [2, "multi-line"], - "handle-callback-err": [2, "^err"], - "valid-jsdoc": [2, { - "requireReturn": false, - "requireReturnDescription": false, - "prefer": { - "return": "returns" - } - }], - "require-jsdoc": [2, { - "require": { - "FunctionDeclaration": true - } - }], - "no-redeclare": [2, { "builtinGlobals": true }], - "no-shadow": [2, { "builtinGlobals": true, "hoist": "all" }], - "no-use-before-define": [2, "nofunc"], - "no-shadow-restricted-names": 2, - "no-extra-semi": 2, - "no-unused-vars": 2, - "no-undef": 2, - "no-irregular-whitespace": 2, - "no-console": 2, - "key-spacing": 0, - "strict": 0, - "dot-notation": 0, - "eol-last": 0, - "no-new": 0, - "semi-spacing": 0, - "no-multi-spaces": 0, - "eqeqeq": 0, - "no-mixed-requires": 0 }, "env": { "node": true @@ -44,5 +21,5 @@ "node_modules/*", "index.d.ts", "coverage", - ] + ], } diff --git a/lib/browser.js b/lib/browser.js index 09e7c70..8950a91 100644 --- a/lib/browser.js +++ b/lib/browser.js @@ -1,2 +1,4 @@ +'use strict'; + /* eslint-env browser */ -module.exports = typeof self == 'object' ? self.FormData : window.FormData; +module.exports = typeof self === 'object' ? self.FormData : window.FormData; diff --git a/lib/form_data.js b/lib/form_data.js index 39222e5..e8e53da 100644 --- a/lib/form_data.js +++ b/lib/form_data.js @@ -1,3 +1,5 @@ +'use strict'; + var CombinedStream = require('combined-stream'); var util = require('util'); var path = require('path'); @@ -10,12 +12,6 @@ var asynckit = require('asynckit'); var setToStringTag = require('es-set-tostringtag'); var populate = require('./populate.js'); -// Public API -module.exports = FormData; - -// make it a Stream -util.inherits(FormData, CombinedStream); - /** * Create readable "multipart/form-data" streams. * Can be used to submit forms @@ -36,34 +32,39 @@ function FormData(options) { CombinedStream.call(this); options = options || {}; - for (var option in options) { + for (var option in options) { // eslint-disable-line no-restricted-syntax this[option] = options[option]; } } +// make it a Stream +util.inherits(FormData, CombinedStream); + FormData.LINE_BREAK = '\r\n'; FormData.DEFAULT_CONTENT_TYPE = 'application/octet-stream'; -FormData.prototype.append = function(field, value, options) { +FormData.prototype.append = function (field, value, options) { options = options || {}; // allow filename as single option - if (typeof options == 'string') { - options = {filename: options}; + if (typeof options === 'string') { + options = { filename: options }; } var append = CombinedStream.prototype.append.bind(this); // all that streamy business can't handle numbers - if (typeof value == 'number') { - value = '' + value; + if (typeof value === 'number') { + value = String(value); } // https://github.com/felixge/node-form-data/issues/38 if (Array.isArray(value)) { - // Please convert your array into string - // the way web server expects it + /* + * Please convert your array into string + * the way web server expects it + */ this._error(new Error('Arrays are not supported.')); return; } @@ -79,15 +80,17 @@ FormData.prototype.append = function(field, value, options) { this._trackLength(header, value, options); }; -FormData.prototype._trackLength = function(header, value, options) { +FormData.prototype._trackLength = function (header, value, options) { var valueLength = 0; - // used w/ getLengthSync(), when length is known. - // e.g. for streaming directly from a remote server, - // w/ a known file a size, and not wanting to wait for - // incoming file to finish to get its size. + /* + * used w/ getLengthSync(), when length is known. + * e.g. for streaming directly from a remote server, + * w/ a known file a size, and not wanting to wait for + * incoming file to finish to get its size. + */ if (options.knownLength != null) { - valueLength += +options.knownLength; + valueLength += Number(options.knownLength); } else if (Buffer.isBuffer(value)) { valueLength = value.length; } else if (typeof value === 'string') { @@ -97,12 +100,10 @@ FormData.prototype._trackLength = function(header, value, options) { this._valueLength += valueLength; // @check why add CRLF? does this account for custom/multiple CRLFs? - this._overheadLength += - Buffer.byteLength(header) + - FormData.LINE_BREAK.length; + this._overheadLength += Buffer.byteLength(header) + FormData.LINE_BREAK.length; // empty or either doesn't have path or not an http response - if (!value || ( !value.path && !(value.readable && Object.prototype.hasOwnProperty.call(value, 'httpVersion')) )) { + if (!value || (!value.path && !(value.readable && Object.prototype.hasOwnProperty.call(value, 'httpVersion')))) { return; } @@ -112,27 +113,31 @@ FormData.prototype._trackLength = function(header, value, options) { } }; -FormData.prototype._lengthRetriever = function(value, callback) { +FormData.prototype._lengthRetriever = function (value, callback) { if (Object.prototype.hasOwnProperty.call(value, 'fd')) { - // take read range into a account - // `end` = Infinity –> read file till the end - // - // TODO: Looks like there is bug in Node fs.createReadStream - // it doesn't respect `end` options without `start` options - // Fix it when node fixes it. - // https://github.com/joyent/node/issues/7819 - if (value.end != undefined && value.end != Infinity && value.start != undefined) { - - // when end specified - // no need to calculate range - // inclusive, starts with 0 + /* + * take read range into a account + * `end` = Infinity –> read file till the end + * + * TODO: Looks like there is bug in Node fs.createReadStream + * it doesn't respect `end` options without `start` options + * Fix it when node fixes it. + * https://github.com/joyent/node/issues/7819 + */ + if (value.end != null && value.end !== Infinity && value.start != null) { + + /* + * when end specified + * no need to calculate range + * inclusive, starts with 0 + */ callback(null, value.end + 1 - (value.start ? value.start : 0)); // not that fast snoopy } else { // still need to fetch file size from fs - fs.stat(value.path, function(err, stat) { + fs.stat(value.path, function (err, stat) { var fileSize; @@ -149,14 +154,14 @@ FormData.prototype._lengthRetriever = function(value, callback) { // or http response } else if (Object.prototype.hasOwnProperty.call(value, 'httpVersion')) { - callback(null, +value.headers['content-length']); + callback(null, Number(value.headers['content-length'])); // or request stream http://github.com/mikeal/request } else if (Object.prototype.hasOwnProperty.call(value, 'httpModule')) { // wait till response come back - value.on('response', function(response) { + value.on('response', function (response) { value.pause(); - callback(null, +response.headers['content-length']); + callback(null, Number(response.headers['content-length'])); }); value.resume(); @@ -166,11 +171,13 @@ FormData.prototype._lengthRetriever = function(value, callback) { } }; -FormData.prototype._multiPartHeader = function(field, value, options) { - // custom header specified (as string)? - // it becomes responsible for boundary - // (e.g. to handle extra CRLFs on .NET servers) - if (typeof options.header == 'string') { +FormData.prototype._multiPartHeader = function (field, value, options) { + /* + * custom header specified (as string)? + * it becomes responsible for boundary + * (e.g. to handle extra CRLFs on .NET servers) + */ + if (typeof options.header === 'string') { return options.header; } @@ -178,26 +185,26 @@ FormData.prototype._multiPartHeader = function(field, value, options) { var contentType = this._getContentType(value, options); var contents = ''; - var headers = { + var headers = { // add custom disposition as third element or keep it two elements if not 'Content-Disposition': ['form-data', 'name="' + field + '"'].concat(contentDisposition || []), // if no content type. allow it to be empty array - 'Content-Type': [].concat(contentType || []) + 'Content-Type': [].concat(contentType || []), }; // allow custom headers. - if (typeof options.header == 'object') { + if (typeof options.header === 'object') { populate(headers, options.header); } var header; - for (var prop in headers) { + for (var prop in headers) { // eslint-disable-line no-restricted-syntax if (Object.prototype.hasOwnProperty.call(headers, prop)) { header = headers[prop]; // skip nullish headers. if (header == null) { - continue; + continue; // eslint-disable-line no-continue, no-restricted-syntax } // convert all headers to arrays. @@ -215,19 +222,19 @@ FormData.prototype._multiPartHeader = function(field, value, options) { return '--' + this.getBoundary() + FormData.LINE_BREAK + contents + FormData.LINE_BREAK; }; -FormData.prototype._getContentDisposition = function(value, options) { - - var filename - , contentDisposition - ; +FormData.prototype._getContentDisposition = function (value, options) { + var filename, + contentDisposition; if (typeof options.filepath === 'string') { // custom filepath for relative paths filename = path.normalize(options.filepath).replace(/\\/g, '/'); } else if (options.filename || value.name || value.path) { - // custom filename take precedence - // formidable and the browser add a name property - // fs- and request- streams have path property + /* + * custom filename take precedence + * formidable and the browser add a name property + * fs- and request- streams have path property + */ filename = path.basename(options.filename || value.name || value.path); } else if (value.readable && Object.prototype.hasOwnProperty.call(value, 'httpVersion')) { // or try http response @@ -241,7 +248,7 @@ FormData.prototype._getContentDisposition = function(value, options) { return contentDisposition; }; -FormData.prototype._getContentType = function(value, options) { +FormData.prototype._getContentType = function (value, options) { // use custom content-type above all var contentType = options.contentType; @@ -267,18 +274,18 @@ FormData.prototype._getContentType = function(value, options) { } // fallback to the default content type if `value` is not simple value - if (!contentType && typeof value == 'object') { + if (!contentType && typeof value === 'object') { contentType = FormData.DEFAULT_CONTENT_TYPE; } return contentType; }; -FormData.prototype._multiPartFooter = function() { - return function(next) { +FormData.prototype._multiPartFooter = function () { + return function (next) { var footer = FormData.LINE_BREAK; - var lastPart = (this._streams.length === 0); + var lastPart = this._streams.length === 0; if (lastPart) { footer += this._lastBoundary(); } @@ -287,17 +294,17 @@ FormData.prototype._multiPartFooter = function() { }.bind(this); }; -FormData.prototype._lastBoundary = function() { +FormData.prototype._lastBoundary = function () { return '--' + this.getBoundary() + '--' + FormData.LINE_BREAK; }; -FormData.prototype.getHeaders = function(userHeaders) { +FormData.prototype.getHeaders = function (userHeaders) { var header; var formHeaders = { - 'content-type': 'multipart/form-data; boundary=' + this.getBoundary() + 'content-type': 'multipart/form-data; boundary=' + this.getBoundary(), }; - for (header in userHeaders) { + for (header in userHeaders) { // eslint-disable-line no-restricted-syntax if (Object.prototype.hasOwnProperty.call(userHeaders, header)) { formHeaders[header.toLowerCase()] = userHeaders[header]; } @@ -306,11 +313,11 @@ FormData.prototype.getHeaders = function(userHeaders) { return formHeaders; }; -FormData.prototype.setBoundary = function(boundary) { +FormData.prototype.setBoundary = function (boundary) { this._boundary = boundary; }; -FormData.prototype.getBoundary = function() { +FormData.prototype.getBoundary = function () { if (!this._boundary) { this._generateBoundary(); } @@ -318,8 +325,8 @@ FormData.prototype.getBoundary = function() { return this._boundary; }; -FormData.prototype.getBuffer = function() { - var dataBuffer = new Buffer.alloc( 0 ); +FormData.prototype.getBuffer = function () { + var dataBuffer = Buffer.alloc(0); var boundary = this.getBoundary(); // Create the form content. Add Line breaks to the end of data. @@ -327,26 +334,28 @@ FormData.prototype.getBuffer = function() { if (typeof this._streams[i] !== 'function') { // Add content to the buffer. - if(Buffer.isBuffer(this._streams[i])) { - dataBuffer = Buffer.concat( [dataBuffer, this._streams[i]]); - }else { - dataBuffer = Buffer.concat( [dataBuffer, Buffer.from(this._streams[i])]); + if (Buffer.isBuffer(this._streams[i])) { + dataBuffer = Buffer.concat([dataBuffer, this._streams[i]]); + } else { + dataBuffer = Buffer.concat([dataBuffer, Buffer.from(this._streams[i])]); } // Add break after content. - if (typeof this._streams[i] !== 'string' || this._streams[i].substring( 2, boundary.length + 2 ) !== boundary) { - dataBuffer = Buffer.concat( [dataBuffer, Buffer.from(FormData.LINE_BREAK)] ); + if (typeof this._streams[i] !== 'string' || this._streams[i].substring(2, boundary.length + 2) !== boundary) { + dataBuffer = Buffer.concat([dataBuffer, Buffer.from(FormData.LINE_BREAK)]); } } } // Add the footer and return the Buffer object. - return Buffer.concat( [dataBuffer, Buffer.from(this._lastBoundary())] ); + return Buffer.concat([dataBuffer, Buffer.from(this._lastBoundary())]); }; -FormData.prototype._generateBoundary = function() { - // This generates a 50 character boundary similar to those used by Firefox. - // They are optimized for boyer-moore parsing. +FormData.prototype._generateBoundary = function () { + /* + * This generates a 50 character boundary similar to those used by Firefox. + * They are optimized for boyer-moore parsing. + */ var boundary = '--------------------------'; for (var i = 0; i < 24; i++) { boundary += Math.floor(Math.random() * 10).toString(16); @@ -355,33 +364,41 @@ FormData.prototype._generateBoundary = function() { this._boundary = boundary; }; -// Note: getLengthSync DOESN'T calculate streams length -// As workaround one can calculate file size manually -// and add it as knownLength option -FormData.prototype.getLengthSync = function() { +/* + * Note: getLengthSync DOESN'T calculate streams length + * As workaround one can calculate file size manually + * and add it as knownLength option + */ +FormData.prototype.getLengthSync = function () { var knownLength = this._overheadLength + this._valueLength; - // Don't get confused, there are 3 "internal" streams for each keyval pair - // so it basically checks if there is any value added to the form + /* + * Don't get confused, there are 3 "internal" streams for each keyval pair + * so it basically checks if there is any value added to the form + */ if (this._streams.length) { knownLength += this._lastBoundary().length; } // https://github.com/form-data/form-data/issues/40 if (!this.hasKnownLength()) { - // Some async length retrievers are present - // therefore synchronous length calculation is false. - // Please use getLength(callback) to get proper length + /* + * Some async length retrievers are present + * therefore synchronous length calculation is false. + * Please use getLength(callback) to get proper length + */ this._error(new Error('Cannot calculate proper length in synchronous way.')); } return knownLength; }; -// Public API to check if length of added values is known -// https://github.com/form-data/form-data/issues/196 -// https://github.com/form-data/form-data/issues/262 -FormData.prototype.hasKnownLength = function() { +/* + * Public API to check if length of added values is known + * https://github.com/form-data/form-data/issues/196 + * https://github.com/form-data/form-data/issues/262 + */ +FormData.prototype.hasKnownLength = function () { var hasKnownLength = true; if (this._valuesToMeasure.length) { @@ -391,7 +408,7 @@ FormData.prototype.hasKnownLength = function() { return hasKnownLength; }; -FormData.prototype.getLength = function(cb) { +FormData.prototype.getLength = function (cb) { var knownLength = this._overheadLength + this._valueLength; if (this._streams.length) { @@ -403,13 +420,13 @@ FormData.prototype.getLength = function(cb) { return; } - asynckit.parallel(this._valuesToMeasure, this._lengthRetriever, function(err, values) { + asynckit.parallel(this._valuesToMeasure, this._lengthRetriever, function (err, values) { if (err) { cb(err); return; } - values.forEach(function(length) { + values.forEach(function (length) { knownLength += length; }); @@ -417,22 +434,23 @@ FormData.prototype.getLength = function(cb) { }); }; -FormData.prototype.submit = function(params, cb) { - var request - , options - , defaults = {method: 'post'} - ; +FormData.prototype.submit = function (params, cb) { + var request; + var options; + var defaults = { method: 'post' }; - // parse provided url if it's string - // or treat it as options object - if (typeof params == 'string') { + /* + * parse provided url if it's string + * or treat it as options object + */ + if (typeof params === 'string') { params = parseUrl(params); options = populate({ port: params.port, path: params.pathname, host: params.hostname, - protocol: params.protocol + protocol: params.protocol, }, defaults); // use custom params @@ -441,7 +459,7 @@ FormData.prototype.submit = function(params, cb) { options = populate(params, defaults); // if no port provided use default one if (!options.port) { - options.port = options.protocol == 'https:' ? 443 : 80; + options.port = options.protocol === 'https:' ? 443 : 80; } } @@ -449,14 +467,14 @@ FormData.prototype.submit = function(params, cb) { options.headers = this.getHeaders(params.headers); // https if specified, fallback to http in any other case - if (options.protocol == 'https:') { + if (options.protocol === 'https:') { request = https.request(options); } else { request = http.request(options); } // get content length and fire away - this.getLength(function(err, length) { + this.getLength(function (err, length) { if (err) { this._error(err); return; @@ -486,7 +504,7 @@ FormData.prototype.submit = function(params, cb) { return request; }; -FormData.prototype._error = function(err) { +FormData.prototype._error = function (err) { if (!this.error) { this.error = err; this.pause(); @@ -498,3 +516,5 @@ FormData.prototype.toString = function () { return '[object FormData]'; }; setToStringTag(FormData, 'FormData'); + +module.exports = FormData; diff --git a/lib/populate.js b/lib/populate.js index 4d35738..734feef 100644 --- a/lib/populate.js +++ b/lib/populate.js @@ -1,8 +1,9 @@ +'use strict'; + // populates missing values -module.exports = function(dst, src) { +module.exports = function (dst, src) { - Object.keys(src).forEach(function(prop) - { + Object.keys(src).forEach(function (prop) { dst[prop] = dst[prop] || src[prop]; }); diff --git a/package.json b/package.json index 37fb8a9..f2d961a 100644 --- a/package.json +++ b/package.json @@ -47,12 +47,13 @@ "mime-types": "^2.1.35" }, "devDependencies": { + "@ljharb/eslint-config": "^21.2.0", "@types/node": "^12.20.55", "browserify": "^13.3.0", "browserify-istanbul": "^2.0.0", "coveralls": "^3.1.1", "cross-spawn": "^6.0.6", - "eslint": "^6.8.0", + "eslint": "=8.8.0", "fake": "^0.2.2", "far": "^0.0.7", "formidable": "^1.2.6", diff --git a/test/common.js b/test/common.js index f3d6371..479fd6d 100644 --- a/test/common.js +++ b/test/common.js @@ -1,3 +1,5 @@ +'use strict'; + var fs = require('fs'); var path = require('path'); var assert = require('assert'); @@ -12,7 +14,7 @@ var rootDir = path.join(__dirname, '..'); common.dir = { lib: path.join(rootDir, '/lib'), fixture: path.join(rootDir, '/test/fixture'), - tmp: path.join(rootDir, '/test/tmp') + tmp: path.join(rootDir, '/test/tmp'), }; common.defaultTypeValue = function () { @@ -37,7 +39,7 @@ common.testFields = function (FIELDS, callback) { return http.createServer(function (req, res) { - var incomingForm = new IncomingForm({uploadDir: common.dir.tmp}); + var incomingForm = new IncomingForm({ uploadDir: common.dir.tmp }); incomingForm.parse(req); @@ -57,11 +59,11 @@ common.actions = {}; // generic form field population common.actions.populateFields = function (form, fields) { var field; - for (var name in fields) { + for (var name in fields) { // eslint-disable-line no-restricted-syntax if (Object.prototype.hasOwnProperty.call(fields, name)) { field = fields[name]; // important to append ReadStreams within the same tick - if ((typeof field.value == 'function')) { + if (typeof field.value === 'function') { field.value = field.value(); } form.append(name, field.value); @@ -70,9 +72,8 @@ common.actions.populateFields = function (form, fields) { }; // generic form submit -common.actions.submit = function(form, server) -{ - return form.submit('http://localhost:' + common.port + '/', function(err, res) { +common.actions.submit = function (form, server) { + return form.submit('http://localhost:' + common.port + '/', function (err, res) { if (err) { throw err; @@ -87,36 +88,35 @@ common.actions.submit = function(form, server) }); }; -common.actions.checkForm = function(form, fields, callback) -{ +common.actions.checkForm = function (form, fields, callback) { var fieldChecked = 0; form - .on('field', function(name, value) { - fieldChecked++; + .on('field', function (name, value) { + fieldChecked += 1; common.actions.formOnField(fields, name, value); }) - .on('file', function(name, file) { - fieldChecked++; + .on('file', function (name, file) { + fieldChecked += 1; common.actions.formOnFile(fields, name, file); }) - .on('end', function() { + .on('end', function () { callback(fieldChecked); }); }; -common.actions.basicFormOnField = function(name, value) { +common.actions.basicFormOnField = function (name, value) { assert.strictEqual(name, 'my_field'); assert.strictEqual(value, 'my_value'); }; -common.actions.formOnField = function(FIELDS, name, value) { +common.actions.formOnField = function (FIELDS, name, value) { assert.ok(name in FIELDS); var field = FIELDS[name]; - assert.strictEqual(value, field.value + ''); + assert.strictEqual(value, String(field.value)); }; -common.actions.formOnFile = function(FIELDS, name, file) { +common.actions.formOnFile = function (FIELDS, name, file) { assert.ok(name in FIELDS); var field = FIELDS[name]; assert.strictEqual(file.name, path.basename(field.value.path || field.name)); @@ -124,7 +124,7 @@ common.actions.formOnFile = function(FIELDS, name, file) { }; // after form has finished parsing -common.actions.formOnEnd = function(res) { +common.actions.formOnEnd = function (res) { res.writeHead(200); res.end('done'); }; diff --git a/test/integration/test-custom-content-type.js b/test/integration/test-custom-content-type.js index 534fdfb..a193fc9 100644 --- a/test/integration/test-custom-content-type.js +++ b/test/integration/test-custom-content-type.js @@ -1,3 +1,5 @@ +'use strict'; + var common = require('../common'); var assert = common.assert; var http = require('http'); @@ -5,38 +7,40 @@ var mime = require('mime-types'); var fs = require('fs'); var FormData = require(common.dir.lib + '/form_data'); -// wrap non simple values into function -// just to deal with ReadStream "autostart" +/* + * wrap non simple values into function + * just to deal with ReadStream "autostart" + */ var FIELDS = { - 'no_type': { - value: 'my_value' + no_type: { + value: 'my_value', }, - 'custom_type': { + custom_type: { value: 'my_value', expectedType: 'image/png', options: { - contentType: 'image/png' - } + contentType: 'image/png', + }, }, - 'default_type': { + default_type: { expectedType: FormData.DEFAULT_CONTENT_TYPE, - value: common.defaultTypeValue + value: common.defaultTypeValue, }, - 'implicit_type': { + implicit_type: { expectedType: mime.lookup(common.dir.fixture + '/unicycle.jpg'), - value: function() { return fs.createReadStream(common.dir.fixture + '/unicycle.jpg'); } + value: function () { return fs.createReadStream(common.dir.fixture + '/unicycle.jpg'); }, }, - 'overridden_type': { + overridden_type: { expectedType: 'image/png', options: { - contentType: 'image/png' + contentType: 'image/png', }, - value: function() { return fs.createReadStream(common.dir.fixture + '/unicycle.jpg'); } - } + value: function () { return fs.createReadStream(common.dir.fixture + '/unicycle.jpg'); }, + }, }; var fieldsPassed = false; -var server = http.createServer(function(req, res) { +var server = http.createServer(function (req, res) { var body = ''; var boundry = req.headers['content-type'].split('boundary=').pop(); @@ -51,10 +55,10 @@ var server = http.createServer(function(req, res) { for (var i = 0; i < fieldNames.length; i++) { assert.ok(fields[i].indexOf('name="' + fieldNames[i] + '"') > -1); - if (!FIELDS[fieldNames[i]].expectedType) { - assert.equal(fields[i].indexOf('Content-Type'), -1, 'Expecting ' + fieldNames[i] + ' not to have Content-Type'); - } else { + if (FIELDS[fieldNames[i]].expectedType) { assert.ok(fields[i].indexOf('Content-Type: ' + FIELDS[fieldNames[i]].expectedType) > -1, 'Expecting ' + fieldNames[i] + ' to have Content-Type ' + FIELDS[fieldNames[i]].expectedType); + } else { + assert.equal(fields[i].indexOf('Content-Type'), -1, 'Expecting ' + fieldNames[i] + ' not to have Content-Type'); } } @@ -63,15 +67,15 @@ var server = http.createServer(function(req, res) { }); }); -server.listen(common.port, function() { +server.listen(common.port, function () { var form = new FormData(); - for (var name in FIELDS) { + for (var name in FIELDS) { // eslint-disable-line no-restricted-syntax if (Object.prototype.hasOwnProperty.call(FIELDS, name)) { var field = FIELDS[name]; // important to append ReadStreams within the same tick - if ((typeof field.value == 'function')) { + if (typeof field.value === 'function') { field.value = field.value(); } form.append(name, field.value, field.options); @@ -82,6 +86,6 @@ server.listen(common.port, function() { common.actions.submit(form, server); }); -process.on('exit', function() { +process.on('exit', function () { assert.ok(fieldsPassed); }); diff --git a/test/integration/test-custom-filename.js b/test/integration/test-custom-filename.js index c296eb5..320afcf 100644 --- a/test/integration/test-custom-filename.js +++ b/test/integration/test-custom-filename.js @@ -1,16 +1,18 @@ +'use strict'; + /* -test custom filename and content-type: -re: https://github.com/felixge/node-form-data/issues/29 -*/ - -var common = require('../common'); -var assert = common.assert; -var mime = require('mime-types'); -var http = require('http'); -var fs = require('fs'); -var path = require('path'); - -var FormData = require(common.dir.lib + '/form_data'); + *test custom filename and content-type: + *re: https://github.com/felixge/node-form-data/issues/29 + */ + +var common = require('../common'); +var assert = common.assert; +var mime = require('mime-types'); +var http = require('http'); +var fs = require('fs'); +var path = require('path'); + +var FormData = require(common.dir.lib + '/form_data'); var IncomingForm = require('formidable').IncomingForm; var knownFile = path.join(common.dir.fixture, 'unicycle.jpg'); @@ -19,50 +21,49 @@ var relativeFile = path.relative(path.join(knownFile, '..', '..'), knownFile); var options = { filename: 'test.png', - contentType: 'image/gif' + contentType: 'image/gif', }; -var server = http.createServer(function(req, res) { +var server = http.createServer(function (req, res) { - var form = new IncomingForm({uploadDir: common.dir.tmp}); + var form = new IncomingForm({ uploadDir: common.dir.tmp }); form.parse(req, function (err, fields, files) { assert(!err); assert('custom_everything' in files); - assert.strictEqual(files['custom_everything'].name, options.filename, 'Expects custom filename'); - assert.strictEqual(files['custom_everything'].type, options.contentType, 'Expects custom content-type'); + assert.strictEqual(files.custom_everything.name, options.filename, 'Expects custom filename'); + assert.strictEqual(files.custom_everything.type, options.contentType, 'Expects custom content-type'); assert('custom_filename' in files); - assert.strictEqual(files['custom_filename'].name, options.filename, 'Expects custom filename'); - assert.strictEqual(files['custom_filename'].type, mime.lookup(knownFile), 'Expects original content-type'); + assert.strictEqual(files.custom_filename.name, options.filename, 'Expects custom filename'); + assert.strictEqual(files.custom_filename.type, mime.lookup(knownFile), 'Expects original content-type'); assert('custom_filepath' in files); - assert.strictEqual(files['custom_filepath'].name, relativeFile.replace(/\\/g, '/'), 'Expects custom filepath'); - assert.strictEqual(files['custom_filepath'].type, mime.lookup(knownFile), 'Expects original content-type'); + assert.strictEqual(files.custom_filepath.name, relativeFile.replace(/\\/g, '/'), 'Expects custom filepath'); + assert.strictEqual(files.custom_filepath.type, mime.lookup(knownFile), 'Expects original content-type'); assert('unknown_with_filename' in files); - assert.strictEqual(files['unknown_with_filename'].name, options.filename, 'Expects custom filename'); - assert.strictEqual(files['unknown_with_filename'].type, mime.lookup(options.filename), 'Expects filename-derived content-type'); + assert.strictEqual(files.unknown_with_filename.name, options.filename, 'Expects custom filename'); + assert.strictEqual(files.unknown_with_filename.type, mime.lookup(options.filename), 'Expects filename-derived content-type'); assert('unknown_with_filename_as_object' in files); - assert.strictEqual(files['unknown_with_filename_as_object'].name, options.filename, 'Expects custom filename'); - assert.strictEqual(files['unknown_with_filename_as_object'].type, mime.lookup(options.filename), 'Expects filename-derived content-type'); + assert.strictEqual(files.unknown_with_filename_as_object.name, options.filename, 'Expects custom filename'); + assert.strictEqual(files.unknown_with_filename_as_object.type, mime.lookup(options.filename), 'Expects filename-derived content-type'); assert('unknown_with_name_prop' in files); - assert.strictEqual(files['unknown_with_name_prop'].name, options.filename, 'Expects custom filename'); - assert.strictEqual(files['unknown_with_name_prop'].type, mime.lookup(options.filename), 'Expects filename-derived content-type'); + assert.strictEqual(files.unknown_with_name_prop.name, options.filename, 'Expects custom filename'); + assert.strictEqual(files.unknown_with_name_prop.type, mime.lookup(options.filename), 'Expects filename-derived content-type'); assert('unknown_everything' in files); - assert.strictEqual(files['unknown_everything'].type, FormData.DEFAULT_CONTENT_TYPE, 'Expects default content-type'); + assert.strictEqual(files.unknown_everything.type, FormData.DEFAULT_CONTENT_TYPE, 'Expects default content-type'); res.writeHead(200); res.end('done'); }); }); - -server.listen(common.port, function() { +server.listen(common.port, function () { var form = new FormData(); // Explicit contentType and filename. @@ -72,9 +73,9 @@ server.listen(common.port, function() { // Filename only with unknown file form.append('unknown_with_filename', fs.createReadStream(unknownFile), options.filename); // Filename only with unknown file - form.append('unknown_with_filename_as_object', fs.createReadStream(unknownFile), {filename: options.filename}); + form.append('unknown_with_filename_as_object', fs.createReadStream(unknownFile), { filename: options.filename }); // Filename with relative path - form.append('custom_filepath', fs.createReadStream(knownFile), {filepath: relativeFile}); + form.append('custom_filepath', fs.createReadStream(knownFile), { filepath: relativeFile }); // No options or implicit file type from extension on name property. var customNameStream = fs.createReadStream(unknownFile); customNameStream.name = options.filename; diff --git a/test/integration/test-custom-headers-object.js b/test/integration/test-custom-headers-object.js index dd40187..504f6d5 100644 --- a/test/integration/test-custom-headers-object.js +++ b/test/integration/test-custom-headers-object.js @@ -1,7 +1,9 @@ +'use strict'; + /* -test custom headers object. -https://github.com/form-data/form-data/issues/133 -*/ + * test custom headers object. + * https://github.com/form-data/form-data/issues/133 + */ var common = require('../common'); var assert = common.assert; @@ -13,9 +15,8 @@ var testHeader = { 'X-Test-Fake': 123 }; var expectedLength; - -var server = http.createServer(function(req, res) { - assert.ok( typeof req.headers['content-length'] !== 'undefined' ); +var server = http.createServer(function (req, res) { + assert.ok(typeof req.headers['content-length'] !== 'undefined'); assert.equal(req.headers['content-length'], expectedLength); req.on('data', function (data) { @@ -29,16 +30,17 @@ var server = http.createServer(function(req, res) { res.end('done'); }); - -server.listen(common.port, function() { +server.listen(common.port, function () { var form = new FormData(); var options = { header: testHeader, - // override content-length, - // much lower than actual buffer size (1000) - knownLength: 1 + /* + * override content-length, + * much lower than actual buffer size (1000) + */ + knownLength: 1, }; var bufferData = []; diff --git a/test/integration/test-custom-headers-string.js b/test/integration/test-custom-headers-string.js index a664a1e..890432e 100644 --- a/test/integration/test-custom-headers-string.js +++ b/test/integration/test-custom-headers-string.js @@ -1,7 +1,9 @@ +'use strict'; + /* -test custom headers, added in pull request: -https://github.com/felixge/node-form-data/pull/17 -*/ + * test custom headers, added in pull request: + * https://github.com/felixge/node-form-data/pull/17 + */ var common = require('../common'); var assert = common.assert; @@ -15,9 +17,8 @@ var testHeader = 'X-Test-Fake: 123'; var expectedLength; - -var server = http.createServer(function(req, res) { - assert.ok( typeof req.headers['content-length'] !== 'undefined' ); +var server = http.createServer(function (req, res) { + assert.ok(typeof req.headers['content-length'] !== 'undefined'); assert.equal(req.headers['content-length'], expectedLength); req.on('data', function (data) { @@ -31,19 +32,18 @@ var server = http.createServer(function(req, res) { res.end('done'); }); - -server.listen(common.port, function() { +server.listen(common.port, function () { var form = new FormData(); var options = { header: - CRLF + '--' + form.getBoundary() + CRLF + - testHeader + - CRLF + CRLF, + CRLF + '--' + form.getBoundary() + CRLF + testHeader + CRLF + CRLF, - // override content-length, - // much lower than actual buffer size (1000) - knownLength: 1 + /* + * override content-length, + * much lower than actual buffer size (1000) + */ + knownLength: 1, }; var bufferData = []; diff --git a/test/integration/test-errors.js b/test/integration/test-errors.js index 1129226..b57d6fa 100644 --- a/test/integration/test-errors.js +++ b/test/integration/test-errors.js @@ -1,3 +1,5 @@ +'use strict'; + var common = require('../common'); var assert = common.assert; var FormData = require(common.dir.lib + '/form_data'); @@ -14,31 +16,30 @@ var http = require('http'); var callback = fake.callback('testAppendArray-onError-append'); fake.expectAnytime(callback, ['Arrays are not supported.']); - form.on('error', function(err) { + form.on('error', function (err) { // workaround for expectAnytime handling objects callback(err.message); }); form.append('my_array', ['bird', 'cute']); -})(); - +}()); (function testGetLengthSync() { var fields = [ { name: 'my_string', - value: 'Test 123' + value: 'Test 123', }, { name: 'my_image', - value: fs.createReadStream(common.dir.fixture + '/unicycle.jpg') - } + value: fs.createReadStream(common.dir.fixture + '/unicycle.jpg'), + }, ]; var form = new FormData(); var expectedLength = 0; - fields.forEach(function(field) { + fields.forEach(function (field) { form.append(field.name, field.value); if (field.value.path) { var stat = fs.statSync(field.value.path); @@ -49,11 +50,10 @@ var http = require('http'); }); expectedLength += form._overheadLength + form._lastBoundary().length; - var callback = fake.callback('testGetLengthSync-onError-getLengthSync'); fake.expectAnytime(callback, ['Cannot calculate proper length in synchronous way.']); - form.on('error', function(err) { + form.on('error', function (err) { // workaroud for expectAnytime handling objects callback(err.message); }); @@ -62,7 +62,7 @@ var http = require('http'); // getLengthSync DOESN'T calculate streams length assert.ok(expectedLength > calculatedLength); -})(); +}()); (function testStreamError() { var req; @@ -75,14 +75,14 @@ var http = require('http'); form.append('fake-stream', src); - form.on('error', function(err) { + form.on('error', function (err) { assert.equal(err.code, 'ENOENT'); assert.equal(err.path, fakePath); - req.on('error', function() {}); + req.on('error', function () {}); server.close(); }); - server.listen(common.port, function() { + server.listen(common.port, function () { req = form.submit(addr); }); -})(); +}()); diff --git a/test/integration/test-form-get-length-sync.js b/test/integration/test-form-get-length-sync.js index e212a76..c092c92 100644 --- a/test/integration/test-form-get-length-sync.js +++ b/test/integration/test-form-get-length-sync.js @@ -1,3 +1,5 @@ +'use strict'; + var common = require('../common'); var assert = common.assert; var FormData = require(common.dir.lib + '/form_data'); @@ -7,64 +9,63 @@ var fs = require('fs'); var fields = [ { name: 'my_number', - value: 123 + value: 123, }, { name: 'my_string', - value: 'Test 123' + value: 'Test 123', }, { name: 'my_buffer', - value: new Buffer('123') - } + value: new Buffer('123'), + }, ]; var form = new FormData(); var expectedLength = 0; - fields.forEach(function(field) { + fields.forEach(function (field) { form.append(field.name, field.value); - expectedLength += ('' + field.value).length; + expectedLength += String(field.value).length; }); expectedLength += form._overheadLength + form._lastBoundary().length; var calculatedLength = form.getLengthSync(); assert.equal(expectedLength, calculatedLength); -})(); - +}()); (function testGetLengthSyncWithKnownLength() { var fields = [ { name: 'my_number', - value: 123 + value: 123, }, { name: 'my_string', - value: 'Test 123' + value: 'Test 123', }, { name: 'my_buffer', - value: new Buffer('123') + value: new Buffer('123'), }, { name: 'my_image', value: fs.createReadStream(common.dir.fixture + '/unicycle.jpg'), - options: { knownLength: fs.statSync(common.dir.fixture + '/unicycle.jpg').size } - } + options: { knownLength: fs.statSync(common.dir.fixture + '/unicycle.jpg').size }, + }, ]; var form = new FormData(); var expectedLength = 0; - fields.forEach(function(field) { + fields.forEach(function (field) { form.append(field.name, field.value, field.options); if (field.value.path) { var stat = fs.statSync(field.value.path); expectedLength += stat.size; } else { - expectedLength += ('' + field.value).length; + expectedLength += String(field.value).length; } }); expectedLength += form._overheadLength + form._lastBoundary().length; @@ -72,4 +73,4 @@ var fs = require('fs'); var calculatedLength = form.getLengthSync(); assert.equal(expectedLength, calculatedLength); -})(); +}()); diff --git a/test/integration/test-form-get-length.js b/test/integration/test-form-get-length.js index 6b03069..c6c6e7e 100644 --- a/test/integration/test-form-get-length.js +++ b/test/integration/test-form-get-length.js @@ -1,3 +1,5 @@ +'use strict'; + var common = require('../common'); var assert = common.assert; var FormData = require(common.dir.lib + '/form_data'); @@ -13,7 +15,7 @@ var fs = require('fs'); // Make sure our response is async assert.strictEqual(calls.length, 0); -})(); +}()); (function testUtf8String() { var FIELD = 'my_field'; @@ -23,14 +25,11 @@ var fs = require('fs'); form.append(FIELD, VALUE); var callback = fake.callback('testUtf8String-getLength'); - var expectedLength = - form._overheadLength + - Buffer.byteLength(VALUE) + - form._lastBoundary().length; + var expectedLength = form._overheadLength + Buffer.byteLength(VALUE) + form._lastBoundary().length; fake.expectAnytime(callback, [null, expectedLength]); form.getLength(callback); -})(); +}()); (function testBuffer() { var FIELD = 'my_field'; @@ -40,40 +39,36 @@ var fs = require('fs'); form.append(FIELD, VALUE); var callback = fake.callback('testBuffer-getLength'); - var expectedLength = - form._overheadLength + - VALUE.length + - form._lastBoundary().length; + var expectedLength = form._overheadLength + VALUE.length + form._lastBoundary().length; fake.expectAnytime(callback, [null, expectedLength]); form.getLength(callback); -})(); - +}()); (function testStringFileBufferFile() { var fields = [ { name: 'my_field', - value: 'Test 123' + value: 'Test 123', }, { name: 'my_image', - value: fs.createReadStream(common.dir.fixture + '/unicycle.jpg') + value: fs.createReadStream(common.dir.fixture + '/unicycle.jpg'), }, { name: 'my_buffer', - value: new Buffer('123') + value: new Buffer('123'), }, { name: 'my_txt', - value: fs.createReadStream(common.dir.fixture + '/veggies.txt') - } + value: fs.createReadStream(common.dir.fixture + '/veggies.txt'), + }, ]; var form = new FormData(); var expectedLength = 0; - fields.forEach(function(field) { + fields.forEach(function (field) { form.append(field.name, field.value); if (field.value.path) { var stat = fs.statSync(field.value.path); @@ -88,4 +83,4 @@ var fs = require('fs'); var callback = fake.callback('testStringFileBufferFile-getLength'); fake.expectAnytime(callback, [null, expectedLength]); form.getLength(callback); -})(); +}()); diff --git a/test/integration/test-get-boundary.js b/test/integration/test-get-boundary.js index 6dc2fb2..6faa0ce 100644 --- a/test/integration/test-get-boundary.js +++ b/test/integration/test-get-boundary.js @@ -1,3 +1,5 @@ +'use strict'; + var common = require('../common'); var assert = common.assert; @@ -9,10 +11,10 @@ var FormData = require(common.dir.lib + '/form_data'); assert.equal(boundary, form.getBoundary()); assert.equal(boundary.length, 50); -})(); +}()); (function testUniqueBoundaryPerForm() { var formA = new FormData(); var formB = new FormData(); assert.notEqual(formA.getBoundary(), formB.getBoundary()); -})(); +}()); diff --git a/test/integration/test-get-buffer.js b/test/integration/test-get-buffer.js index cca6fa0..485a3b5 100644 --- a/test/integration/test-get-buffer.js +++ b/test/integration/test-get-buffer.js @@ -1,3 +1,5 @@ +'use strict'; + var common = require('../common'); var assert = common.assert; @@ -5,11 +7,11 @@ var FormData = require(common.dir.lib + '/form_data'); (function testTypeIsBuffer() { var form = new FormData(); - form.append( 'String', 'Some random string' ); + form.append('String', 'Some random string'); var buffer = form.getBuffer(); assert.equal(typeof buffer === 'object' && Buffer.isBuffer(buffer), true); -})(); +}()); (function testBufferIsValid() { var form = new FormData(); @@ -19,36 +21,25 @@ var FormData = require(common.dir.lib + '/form_data'); var intName = 'Int'; var intValue = 1549873167987; var bufferName = 'Buffer'; - var bufferValue = Buffer.from([0x00,0x4a,0x45,0x46,0x46,0x52,0x45,0x59,0x255]); + var bufferValue = Buffer.from([0x00, 0x4a, 0x45, 0x46, 0x46, 0x52, 0x45, 0x59, 0x255]); // Fill the formData object - form.append( stringName, stringValue ); - form.append( intName, intValue ); - form.append( bufferName, bufferValue ); + form.append(stringName, stringValue); + form.append(intName, intValue); + form.append(bufferName, bufferValue); // Get the resulting Buffer var buffer = form.getBuffer(); // Generate expected code. var boundary = form.getBoundary(); - var expected = Buffer.concat( [ - Buffer.from( '--' + boundary + FormData.LINE_BREAK + - 'Content-Disposition: form-data; name="' + stringName + '"' + FormData.LINE_BREAK + - FormData.LINE_BREAK + - stringValue + FormData.LINE_BREAK + - '--' + boundary + FormData.LINE_BREAK + - 'Content-Disposition: form-data; name="' + intName + '"' + FormData.LINE_BREAK + - FormData.LINE_BREAK + - intValue + FormData.LINE_BREAK + - '--' + boundary + FormData.LINE_BREAK + - 'Content-Disposition: form-data; name="' + bufferName + '"' + FormData.LINE_BREAK + - 'Content-Type: application/octet-stream' + FormData.LINE_BREAK + - FormData.LINE_BREAK), + var expected = Buffer.concat([ + Buffer.from('--' + boundary + FormData.LINE_BREAK + 'Content-Disposition: form-data; name="' + stringName + '"' + FormData.LINE_BREAK + FormData.LINE_BREAK + stringValue + FormData.LINE_BREAK + '--' + boundary + FormData.LINE_BREAK + 'Content-Disposition: form-data; name="' + intName + '"' + FormData.LINE_BREAK + FormData.LINE_BREAK + intValue + FormData.LINE_BREAK + '--' + boundary + FormData.LINE_BREAK + 'Content-Disposition: form-data; name="' + bufferName + '"' + FormData.LINE_BREAK + 'Content-Type: application/octet-stream' + FormData.LINE_BREAK + FormData.LINE_BREAK), bufferValue, - Buffer.from( FormData.LINE_BREAK + '--' + boundary + '--' + FormData.LINE_BREAK ) - ] ); + Buffer.from(FormData.LINE_BREAK + '--' + boundary + '--' + FormData.LINE_BREAK), + ]); // Test if the buffer content, equals the expected buffer. assert.equal(buffer.length, expected.length); assert.equal(buffer.toString('hex'), expected.toString('hex')); -})(); +}()); diff --git a/test/integration/test-http-response.js b/test/integration/test-http-response.js index bb420c8..a9ca8e2 100644 --- a/test/integration/test-http-response.js +++ b/test/integration/test-http-response.js @@ -1,3 +1,5 @@ +'use strict'; + var common = require('../common'); var assert = common.assert; var http = require('http'); @@ -14,34 +16,34 @@ var options = { method: 'get', port: parsedUrl.port || 80, path: parsedUrl.pathname, - host: parsedUrl.hostname + host: parsedUrl.hostname, }; var FIELDS = { - 'my_field': { - value: 'my_value' + my_field: { + value: 'my_value', }, - 'my_buffer': { + my_buffer: { type: FormData.DEFAULT_CONTENT_TYPE, - value: common.defaultTypeValue + value: common.defaultTypeValue, }, - 'remote_file': { + remote_file: { value: 'TBD', - name: remoteFile - } + name: remoteFile, + }, }; // request static file -http.request(options, function(response) { +http.request(options, function (response) { var form = new FormData(); // add http response to the form fields - FIELDS['remote_file'].value = response; + FIELDS.remote_file.value = response; common.actions.populateFields(form, FIELDS); - server.listen(common.port, function() { + server.listen(common.port, function () { common.actions.submit(form, server); }); @@ -51,11 +53,10 @@ http.request(options, function(response) { var fieldsPassed = Object.keys(FIELDS).length; // prepare form-receiving http server -server = common.testFields(FIELDS, function(fields){ +server = common.testFields(FIELDS, function (fields) { fieldsPassed = fields; }); - -process.on('exit', function() { +process.on('exit', function () { assert.strictEqual(fieldsPassed, 0); }); diff --git a/test/integration/test-last_boundary-line_break.js b/test/integration/test-last_boundary-line_break.js index 625fefc..bb5f8cc 100644 --- a/test/integration/test-last_boundary-line_break.js +++ b/test/integration/test-last_boundary-line_break.js @@ -1,3 +1,5 @@ +'use strict'; + var http = require('http'); var common = require('../common'); var assert = common.assert; @@ -17,18 +19,18 @@ function submitForm() { } // create https server -server = http.createServer(function(req, res) { +server = http.createServer(function (req, res) { var body = ''; req.setEncoding('utf8'); // old and simple - req.on('data', function(data) { + req.on('data', function (data) { body += data; }); - req.on('end', function() { + req.on('end', function () { // last character(s) sequence equals predefined line break assert.strictEqual(body.substr(-1 * FormData.LINE_BREAK.length), FormData.LINE_BREAK); diff --git a/test/integration/test-options-override.js b/test/integration/test-options-override.js index 337842e..fd08804 100644 --- a/test/integration/test-options-override.js +++ b/test/integration/test-options-override.js @@ -1,6 +1,8 @@ +'use strict'; + var common = require('../common'); var assert = common.assert; var FormData = require(common.dir.lib + '/form_data'); -var form = new FormData({maxDataSize: 20 * 1024 * 1024}); +var form = new FormData({ maxDataSize: 20 * 1024 * 1024 }); assert.strictEqual(form.maxDataSize, 20 * 1024 * 1024); diff --git a/test/integration/test-pipe.js b/test/integration/test-pipe.js index 1b41a02..32bb1aa 100644 --- a/test/integration/test-pipe.js +++ b/test/integration/test-pipe.js @@ -1,3 +1,5 @@ +'use strict'; + var common = require('../common'); var assert = common.assert; var http = require('http'); @@ -9,35 +11,36 @@ var IncomingForm = require('formidable').IncomingForm; var remoteFile = 'http://localhost:' + common.staticPort + '/unicycle.jpg'; -// wrap non simple values into function -// just to deal with ReadStream "autostart" +/* + * wrap non simple values into function + * just to deal with ReadStream "autostart" + */ var FIELDS = { - 'my_field': { - value: 'my_value' + my_field: { + value: 'my_value', }, - 'my_buffer': { + my_buffer: { type: FormData.DEFAULT_CONTENT_TYPE, - value: common.defaultTypeValue + value: common.defaultTypeValue, }, - 'my_file': { + my_file: { type: mime.lookup(common.dir.fixture + '/unicycle.jpg'), - value: function() { return fs.createReadStream(common.dir.fixture + '/unicycle.jpg'); } + value: function () { return fs.createReadStream(common.dir.fixture + '/unicycle.jpg'); }, }, - 'remote_file': { + remote_file: { type: mime.lookup(common.dir.fixture + '/unicycle.jpg'), - value: function() { return request(remoteFile); } - } + value: function () { return request(remoteFile); }, + }, }; var fieldsPassed = Object.keys(FIELDS).length; -var server = http.createServer(function(req, res) { +var server = http.createServer(function (req, res) { - var form = new IncomingForm({uploadDir: common.dir.tmp}); + var form = new IncomingForm({ uploadDir: common.dir.tmp }); form.parse(req); - common.actions.checkForm(form, FIELDS, function(fieldsChecked) - { + common.actions.checkForm(form, FIELDS, function (fieldsChecked) { // keep track of number of the processed fields fieldsPassed = fieldsPassed - fieldsChecked; // finish it @@ -45,15 +48,15 @@ var server = http.createServer(function(req, res) { }); }); -server.listen(common.port, function() { +server.listen(common.port, function () { var form = new FormData(); - for (var name in FIELDS) { + for (var name in FIELDS) { // eslint-disable-line no-restricted-syntax if (Object.prototype.hasOwnProperty.call(FIELDS, name)) { var field = FIELDS[name]; // important to append ReadStreams within the same tick - if ((typeof field.value == 'function')) { + if (typeof field.value === 'function') { field.value = field.value(); } form.append(name, field.value); @@ -64,12 +67,12 @@ server.listen(common.port, function() { method: 'post', port: common.port, path: '/upload', - headers: form.getHeaders() + headers: form.getHeaders(), }); form.pipe(req); - req.on('response', function(res) { + req.on('response', function (res) { // unstuck new streams res.resume(); @@ -78,6 +81,6 @@ server.listen(common.port, function() { }); }); -process.on('exit', function() { +process.on('exit', function () { assert.strictEqual(fieldsPassed, 0); }); diff --git a/test/integration/test-ranged-filestream.js b/test/integration/test-ranged-filestream.js index 8fa0caf..6e3c45a 100644 --- a/test/integration/test-ranged-filestream.js +++ b/test/integration/test-ranged-filestream.js @@ -1,36 +1,38 @@ +'use strict'; + /* -test ranged fs.createReadStream -re: https://github.com/felixge/node-form-data/issues/71 -*/ + * test ranged fs.createReadStream + * re: https://github.com/felixge/node-form-data/issues/71 + */ -var common = require('../common'); -var assert = common.assert; -var http = require('http'); -var fs = require('fs'); +var common = require('../common'); +var assert = common.assert; +var http = require('http'); +var fs = require('fs'); -var FormData = require(common.dir.lib + '/form_data'); +var FormData = require(common.dir.lib + '/form_data'); var IncomingForm = require('formidable').IncomingForm; var testSubjects = { - 'a_file': { + a_file: { file: 'veggies.txt', start: 8, - end: 18 - }, 'b_file': { + end: 18, + }, b_file: { file: 'veggies.txt', - start: 6 - }, 'c_file': { + start: 6, + }, c_file: { file: 'veggies.txt', - end: 16 - }, 'd_file': { + end: 16, + }, d_file: { file: 'veggies.txt', start: 0, - end: 16 - }, 'e_file': { + end: 16, + }, e_file: { file: 'veggies.txt', start: 0, - end: 0 - } + end: 0, + }, }; /** @@ -42,46 +44,45 @@ function readSizeAccumulator(data) { this.readSize += data.length; } -var server = http.createServer(function(req, res) { +var server = http.createServer(function (req, res) { var requestBodyLength = 0; // calculate actual length of the request body - req.on('data', function(data) { + req.on('data', function (data) { requestBodyLength += data.length; }); - req.on('end', function() { + req.on('end', function () { // make sure total Content-Length is properly calculated assert.equal(req.headers['content-length'], requestBodyLength); // successfully accepted request and it's good res.writeHead(200); }); - var form = new IncomingForm({uploadDir: common.dir.tmp}); + var form = new IncomingForm({ uploadDir: common.dir.tmp }); form.parse(req); form - .on('file', function(name, file) { + .on('file', function (name, file) { // make sure chunks are the same size assert.equal(file.size, testSubjects[name].readSize); // clean up tested subject delete testSubjects[name]; }) - .on('end', function() { + .on('end', function () { // done here res.end(); }); }); - -server.listen(common.port, function() { +server.listen(common.port, function () { var form = new FormData(); var name, options; // add test subjects to the form - for (name in testSubjects) { + for (name in testSubjects) { // eslint-disable-line no-restricted-syntax if (Object.prototype.hasOwnProperty.call(testSubjects, name)) { - options = {encoding: 'utf8'}; + options = { encoding: 'utf8' }; if (testSubjects[name].start) { options.start = testSubjects[name].start; } if (testSubjects[name].end) { options.end = testSubjects[name].end; } @@ -94,7 +95,7 @@ server.listen(common.port, function() { } } - form.submit('http://localhost:' + common.port + '/', function(err, res) { + form.submit('http://localhost:' + common.port + '/', function (err, res) { if (err) { throw err; } @@ -102,7 +103,7 @@ server.listen(common.port, function() { assert.strictEqual(res.statusCode, 200); // wait for server to finish - res.on('end', function() { + res.on('end', function () { // check that all subjects were tested assert.strictEqual(Object.keys(testSubjects).length, 0); server.close(); diff --git a/test/integration/test-request.js b/test/integration/test-request.js index 88ee4bc..c1163ce 100644 --- a/test/integration/test-request.js +++ b/test/integration/test-request.js @@ -1,3 +1,5 @@ +'use strict'; + /** * Show & Test for `mikeal/request` library * as bonus shows progress monitor implementation @@ -13,24 +15,24 @@ var fs = require('fs'); var IncomingForm = require('formidable').IncomingForm; var fileName = common.dir.fixture + '/unicycle.jpg'; -var myFile = function() { return fs.createReadStream(fileName); }; +var myFile = function () { return fs.createReadStream(fileName); }; var numItems = 5; // Make request to use our FormData request.prototype.form = function (form) { var self = this; if (form) { - if (!/^application\/x-www-form-urlencoded\b/.test(self.getHeader('content-type'))) { + if (!(/^application\/x-www-form-urlencoded\b/).test(self.getHeader('content-type'))) { self.setHeader('content-type', 'application/x-www-form-urlencoded'); } - self.body = (typeof form === 'string') + self.body = typeof form === 'string' ? self._qs.rfc3986(form.toString('utf8')) : self._qs.stringify(form).toString('utf8'); return self; } // create form-data object self._form = new FormData(); - self._form.on('error', function(err) { + self._form.on('error', function (err) { err.message = 'form-data: ' + err.message; self.emit('error', err); self.abort(); @@ -38,27 +40,27 @@ request.prototype.form = function (form) { return self._form; }; -var server = http.createServer(function(req, res) { +var server = http.createServer(function (req, res) { - var form = new IncomingForm({uploadDir: common.dir.tmp}); + var form = new IncomingForm({ uploadDir: common.dir.tmp }); form.parse(req); form - .on('file', function(name, file) { - numItems--; + .on('file', function (name, file) { + numItems -= 1; assert.strictEqual(file.name, path.basename(fileName)); assert.strictEqual(file.type, mime.lookup(file.name)); }) .on('end', common.actions.formOnEnd.bind(null, res)); }); -server.listen(common.port, function() { +server.listen(common.port, function () { var uploadSize = 0; var uploaded = 0; - var r = request.post('http://localhost:' + common.port + '/', function(err, res) { + var r = request.post('http://localhost:' + common.port + '/', function (err, res) { assert.ifError(err); assert.strictEqual(res.statusCode, 200); server.close(); @@ -71,23 +73,23 @@ server.listen(common.port, function() { } // get upload size - form.getLength(function(err, size) { + form.getLength(function (err, size) { assert.equal(err, null); uploadSize = size; assert.ok(uploadSize > 0); }); // calculate uploaded size chunk by chunk - form.on('data', function(data) { + form.on('data', function (data) { uploaded += data.length; }); // done uploading compare sizes - form.on('end', function() { + form.on('end', function () { assert.equal(uploaded, uploadSize); }); }); -process.on('exit', function() { +process.on('exit', function () { assert.strictEqual(numItems, 0); }); diff --git a/test/integration/test-return-http-request.js b/test/integration/test-return-http-request.js index 5074138..a261eea 100644 --- a/test/integration/test-return-http-request.js +++ b/test/integration/test-return-http-request.js @@ -1,9 +1,11 @@ -/* -test return http request, added for issue #47: -https://github.com/felixge/node-form-data/issues/47 +'use strict'; -Checking correct length header and request object -*/ +/* + *test return http request, added for issue #47: + *https://github.com/felixge/node-form-data/issues/47 + * + *Checking correct length header and request object + */ var common = require('../common'); var assert = common.assert; @@ -13,19 +15,19 @@ var FormData = require(common.dir.lib + '/form_data'); var expectedLength; -var dataSize = 1000000; +var dataSize = 1e6; -var server = http.createServer(function(req, res) { +var server = http.createServer(function (req, res) { var uploaded = 0; - assert.ok( typeof req.headers['content-length'] !== 'undefined' ); + assert.ok(typeof req.headers['content-length'] !== 'undefined'); assert.equal(req.headers['content-length'], expectedLength); // check for uploaded body - req.on('data', function(data) { + req.on('data', function (data) { uploaded += data.length; }); - req.on('end', function() { + req.on('end', function () { // compare uploaded total to the expected length assert.equal(uploaded, expectedLength); @@ -35,9 +37,10 @@ var server = http.createServer(function(req, res) { }); - -server.listen(common.port, function() { - var R, oWrite, progress = 0, form = new FormData(); +server.listen(common.port, function () { + var R, oWrite, + progress = 0, + form = new FormData(); var bufferData = []; for (var z = 0; z < dataSize; z++) { @@ -50,7 +53,7 @@ server.listen(common.port, function() { // (available to req handler) expectedLength = form._lastBoundary().length + form._overheadLength + dataSize; - R = form.submit('http://localhost:' + common.port + '/', function(err, res) { + R = form.submit('http://localhost:' + common.port + '/', function (err, res) { if (err) { throw err; } @@ -68,14 +71,14 @@ server.listen(common.port, function() { // augment into request oWrite = R.write; - R.write = function(chunk) { - return oWrite.call(this, chunk, function() { + R.write = function (chunk) { + return oWrite.call(this, chunk, function () { form.emit('progress', chunk); }); }; // track progress - form.on('progress', function(chunk) { + form.on('progress', function (chunk) { progress += chunk.length; assert.ok(progress <= expectedLength); }); diff --git a/test/integration/test-set-boundary.js b/test/integration/test-set-boundary.js index f1d8820..0eaa194 100644 --- a/test/integration/test-set-boundary.js +++ b/test/integration/test-set-boundary.js @@ -1,3 +1,5 @@ +'use strict'; + var common = require('../common'); var assert = common.assert; @@ -9,7 +11,7 @@ var FormData = require(common.dir.lib + '/form_data'); form.setBoundary(userBoundary); assert.equal(form.getBoundary(), userBoundary); -})(); +}()); (function testUniqueBoundaryPerFormAfterSet() { var userBoundary = '---something'; @@ -20,4 +22,4 @@ var FormData = require(common.dir.lib + '/form_data'); assert.equal(formA.getBoundary(), userBoundary); assert.notEqual(formA.getBoundary(), formB.getBoundary()); -})(); +}()); diff --git a/test/integration/test-submit-custom-header.js b/test/integration/test-submit-custom-header.js index 6a6aff5..cbb9843 100644 --- a/test/integration/test-submit-custom-header.js +++ b/test/integration/test-submit-custom-header.js @@ -1,3 +1,5 @@ +'use strict'; + var common = require('../common'); var assert = common.assert; var http = require('http'); @@ -9,36 +11,37 @@ var IncomingForm = require('formidable').IncomingForm; var remoteFile = 'http://localhost:' + common.staticPort + '/unicycle.jpg'; -// wrap non simple values into function -// just to deal with ReadStream "autostart" +/* + * wrap non simple values into function + * just to deal with ReadStream "autostart" + */ var FIELDS = { - 'my_field': { - value: 'my_value' + my_field: { + value: 'my_value', }, - 'my_buffer': { + my_buffer: { type: FormData.DEFAULT_CONTENT_TYPE, - value: common.defaultTypeValue + value: common.defaultTypeValue, }, - 'my_file': { + my_file: { type: mime.lookup(common.dir.fixture + '/unicycle.jpg'), - value: function() { return fs.createReadStream(common.dir.fixture + '/unicycle.jpg'); } + value: function () { return fs.createReadStream(common.dir.fixture + '/unicycle.jpg'); }, }, - 'remote_file': { + remote_file: { type: mime.lookup(common.dir.fixture + '/unicycle.jpg'), - value: function() { return request(remoteFile); } - } + value: function () { return request(remoteFile); }, + }, }; var fieldsPassed = Object.keys(FIELDS).length; -var server = http.createServer(function(req, res) { +var server = http.createServer(function (req, res) { assert.ok(req.headers['x-test-header'], 'test-header-value'); - var form = new IncomingForm({uploadDir: common.dir.tmp}); + var form = new IncomingForm({ uploadDir: common.dir.tmp }); form.parse(req); - common.actions.checkForm(form, FIELDS, function(fieldsChecked) - { + common.actions.checkForm(form, FIELDS, function (fieldsChecked) { // keep track of number of the processed fields fieldsPassed = fieldsPassed - fieldsChecked; // finish it @@ -46,7 +49,7 @@ var server = http.createServer(function(req, res) { }); }); -server.listen(common.port, function() { +server.listen(common.port, function () { var form = new FormData(); @@ -57,9 +60,9 @@ server.listen(common.port, function() { port: common.port, path: '/', headers: { - 'x-test-header': 'test-header-value' - } - }, function(error, result) { + 'x-test-header': 'test-header-value', + }, + }, function (error, result) { if (error) { throw error; } @@ -73,6 +76,6 @@ server.listen(common.port, function() { }); -process.on('exit', function() { +process.on('exit', function () { assert.strictEqual(fieldsPassed, 0); }); diff --git a/test/integration/test-submit-custom.js b/test/integration/test-submit-custom.js index acba6eb..27c1f4b 100644 --- a/test/integration/test-submit-custom.js +++ b/test/integration/test-submit-custom.js @@ -1,3 +1,5 @@ +'use strict'; + var common = require('../common'); var assert = common.assert; var mime = require('mime-types'); @@ -7,35 +9,37 @@ var FormData = require(common.dir.lib + '/form_data'); var remoteFile = 'http://localhost:' + common.staticPort + '/unicycle.jpg'; -// wrap non simple values into function -// just to deal with ReadStream "autostart" +/* + * wrap non simple values into function + * just to deal with ReadStream "autostart" + */ var FIELDS = { - 'my_field': { - value: 'my_value' + my_field: { + value: 'my_value', }, - 'my_buffer': { + my_buffer: { type: FormData.DEFAULT_CONTENT_TYPE, - value: common.defaultTypeValue + value: common.defaultTypeValue, }, - 'my_file': { + my_file: { type: mime.lookup(common.dir.fixture + '/unicycle.jpg'), - value: function() { return fs.createReadStream(common.dir.fixture + '/unicycle.jpg'); } + value: function () { return fs.createReadStream(common.dir.fixture + '/unicycle.jpg'); }, }, - 'remote_file': { + remote_file: { type: mime.lookup(common.dir.fixture + '/unicycle.jpg'), - value: function() { return request(remoteFile); } - } + value: function () { return request(remoteFile); }, + }, }; // count total var fieldsPassed = Object.keys(FIELDS).length; // prepare form-receiving http server -var server = common.testFields(FIELDS, function(fields){ +var server = common.testFields(FIELDS, function (fields) { fieldsPassed = fields; }); -server.listen(common.port, function() { +server.listen(common.port, function () { var form = new FormData(); @@ -44,8 +48,8 @@ server.listen(common.port, function() { // custom params object passed to submit form.submit({ port: common.port, - path: '/' - }, function(err, res) { + path: '/', + }, function (err, res) { if (err) { throw err; @@ -59,6 +63,6 @@ server.listen(common.port, function() { }); -process.on('exit', function() { +process.on('exit', function () { assert.strictEqual(fieldsPassed, 0); }); diff --git a/test/integration/test-submit-https.js b/test/integration/test-submit-https.js index 51f0b45..bbc6395 100644 --- a/test/integration/test-submit-https.js +++ b/test/integration/test-submit-https.js @@ -1,4 +1,7 @@ +'use strict'; + var https = require('https'); +var constants = require('constants'); var common = require('../common'); var assert = common.assert; var FormData = require(common.dir.lib + '/form_data'); @@ -19,9 +22,9 @@ function submitForm() { port: common.httpsPort, pathname: '/', // for self-signed certs on localhost - secureOptions: require('constants').SSL_OP_NO_TLSv1_2, - ca: common.httpsServerCert - }, function(err, res) { + secureOptions: constants.SSL_OP_NO_TLSv1_2, + ca: common.httpsServerCert, + }, function (err, res) { if (err) { throw err; @@ -40,14 +43,14 @@ function submitForm() { // create https server server = https.createServer({ key: common.httpsServerKey, - cert: common.httpsServerCert -}, function(req, res) { + cert: common.httpsServerCert, +}, function (req, res) { // old and simple - req.on('data', function() {}); + req.on('data', function () {}); - req.on('end', function() { - res.writeHead(200, {'x-success': 'OK'}); + req.on('end', function () { + res.writeHead(200, { 'x-success': 'OK' }); res.end('Great Success'); }); }); diff --git a/test/integration/test-submit-multi-nocallback.js b/test/integration/test-submit-multi-nocallback.js index 5b666fa..b8d5a66 100644 --- a/test/integration/test-submit-multi-nocallback.js +++ b/test/integration/test-submit-multi-nocallback.js @@ -1,3 +1,5 @@ +'use strict'; + var common = require('../common'); var assert = common.assert; var http = require('http'); @@ -6,29 +8,31 @@ var IncomingForm = require('formidable').IncomingForm; var times = 10; -var server = http.createServer(function(req, res) { +var server = http.createServer(function (req, res) { - // no need to have tmp dir here, since no files being uploaded - // but formidable would fail in 0.6 otherwise - var form = new IncomingForm({uploadDir: common.dir.tmp}); + /* + * no need to have tmp dir here, since no files being uploaded + * but formidable would fail in 0.6 otherwise + */ + var form = new IncomingForm({ uploadDir: common.dir.tmp }); form.parse(req); form .on('field', common.actions.basicFormOnField) - .on('end', function() { + .on('end', function () { res.writeHead(200); res.end('done'); - times--; + times -= 1; - if (times == 0) { + if (times === 0) { server.close(); } }); }); -server.listen(common.port, function() { +server.listen(common.port, function () { var i; for (i = 0; i < times; i++) { @@ -41,6 +45,6 @@ server.listen(common.port, function() { }); -process.on('exit', function() { +process.on('exit', function () { assert.strictEqual(times, 0); }); diff --git a/test/integration/test-submit-multi.js b/test/integration/test-submit-multi.js index a0bc3dc..7c9a019 100644 --- a/test/integration/test-submit-multi.js +++ b/test/integration/test-submit-multi.js @@ -1,3 +1,5 @@ +'use strict'; + var common = require('../common'); var assert = common.assert; var http = require('http'); @@ -14,29 +16,33 @@ function submitForm() { form.append('my_field', 'my_value'); - form.submit('http://localhost:' + common.port + '/', function(err, res) { + form.submit('http://localhost:' + common.port + '/', function (err, res) { if (err) { throw err; } assert.strictEqual(res.statusCode, 200); - // Needed for node-0.10.x because Streams2 - // more info: http://nodejs.org/api/stream.html#stream_compatibility_with_older_node_versions + /* + * Needed for node-0.10.x because Streams2 + * more info: http://nodejs.org/api/stream.html#stream_compatibility_with_older_node_versions + */ res.resume(); - times--; - if (times == 0) { + times -= 1; + if (times === 0) { server.close(); } }); } -server = http.createServer(function(req, res) { +server = http.createServer(function (req, res) { - // no need to have tmp dir here, since no files being uploaded - // but formidable would fail in 0.6 otherwise - var form = new IncomingForm({uploadDir: common.dir.tmp}); + /* + * no need to have tmp dir here, since no files being uploaded + * but formidable would fail in 0.6 otherwise + */ + var form = new IncomingForm({ uploadDir: common.dir.tmp }); form.parse(req); @@ -45,7 +51,7 @@ server = http.createServer(function(req, res) { .on('end', common.actions.formOnEnd.bind(null, res)); }); -server.listen(common.port, function() { +server.listen(common.port, function () { var i; for (i = 0; i < times; i++) { @@ -53,6 +59,6 @@ server.listen(common.port, function() { } }); -process.on('exit', function() { +process.on('exit', function () { assert.strictEqual(times, 0); }); diff --git a/test/integration/test-submit-url-parsing.js b/test/integration/test-submit-url-parsing.js index becc1d7..2f16fb2 100644 --- a/test/integration/test-submit-url-parsing.js +++ b/test/integration/test-submit-url-parsing.js @@ -1,3 +1,5 @@ +'use strict'; + var http = require('http'); var https = require('https'); var common = require('../common'); @@ -13,21 +15,20 @@ var form = new FormData(); form.append('field', 'value'); // Basic parsing -req = form.submit('http://localhost/path', function() {}); +req = form.submit('http://localhost/path', function () {}); assert.strictEqual(req.path, '/path'); assert.ok(req.agent instanceof http.Agent, 'req.agent instanceof http.Agent'); assert.strictEqual(req.getHeader('Host'), 'localhost'); req.abort(); // Non-default port handling -req = form.submit('http://localhost:' + common.port, function() {}); +req = form.submit('http://localhost:' + common.port, function () {}); assert.strictEqual(req.getHeader('Host'), 'localhost:' + common.port); req.abort(); // HTTPS protocol handling -req = form.submit('https://localhost/path', function() {}); +req = form.submit('https://localhost/path', function () {}); assert.ok(req.agent instanceof https.Agent, 'req.agent instanceof https.Agent'); assert.strictEqual(req.getHeader('Host'), 'localhost'); req.abort(); - diff --git a/test/integration/test-submit.js b/test/integration/test-submit.js index 09a1e0c..fdf848d 100644 --- a/test/integration/test-submit.js +++ b/test/integration/test-submit.js @@ -1,3 +1,5 @@ +'use strict'; + var common = require('../common'); var assert = common.assert; var mime = require('mime-types'); @@ -7,36 +9,37 @@ var FormData = require(common.dir.lib + '/form_data'); var remoteFile = 'http://localhost:' + common.staticPort + '/unicycle.jpg'; -// wrap non simple values into function -// just to deal with ReadStream "autostart" +/* + * wrap non simple values into function + * just to deal with ReadStream "autostart" + */ var FIELDS = { - 'my_field': { - value: 'my_value' + my_field: { + value: 'my_value', }, - 'my_buffer': { + my_buffer: { type: FormData.DEFAULT_CONTENT_TYPE, - value: common.defaultTypeValue + value: common.defaultTypeValue, }, - 'my_file': { + my_file: { type: mime.lookup(common.dir.fixture + '/unicycle.jpg'), - value: function() { return fs.createReadStream(common.dir.fixture + '/unicycle.jpg'); } + value: function () { return fs.createReadStream(common.dir.fixture + '/unicycle.jpg'); }, }, - 'remote_file': { + remote_file: { type: mime.lookup(common.dir.fixture + '/unicycle.jpg'), - value: function() { return request(remoteFile); } - } + value: function () { return request(remoteFile); }, + }, }; // count total var fieldsPassed = Object.keys(FIELDS).length; // prepare form-receiving http server -var server = common.testFields( FIELDS, function(fields){ +var server = common.testFields(FIELDS, function (fields) { fieldsPassed = fields; }); - -server.listen(common.port, function() { +server.listen(common.port, function () { var form = new FormData(); @@ -45,6 +48,6 @@ server.listen(common.port, function() { common.actions.submit(form, server); }); -process.on('exit', function() { +process.on('exit', function () { assert.strictEqual(fieldsPassed, 0); }); diff --git a/test/integration/test-to-string.js b/test/integration/test-to-string.js index 877195e..79c37a2 100644 --- a/test/integration/test-to-string.js +++ b/test/integration/test-to-string.js @@ -1,5 +1,7 @@ -var common = require('../common'); -var assert = common.assert; +'use strict'; + +var common = require('../common'); +var assert = common.assert; var FormData = require(common.dir.lib + '/form_data'); assert(new FormData().toString() === '[object FormData]'); diff --git a/test/run-browser.js b/test/run-browser.js index 93077cc..cea7bd4 100644 --- a/test/run-browser.js +++ b/test/run-browser.js @@ -1,9 +1,10 @@ +'use strict'; + var test = require('tape'); var FormData = require('../lib/browser.js'); var form = new FormData(); -test('being nice to browser-like environments', function(t) -{ +test('being nice to browser-like environments', function (t) { t.plan(3); t.notEqual(typeof FormData, 'undefined', 'FormData should be defined'); t.equal(typeof form, 'object', 'FormData instance should be object'); diff --git a/test/run.js b/test/run.js index 22c804e..1d1c290 100755 --- a/test/run.js +++ b/test/run.js @@ -1,6 +1,9 @@ #!/usr/bin/env node + +'use strict'; + var path = require('path'); -var static = require('./static'); +var staticS = require('./static'); var far = require('far').create(); var farPaths = require('far/lib/paths'); var spawn = require('cross-spawn'); @@ -9,17 +12,20 @@ var istanbul = path.join(basePath, './node_modules/.bin/istanbul'); // augment Far to support istanbul if (process.env.running_under_istanbul) { - far.constructor.prototype._execute = function(file) { + far.constructor.prototype._execute = function (file) { this._printStatus(file); var node = spawn(istanbul, [ 'cover', - '--report', 'none', - '--print', 'none', + '--report', + 'none', + '--print', + 'none', '--include-all-sources', '--include-pid', - '--root', basePath, - file + '--root', + basePath, + file, ]); var output = ''; @@ -42,8 +48,8 @@ if (process.env.running_under_istanbul) { node.stdout.on('data', onOutput.bind(this)); node.stderr.on('data', onOutput.bind(this)); - node.on('exit', function(code) { - this._index++; + node.on('exit', function (code) { + this._index += 1; this._printTestResult(file, code, output); this._executeNext(); }.bind(this)); @@ -52,10 +58,10 @@ if (process.env.running_under_istanbul) { // augment far to work on windows -farPaths.expandSync = function(pathList) { +farPaths.expandSync = function (pathList) { var expanded = {}; - pathList.forEach(function(p) { + pathList.forEach(function (p) { p = path.resolve(process.cwd(), p); if (!farPaths.isDirectory(p)) { @@ -65,7 +71,7 @@ farPaths.expandSync = function(pathList) { farPaths .findRecursiveSync(p) - .forEach(function(pp) { + .forEach(function (pp) { expanded[pp] = true; }); }); @@ -83,6 +89,6 @@ far.add(__dirname); far.include(/test-.*\.js$/); // start static server for all tests -static(function() { +staticS(function () { far.execute(); }); diff --git a/test/static.js b/test/static.js index 0cdffa8..f613413 100644 --- a/test/static.js +++ b/test/static.js @@ -1,3 +1,5 @@ +'use strict'; + // serves static files var http = require('http'); var fs = require('fs'); @@ -10,17 +12,17 @@ if (!fs.existsSync(common.dir.tmp)) { fs.mkdirSync(common.dir.tmp); } -module.exports = function(callback) { +module.exports = function (callback) { // create http server - var httpServer = http.createServer(function(req, res) { + var httpServer = http.createServer(function (req, res) { var target = path.join(common.dir.fixture, req.url); var stat = fs.statSync(target); res.writeHead(200, { 'Content-Type': mime.lookup(target), - 'Content-Length': stat.size + 'Content-Length': stat.size, }); fs.createReadStream(target).pipe(res); From 11d9f7338f18a59b431832a3562b49baece0a432 Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Fri, 14 Feb 2025 18:54:33 -0800 Subject: [PATCH 17/29] [meta] fix scripts to use prepublishOnly --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index f2d961a..8b8801e 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,8 @@ "get-version": "node -e \"console.log(require('./package.json').version)\"", "update-readme": "sed -i.bak 's/\\/master\\.svg/\\/v'$(npm --silent run get-version)'.svg/g' README.md", "restore-readme": "mv README.md.bak README.md", - "prepublish": "in-publish && npm run update-readme || not-in-publish", + "prepublish": "not-in-publish || npm run prepublishOnly", + "prepublishOnly": "npm run update-readme", "postpublish": "npm run restore-readme" }, "pre-commit": [ From 1a78b5dd05e508d67e97764d812ac7c6d92ea88d Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Wed, 16 Jul 2025 22:15:14 -0700 Subject: [PATCH 18/29] [Refactor] use `hasown` --- lib/form_data.js | 17 +++++++++-------- package.json | 1 + test/common.js | 3 ++- test/integration/test-custom-content-type.js | 3 ++- test/integration/test-pipe.js | 3 ++- test/integration/test-ranged-filestream.js | 3 ++- 6 files changed, 18 insertions(+), 12 deletions(-) diff --git a/lib/form_data.js b/lib/form_data.js index e8e53da..8c63e5c 100644 --- a/lib/form_data.js +++ b/lib/form_data.js @@ -10,6 +10,7 @@ var fs = require('fs'); var mime = require('mime-types'); var asynckit = require('asynckit'); var setToStringTag = require('es-set-tostringtag'); +var hasOwn = require('hasown'); var populate = require('./populate.js'); /** @@ -103,7 +104,7 @@ FormData.prototype._trackLength = function (header, value, options) { this._overheadLength += Buffer.byteLength(header) + FormData.LINE_BREAK.length; // empty or either doesn't have path or not an http response - if (!value || (!value.path && !(value.readable && Object.prototype.hasOwnProperty.call(value, 'httpVersion')))) { + if (!value || (!value.path && !(value.readable && hasOwn(value, 'httpVersion')))) { return; } @@ -114,7 +115,7 @@ FormData.prototype._trackLength = function (header, value, options) { }; FormData.prototype._lengthRetriever = function (value, callback) { - if (Object.prototype.hasOwnProperty.call(value, 'fd')) { + if (hasOwn(value, 'fd')) { /* * take read range into a account @@ -153,11 +154,11 @@ FormData.prototype._lengthRetriever = function (value, callback) { } // or http response - } else if (Object.prototype.hasOwnProperty.call(value, 'httpVersion')) { + } else if (hasOwn(value, 'httpVersion')) { callback(null, Number(value.headers['content-length'])); // or request stream http://github.com/mikeal/request - } else if (Object.prototype.hasOwnProperty.call(value, 'httpModule')) { + } else if (hasOwn(value, 'httpModule')) { // wait till response come back value.on('response', function (response) { value.pause(); @@ -199,7 +200,7 @@ FormData.prototype._multiPartHeader = function (field, value, options) { var header; for (var prop in headers) { // eslint-disable-line no-restricted-syntax - if (Object.prototype.hasOwnProperty.call(headers, prop)) { + if (hasOwn(headers, prop)) { header = headers[prop]; // skip nullish headers. @@ -236,7 +237,7 @@ FormData.prototype._getContentDisposition = function (value, options) { * fs- and request- streams have path property */ filename = path.basename(options.filename || value.name || value.path); - } else if (value.readable && Object.prototype.hasOwnProperty.call(value, 'httpVersion')) { + } else if (value.readable && hasOwn(value, 'httpVersion')) { // or try http response filename = path.basename(value.client._httpMessage.path || ''); } @@ -264,7 +265,7 @@ FormData.prototype._getContentType = function (value, options) { } // or if it's http-reponse - if (!contentType && value.readable && Object.prototype.hasOwnProperty.call(value, 'httpVersion')) { + if (!contentType && value.readable && hasOwn(value, 'httpVersion')) { contentType = value.headers['content-type']; } @@ -305,7 +306,7 @@ FormData.prototype.getHeaders = function (userHeaders) { }; for (header in userHeaders) { // eslint-disable-line no-restricted-syntax - if (Object.prototype.hasOwnProperty.call(userHeaders, header)) { + if (hasOwn(userHeaders, header)) { formHeaders[header.toLowerCase()] = userHeaders[header]; } } diff --git a/package.json b/package.json index 8b8801e..5b40b9c 100644 --- a/package.json +++ b/package.json @@ -45,6 +45,7 @@ "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", "mime-types": "^2.1.35" }, "devDependencies": { diff --git a/test/common.js b/test/common.js index 479fd6d..79f56c1 100644 --- a/test/common.js +++ b/test/common.js @@ -6,6 +6,7 @@ var assert = require('assert'); var fake = require('fake'); var mime = require('mime-types'); var http = require('http'); +var hasOwn = require('hasown'); var IncomingForm = require('formidable').IncomingForm; var common = module.exports; @@ -60,7 +61,7 @@ common.actions = {}; common.actions.populateFields = function (form, fields) { var field; for (var name in fields) { // eslint-disable-line no-restricted-syntax - if (Object.prototype.hasOwnProperty.call(fields, name)) { + if (hasOwn(fields, name)) { field = fields[name]; // important to append ReadStreams within the same tick if (typeof field.value === 'function') { diff --git a/test/integration/test-custom-content-type.js b/test/integration/test-custom-content-type.js index a193fc9..15eb222 100644 --- a/test/integration/test-custom-content-type.js +++ b/test/integration/test-custom-content-type.js @@ -5,6 +5,7 @@ var assert = common.assert; var http = require('http'); var mime = require('mime-types'); var fs = require('fs'); +var hasOwn = require('hasown'); var FormData = require(common.dir.lib + '/form_data'); /* @@ -72,7 +73,7 @@ server.listen(common.port, function () { var form = new FormData(); for (var name in FIELDS) { // eslint-disable-line no-restricted-syntax - if (Object.prototype.hasOwnProperty.call(FIELDS, name)) { + if (hasOwn(FIELDS, name)) { var field = FIELDS[name]; // important to append ReadStreams within the same tick if (typeof field.value === 'function') { diff --git a/test/integration/test-pipe.js b/test/integration/test-pipe.js index 32bb1aa..f5272db 100644 --- a/test/integration/test-pipe.js +++ b/test/integration/test-pipe.js @@ -6,6 +6,7 @@ var http = require('http'); var mime = require('mime-types'); var request = require('request'); var fs = require('fs'); +var hasOwn = require('hasown'); var FormData = require(common.dir.lib + '/form_data'); var IncomingForm = require('formidable').IncomingForm; @@ -53,7 +54,7 @@ server.listen(common.port, function () { var form = new FormData(); for (var name in FIELDS) { // eslint-disable-line no-restricted-syntax - if (Object.prototype.hasOwnProperty.call(FIELDS, name)) { + if (hasOwn(FIELDS, name)) { var field = FIELDS[name]; // important to append ReadStreams within the same tick if (typeof field.value === 'function') { diff --git a/test/integration/test-ranged-filestream.js b/test/integration/test-ranged-filestream.js index 6e3c45a..b5d2c79 100644 --- a/test/integration/test-ranged-filestream.js +++ b/test/integration/test-ranged-filestream.js @@ -9,6 +9,7 @@ var common = require('../common'); var assert = common.assert; var http = require('http'); var fs = require('fs'); +var hasOwn = require('hasown'); var FormData = require(common.dir.lib + '/form_data'); var IncomingForm = require('formidable').IncomingForm; @@ -81,7 +82,7 @@ server.listen(common.port, function () { // add test subjects to the form for (name in testSubjects) { // eslint-disable-line no-restricted-syntax - if (Object.prototype.hasOwnProperty.call(testSubjects, name)) { + if (hasOwn(testSubjects, name)) { options = { encoding: 'utf8' }; if (testSubjects[name].start) { options.start = testSubjects[name].start; } From b22a64ef94ba4f3f6ff7d1ac72a54cca128567df Mon Sep 17 00:00:00 2001 From: Mallikarjun-0 Date: Wed, 16 Apr 2025 03:56:06 +0530 Subject: [PATCH 19/29] [Tests] add tests to check the behavior of `getBoundary` with non-strings --- test/integration/test-set-boundary.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/test/integration/test-set-boundary.js b/test/integration/test-set-boundary.js index 0eaa194..778d8d7 100644 --- a/test/integration/test-set-boundary.js +++ b/test/integration/test-set-boundary.js @@ -23,3 +23,13 @@ var FormData = require(common.dir.lib + '/form_data'); assert.equal(formA.getBoundary(), userBoundary); assert.notEqual(formA.getBoundary(), formB.getBoundary()); }()); + +(function testsetBoundaryWithNonString_preExistingBehavior() { + var form = new FormData(); + + var nonStringValues = [123, { value: 123 }, ['---something']]; + nonStringValues.forEach(function (value) { + form.setBoundary(value); + assert.equal(form.getBoundary(), value); + }); +}()); From 70bbaa0b395ca0fb975c309de8d7286979254cc4 Mon Sep 17 00:00:00 2001 From: Mallikarjun-0 Date: Sat, 12 Apr 2025 20:13:44 +0530 Subject: [PATCH 20/29] [Fix] validate boundary type in `setBoundary()` method --- lib/form_data.js | 3 +++ test/integration/test-set-boundary.js | 12 +++++++----- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/lib/form_data.js b/lib/form_data.js index 8c63e5c..8e242c2 100644 --- a/lib/form_data.js +++ b/lib/form_data.js @@ -315,6 +315,9 @@ FormData.prototype.getHeaders = function (userHeaders) { }; FormData.prototype.setBoundary = function (boundary) { + if (typeof boundary !== 'string') { + throw new TypeError('FormData boundary must be a string'); + } this._boundary = boundary; }; diff --git a/test/integration/test-set-boundary.js b/test/integration/test-set-boundary.js index 778d8d7..7b2fa45 100644 --- a/test/integration/test-set-boundary.js +++ b/test/integration/test-set-boundary.js @@ -24,12 +24,14 @@ var FormData = require(common.dir.lib + '/form_data'); assert.notEqual(formA.getBoundary(), formB.getBoundary()); }()); -(function testsetBoundaryWithNonString_preExistingBehavior() { +(function testSetBoundaryWithNonString() { var form = new FormData(); - var nonStringValues = [123, { value: 123 }, ['---something']]; - nonStringValues.forEach(function (value) { - form.setBoundary(value); - assert.equal(form.getBoundary(), value); + var invalidValues = [123, null, undefined, { value: 123 }, ['---something']]; + + invalidValues.forEach(function (value) { + assert.throws(function () { + form.setBoundary(value); + }, TypeError); }); }()); From 002b9b0c4862576305292ac44f7be25ec7ccea0e Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Thu, 8 May 2025 11:46:59 -0700 Subject: [PATCH 21/29] [Fix] `append`: avoid a crash on nullish values Fixes #577 --- lib/form_data.js | 16 ++++++++-------- test/integration/test-set-nonstring.js | 22 ++++++++++++++++++++++ 2 files changed, 30 insertions(+), 8 deletions(-) create mode 100644 test/integration/test-set-nonstring.js diff --git a/lib/form_data.js b/lib/form_data.js index 8e242c2..d34eefe 100644 --- a/lib/form_data.js +++ b/lib/form_data.js @@ -56,7 +56,7 @@ FormData.prototype.append = function (field, value, options) { var append = CombinedStream.prototype.append.bind(this); // all that streamy business can't handle numbers - if (typeof value === 'number') { + if (typeof value === 'number' || value == null) { value = String(value); } @@ -230,14 +230,14 @@ FormData.prototype._getContentDisposition = function (value, options) { if (typeof options.filepath === 'string') { // custom filepath for relative paths filename = path.normalize(options.filepath).replace(/\\/g, '/'); - } else if (options.filename || value.name || value.path) { + } else if (options.filename || (value && (value.name || value.path))) { /* * custom filename take precedence * formidable and the browser add a name property * fs- and request- streams have path property */ - filename = path.basename(options.filename || value.name || value.path); - } else if (value.readable && hasOwn(value, 'httpVersion')) { + filename = path.basename(options.filename || (value && (value.name || value.path))); + } else if (value && value.readable && hasOwn(value, 'httpVersion')) { // or try http response filename = path.basename(value.client._httpMessage.path || ''); } @@ -255,17 +255,17 @@ FormData.prototype._getContentType = function (value, options) { var contentType = options.contentType; // or try `name` from formidable, browser - if (!contentType && value.name) { + if (!contentType && value && value.name) { contentType = mime.lookup(value.name); } // or try `path` from fs-, request- streams - if (!contentType && value.path) { + if (!contentType && value && value.path) { contentType = mime.lookup(value.path); } // or if it's http-reponse - if (!contentType && value.readable && hasOwn(value, 'httpVersion')) { + if (!contentType && value && value.readable && hasOwn(value, 'httpVersion')) { contentType = value.headers['content-type']; } @@ -275,7 +275,7 @@ FormData.prototype._getContentType = function (value, options) { } // fallback to the default content type if `value` is not simple value - if (!contentType && typeof value === 'object') { + if (!contentType && value && typeof value === 'object') { contentType = FormData.DEFAULT_CONTENT_TYPE; } diff --git a/test/integration/test-set-nonstring.js b/test/integration/test-set-nonstring.js new file mode 100644 index 0000000..1b828db --- /dev/null +++ b/test/integration/test-set-nonstring.js @@ -0,0 +1,22 @@ +'use strict'; + +var common = require('../common'); +var assert = common.assert; + +var FormData = require(common.dir.lib + '/form_data'); + +(function testSetUndefined() { + var form = new FormData(); + + assert.doesNotThrow(function () { + form.append('key', undefined); + }); + + var buffer = form.getBuffer(); + + assert.deepEqual(buffer.toString().split(form.getBoundary()), [ + '--', + '\r\nContent-Disposition: form-data; name="key"\r\n\r\nundefined\r\n--', + '--\r\n', + ]); +}()); From a14d09ea8ed7e0a2e1705269ce6fb54bb7ee6bdb Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Thu, 5 Jun 2025 07:45:16 -0700 Subject: [PATCH 22/29] [Dev Deps] remove unused deps --- package.json | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/package.json b/package.json index 5b40b9c..cdbd8a7 100644 --- a/package.json +++ b/package.json @@ -50,7 +50,6 @@ }, "devDependencies": { "@ljharb/eslint-config": "^21.2.0", - "@types/node": "^12.20.55", "browserify": "^13.3.0", "browserify-istanbul": "^2.0.0", "coveralls": "^3.1.1", @@ -65,11 +64,9 @@ "obake": "^0.1.2", "pkgfiles": "^2.3.2", "pre-commit": "^1.2.2", - "puppeteer": "^1.20.0", "request": "~2.87.0", "rimraf": "^2.7.1", - "tape": "^5.9.0", - "typescript": "^3.9.10" + "tape": "^5.9.0" }, "license": "MIT" } From fc42bb9315b641bfa6dae51cb4e188a86bb04769 Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Thu, 5 Jun 2025 07:50:22 -0700 Subject: [PATCH 23/29] [meta] remove local commit hooks this concept is a security hole --- package.json | 6 ------ 1 file changed, 6 deletions(-) diff --git a/package.json b/package.json index cdbd8a7..ce37435 100644 --- a/package.json +++ b/package.json @@ -33,11 +33,6 @@ "prepublishOnly": "npm run update-readme", "postpublish": "npm run restore-readme" }, - "pre-commit": [ - "lint", - "ci-test", - "check" - ], "engines": { "node": ">= 6" }, @@ -63,7 +58,6 @@ "istanbul": "^0.4.5", "obake": "^0.1.2", "pkgfiles": "^2.3.2", - "pre-commit": "^1.2.2", "request": "~2.87.0", "rimraf": "^2.7.1", "tape": "^5.9.0" From d2eb290a3e47ed5bcad7020d027daa15b3cf5ef5 Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Wed, 16 Jul 2025 21:38:20 -0700 Subject: [PATCH 24/29] [meta] add `auto-changelog` --- .npmrc | 2 + CHANGELOG.md | 589 +++++++++++++++++++++++++++++++++++++++++++++++++++ package.json | 15 +- 3 files changed, 604 insertions(+), 2 deletions(-) create mode 100644 CHANGELOG.md diff --git a/.npmrc b/.npmrc index 43c97e7..eacea13 100644 --- a/.npmrc +++ b/.npmrc @@ -1 +1,3 @@ package-lock=false +allow-same-version=true +message=v%s diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..b57a80c --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,589 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [v4.0.3](https://github.com/form-data/form-data/compare/v4.0.2...v4.0.3) - 2025-06-05 + +### Fixed + +- [Fix] `append`: avoid a crash on nullish values [`#577`](https://github.com/form-data/form-data/issues/577) + +### Commits + +- [eslint] use a shared config [`426ba9a`](https://github.com/form-data/form-data/commit/426ba9ac440f95d1998dac9a5cd8d738043b048f) +- [eslint] fix some spacing issues [`2094191`](https://github.com/form-data/form-data/commit/20941917f0e9487e68c564ebc3157e23609e2939) +- [Refactor] use `hasown` [`81ab41b`](https://github.com/form-data/form-data/commit/81ab41b46fdf34f5d89d7ff30b513b0925febfaa) +- [Fix] validate boundary type in `setBoundary()` method [`8d8e469`](https://github.com/form-data/form-data/commit/8d8e4693093519f7f18e3c597d1e8df8c493de9e) +- [Tests] add tests to check the behavior of `getBoundary` with non-strings [`837b8a1`](https://github.com/form-data/form-data/commit/837b8a1f7562bfb8bda74f3fc538adb7a5858995) +- [Dev Deps] remove unused deps [`870e4e6`](https://github.com/form-data/form-data/commit/870e4e665935e701bf983a051244ab928e62d58e) +- [meta] remove local commit hooks [`e6e83cc`](https://github.com/form-data/form-data/commit/e6e83ccb545a5619ed6cd04f31d5c2f655eb633e) +- [Dev Deps] update `eslint` [`4066fd6`](https://github.com/form-data/form-data/commit/4066fd6f65992b62fa324a6474a9292a4f88c916) +- [meta] fix scripts to use prepublishOnly [`c4bbb13`](https://github.com/form-data/form-data/commit/c4bbb13c0ef669916657bc129341301b1d331d75) + +## [v4.0.2](https://github.com/form-data/form-data/compare/v4.0.1...v4.0.2) - 2025-02-14 + +### Merged + +- [Fix] set `Symbol.toStringTag` when available [`#573`](https://github.com/form-data/form-data/pull/573) +- [Fix] set `Symbol.toStringTag` when available [`#573`](https://github.com/form-data/form-data/pull/573) +- fix (npmignore): ignore temporary build files [`#532`](https://github.com/form-data/form-data/pull/532) +- fix (npmignore): ignore temporary build files [`#532`](https://github.com/form-data/form-data/pull/532) + +### Fixed + +- [Fix] set `Symbol.toStringTag` when available (#573) [`#396`](https://github.com/form-data/form-data/issues/396) +- [Fix] set `Symbol.toStringTag` when available (#573) [`#396`](https://github.com/form-data/form-data/issues/396) +- [Fix] set `Symbol.toStringTag` when available [`#396`](https://github.com/form-data/form-data/issues/396) + +### Commits + +- Merge tags v2.5.3 and v3.0.3 [`92613b9`](https://github.com/form-data/form-data/commit/92613b9208556eb4ebc482fdf599fae111626fb6) +- [Tests] migrate from travis to GHA [`806eda7`](https://github.com/form-data/form-data/commit/806eda77740e6e3c67c7815afb216f2e1f187ba5) +- [Tests] migrate from travis to GHA [`8fdb3bc`](https://github.com/form-data/form-data/commit/8fdb3bc6b5d001f8909a9fca391d1d1d97ef1d79) +- [Refactor] use `Object.prototype.hasOwnProperty.call` [`7fecefe`](https://github.com/form-data/form-data/commit/7fecefe4ba8f775634aff86a698776ad95ecffb5) +- [Refactor] use `Object.prototype.hasOwnProperty.call` [`6e682d4`](https://github.com/form-data/form-data/commit/6e682d4bd41de7e80de41e3c4ee10f23fcc3dd00) +- [Refactor] use `Object.prototype.hasOwnProperty.call` [`df3c1e6`](https://github.com/form-data/form-data/commit/df3c1e6f0937f47a782dc4573756a54987f31dde) +- [Dev Deps] update `@types/node`, `browserify`, `coveralls`, `cross-spawn`, `eslint`, `formidable`, `in-publish`, `pkgfiles`, `pre-commit`, `puppeteer`, `request`, `tape`, `typescript` [`8261fcb`](https://github.com/form-data/form-data/commit/8261fcb8bf5944d30ae3bd04b91b71d6a9932ef4) +- [Dev Deps] update `@types/node`, `browserify`, `coveralls`, `cross-spawn`, `eslint`, `formidable`, `in-publish`, `pkgfiles`, `pre-commit`, `puppeteer`, `request`, `tape`, `typescript` [`fb66cb7`](https://github.com/form-data/form-data/commit/fb66cb740e29fb170eee947d4be6fdf82d6659af) +- [Dev Deps] update `@types/node`, `browserify`, `coveralls`, `eslint`, `formidable`, `in-publish`, `phantomjs-prebuilt`, `pkgfiles`, `pre-commit`, `request`, `tape`, `typescript` [`819f6b7`](https://github.com/form-data/form-data/commit/819f6b7a543306a891fca37c3a06d0ff4a734422) +- [eslint] clean up ignores [`3217b3d`](https://github.com/form-data/form-data/commit/3217b3ded8e382e51171d5c74c6038a21cc54440) +- [eslint] clean up ignores [`3a9d480`](https://github.com/form-data/form-data/commit/3a9d480232dbcbc07260ad84c3da4975d9a3ae9e) +- [Fix] `Buffer.from` and `Buffer.alloc` require node 4+ [`c499f76`](https://github.com/form-data/form-data/commit/c499f76f1faac1ddbf210c45217038e4c1e02337) +- Only apps should have lockfiles [`b82f590`](https://github.com/form-data/form-data/commit/b82f59093cdbadb4b7ec0922d33ae7ab048b82ff) +- Only apps should have lockfiles [`b170ee2`](https://github.com/form-data/form-data/commit/b170ee2b22b4c695c363b811c0c553d2fb1bbd79) +- [Deps] update `combined-stream`, `mime-types` [`6b1ca1d`](https://github.com/form-data/form-data/commit/6b1ca1dc7362a1b1c3a99a885516cca4b7eb817f) +- [Dev Deps] pin `request` which via `tough-cookie` ^2.4 depends on `psl` [`e5df7f2`](https://github.com/form-data/form-data/commit/e5df7f24383342264bd73dee3274818a40d04065) +- [Deps] update `mime-types` [`5a5bafe`](https://github.com/form-data/form-data/commit/5a5bafee894fead10da49e1fa2b084e17f2e1034) +- Bumped version 2.5.3 [`9457283`](https://github.com/form-data/form-data/commit/9457283e1dce6122adc908fdd7442cfc54cabe7a) +- [Dev Deps] pin `request` which via `tough-cookie` ^2.4 depends on `psl` [`9dbe192`](https://github.com/form-data/form-data/commit/9dbe192be3db215eac4d9c0b980470a5c2c030c6) +- Merge tags v2.5.2 and v3.0.2 [`d53265d`](https://github.com/form-data/form-data/commit/d53265d86c5153f535ec68eb107548b1b2883576) +- Bumped version 2.5.2 [`7020dd4`](https://github.com/form-data/form-data/commit/7020dd4c1260370abc40e86e3dfe49c5d576fbda) +- [Dev Deps] downgrade `cross-spawn` [`3fc1a9b`](https://github.com/form-data/form-data/commit/3fc1a9b62ddf1fe77a2bd6bd3476e4c0a9e01a88) +- fix: move util.isArray to Array.isArray (#564) [`edb555a`](https://github.com/form-data/form-data/commit/edb555a811f6f7e4668db4831551cf41c1de1cac) +- fix: move util.isArray to Array.isArray (#564) [`10418d1`](https://github.com/form-data/form-data/commit/10418d1fe4b0d65fe020eafe3911feb5ad5e2bd6) + +## [v4.0.1](https://github.com/form-data/form-data/compare/v4.0.0...v4.0.1) - 2024-10-10 + +### Commits + +- [Tests] migrate from travis to GHA [`757b4e3`](https://github.com/form-data/form-data/commit/757b4e32e95726aec9bdcc771fb5a3b564d88034) +- [eslint] clean up ignores [`e8f0d80`](https://github.com/form-data/form-data/commit/e8f0d80cd7cd424d1488532621ec40a33218b30b) +- fix (npmignore): ignore temporary build files [`335ad19`](https://github.com/form-data/form-data/commit/335ad19c6e17dc2d7298ffe0e9b37ba63600e94b) +- fix: move util.isArray to Array.isArray [`440d3be`](https://github.com/form-data/form-data/commit/440d3bed752ac2f9213b4c2229dbccefe140e5fa) + +## [v4.0.0](https://github.com/form-data/form-data/compare/v3.0.3...v4.0.0) - 2021-02-15 + +### Merged + +- Handle custom stream [`#382`](https://github.com/form-data/form-data/pull/382) + +### Commits + +- Fix typo [`e705c0a`](https://github.com/form-data/form-data/commit/e705c0a1fdaf90d21501f56460b93e43a18bd435) +- Update README for custom stream behavior [`6dd8624`](https://github.com/form-data/form-data/commit/6dd8624b2999e32768d62752c9aae5845a803b0d) + +## [v3.0.3](https://github.com/form-data/form-data/compare/v3.0.2...v3.0.3) - 2025-02-14 + +### Merged + +- [Fix] set `Symbol.toStringTag` when available [`#573`](https://github.com/form-data/form-data/pull/573) + +### Fixed + +- [Fix] set `Symbol.toStringTag` when available (#573) [`#396`](https://github.com/form-data/form-data/issues/396) + +### Commits + +- [Refactor] use `Object.prototype.hasOwnProperty.call` [`7fecefe`](https://github.com/form-data/form-data/commit/7fecefe4ba8f775634aff86a698776ad95ecffb5) +- [Dev Deps] update `@types/node`, `browserify`, `coveralls`, `cross-spawn`, `eslint`, `formidable`, `in-publish`, `pkgfiles`, `pre-commit`, `puppeteer`, `request`, `tape`, `typescript` [`8261fcb`](https://github.com/form-data/form-data/commit/8261fcb8bf5944d30ae3bd04b91b71d6a9932ef4) +- Only apps should have lockfiles [`b82f590`](https://github.com/form-data/form-data/commit/b82f59093cdbadb4b7ec0922d33ae7ab048b82ff) +- [Dev Deps] pin `request` which via `tough-cookie` ^2.4 depends on `psl` [`e5df7f2`](https://github.com/form-data/form-data/commit/e5df7f24383342264bd73dee3274818a40d04065) +- [Deps] update `mime-types` [`5a5bafe`](https://github.com/form-data/form-data/commit/5a5bafee894fead10da49e1fa2b084e17f2e1034) + +## [v3.0.2](https://github.com/form-data/form-data/compare/v3.0.1...v3.0.2) - 2024-10-10 + +### Merged + +- fix (npmignore): ignore temporary build files [`#532`](https://github.com/form-data/form-data/pull/532) + +### Commits + +- [Tests] migrate from travis to GHA [`8fdb3bc`](https://github.com/form-data/form-data/commit/8fdb3bc6b5d001f8909a9fca391d1d1d97ef1d79) +- [eslint] clean up ignores [`3217b3d`](https://github.com/form-data/form-data/commit/3217b3ded8e382e51171d5c74c6038a21cc54440) +- fix: move util.isArray to Array.isArray (#564) [`edb555a`](https://github.com/form-data/form-data/commit/edb555a811f6f7e4668db4831551cf41c1de1cac) + +## [v3.0.1](https://github.com/form-data/form-data/compare/v3.0.0...v3.0.1) - 2021-02-15 + +### Merged + +- Fix typo: ads -> adds [`#451`](https://github.com/form-data/form-data/pull/451) + +### Commits + +- feat: add setBoundary method [`55d90ce`](https://github.com/form-data/form-data/commit/55d90ce4a4c22b0ea0647991d85cb946dfb7395b) + +## [v3.0.0](https://github.com/form-data/form-data/compare/v2.5.3...v3.0.0) - 2019-11-05 + +### Merged + +- Update Readme.md [`#449`](https://github.com/form-data/form-data/pull/449) +- Update package.json [`#448`](https://github.com/form-data/form-data/pull/448) +- fix memory leak [`#447`](https://github.com/form-data/form-data/pull/447) +- form-data: Replaced PhantomJS Dependency [`#442`](https://github.com/form-data/form-data/pull/442) +- Fix constructor options in Typescript definitions [`#446`](https://github.com/form-data/form-data/pull/446) +- Fix the getHeaders method signatures [`#434`](https://github.com/form-data/form-data/pull/434) +- Update combined-stream (fixes #422) [`#424`](https://github.com/form-data/form-data/pull/424) + +### Fixed + +- Merge pull request #424 from botgram/update-combined-stream [`#422`](https://github.com/form-data/form-data/issues/422) +- Update combined-stream (fixes #422) [`#422`](https://github.com/form-data/form-data/issues/422) + +### Commits + +- Add readable stream options to constructor type [`80c8f74`](https://github.com/form-data/form-data/commit/80c8f746bcf4c0418ae35fbedde12fb8c01e2748) +- Fixed: getHeaders method signatures [`f4ca7f8`](https://github.com/form-data/form-data/commit/f4ca7f8e31f7e07df22c1aeb8e0a32a7055a64ca) +- Pass options to constructor if not used with new [`4bde68e`](https://github.com/form-data/form-data/commit/4bde68e12de1ba90fefad2e7e643f6375b902763) +- Make userHeaders optional [`2b4e478`](https://github.com/form-data/form-data/commit/2b4e4787031490942f2d1ee55c56b85a250875a7) + +## [v2.5.3](https://github.com/form-data/form-data/compare/v2.5.2...v2.5.3) - 2025-02-14 + +### Merged + +- [Fix] set `Symbol.toStringTag` when available [`#573`](https://github.com/form-data/form-data/pull/573) + +### Fixed + +- [Fix] set `Symbol.toStringTag` when available (#573) [`#396`](https://github.com/form-data/form-data/issues/396) + +### Commits + +- [Refactor] use `Object.prototype.hasOwnProperty.call` [`6e682d4`](https://github.com/form-data/form-data/commit/6e682d4bd41de7e80de41e3c4ee10f23fcc3dd00) +- [Dev Deps] update `@types/node`, `browserify`, `coveralls`, `eslint`, `formidable`, `in-publish`, `phantomjs-prebuilt`, `pkgfiles`, `pre-commit`, `request`, `tape`, `typescript` [`819f6b7`](https://github.com/form-data/form-data/commit/819f6b7a543306a891fca37c3a06d0ff4a734422) +- Only apps should have lockfiles [`b170ee2`](https://github.com/form-data/form-data/commit/b170ee2b22b4c695c363b811c0c553d2fb1bbd79) +- [Deps] update `combined-stream`, `mime-types` [`6b1ca1d`](https://github.com/form-data/form-data/commit/6b1ca1dc7362a1b1c3a99a885516cca4b7eb817f) +- Bumped version 2.5.3 [`9457283`](https://github.com/form-data/form-data/commit/9457283e1dce6122adc908fdd7442cfc54cabe7a) +- [Dev Deps] pin `request` which via `tough-cookie` ^2.4 depends on `psl` [`9dbe192`](https://github.com/form-data/form-data/commit/9dbe192be3db215eac4d9c0b980470a5c2c030c6) + +## [v2.5.2](https://github.com/form-data/form-data/compare/v2.5.1...v2.5.2) - 2024-10-10 + +### Merged + +- fix (npmignore): ignore temporary build files [`#532`](https://github.com/form-data/form-data/pull/532) + +### Commits + +- [Tests] migrate from travis to GHA [`806eda7`](https://github.com/form-data/form-data/commit/806eda77740e6e3c67c7815afb216f2e1f187ba5) +- [eslint] clean up ignores [`3a9d480`](https://github.com/form-data/form-data/commit/3a9d480232dbcbc07260ad84c3da4975d9a3ae9e) +- [Fix] `Buffer.from` and `Buffer.alloc` require node 4+ [`c499f76`](https://github.com/form-data/form-data/commit/c499f76f1faac1ddbf210c45217038e4c1e02337) +- Bumped version 2.5.2 [`7020dd4`](https://github.com/form-data/form-data/commit/7020dd4c1260370abc40e86e3dfe49c5d576fbda) +- [Dev Deps] downgrade `cross-spawn` [`3fc1a9b`](https://github.com/form-data/form-data/commit/3fc1a9b62ddf1fe77a2bd6bd3476e4c0a9e01a88) +- fix: move util.isArray to Array.isArray (#564) [`10418d1`](https://github.com/form-data/form-data/commit/10418d1fe4b0d65fe020eafe3911feb5ad5e2bd6) + +## [v2.5.1](https://github.com/form-data/form-data/compare/v2.5.0...v2.5.1) - 2019-08-28 + +### Merged + +- Fix error in callback signatures [`#435`](https://github.com/form-data/form-data/pull/435) +- -Fixed: Eerror in the documentations as indicated in #439 [`#440`](https://github.com/form-data/form-data/pull/440) +- Add constructor options to TypeScript defs [`#437`](https://github.com/form-data/form-data/pull/437) + +### Commits + +- Add remaining combined-stream options to typedef [`4d41a32`](https://github.com/form-data/form-data/commit/4d41a32c0b3f85f8bbc9cf17df43befd2d5fc305) +- Bumped version 2.5.1 [`8ce81f5`](https://github.com/form-data/form-data/commit/8ce81f56cccf5466363a5eff135ad394a929f59b) +- Bump rimraf to 2.7.1 [`a6bc2d4`](https://github.com/form-data/form-data/commit/a6bc2d4296dbdee5d84cbab7c69bcd0eea7a12e2) + +## [v2.5.0](https://github.com/form-data/form-data/compare/v2.4.0...v2.5.0) - 2019-07-03 + +### Merged + +- - Added: public methods with information and examples to readme [`#429`](https://github.com/form-data/form-data/pull/429) +- chore: move @types/node to devDep [`#431`](https://github.com/form-data/form-data/pull/431) +- Switched windows tests from AppVeyor to Travis [`#430`](https://github.com/form-data/form-data/pull/430) +- feat(typings): migrate TS typings #427 [`#428`](https://github.com/form-data/form-data/pull/428) +- enhance the method of path.basename, handle undefined case [`#421`](https://github.com/form-data/form-data/pull/421) + +### Commits + +- - Added: public methods with information and examples to the readme file. [`21323f3`](https://github.com/form-data/form-data/commit/21323f3b4043a167046a4a2554c5f2825356c423) +- feat(typings): migrate TS typings [`a3c0142`](https://github.com/form-data/form-data/commit/a3c0142ed91b0c7dcaf89c4f618776708f1f70a9) +- - Fixed: Typos [`37350fa`](https://github.com/form-data/form-data/commit/37350fa250782f156a998ec1fa9671866d40ac49) +- Switched to Travis Windows from Appveyor [`fc61c73`](https://github.com/form-data/form-data/commit/fc61c7381fad12662df16dbc3e7621c91b886f03) +- - Fixed: rendering of subheaders [`e93ed8d`](https://github.com/form-data/form-data/commit/e93ed8df9d7f22078bc3a2c24889e9dfa11e192d) +- Updated deps and readme [`e3d8628`](https://github.com/form-data/form-data/commit/e3d8628728f6e4817ab97deeed92f0c822661b89) +- Updated dependencies [`19add50`](https://github.com/form-data/form-data/commit/19add50afb7de66c70d189f422d16f1b886616e2) +- Bumped version to 2.5.0 [`905f173`](https://github.com/form-data/form-data/commit/905f173a3f785e8d312998e765634ee451ca5f42) +- - Fixed: filesize is not a valid option? knownLength should be used for streams [`d88f912`](https://github.com/form-data/form-data/commit/d88f912b75b666b47f8674467516eade69d2d5be) +- Bump notion of modern node to node8 [`508b626`](https://github.com/form-data/form-data/commit/508b626bf1b460d3733d3420dc1cfd001617f6ac) +- enhance the method of path.basename [`faaa68a`](https://github.com/form-data/form-data/commit/faaa68a297be7d4fca0ac4709d5b93afc1f78b5c) + +## [v2.4.0](https://github.com/form-data/form-data/compare/v2.3.2...v2.4.0) - 2019-06-19 + +### Merged + +- Added "getBuffer" method and updated certificates [`#419`](https://github.com/form-data/form-data/pull/419) +- docs(readme): add axios integration document [`#425`](https://github.com/form-data/form-data/pull/425) +- Allow newer versions of combined-stream [`#402`](https://github.com/form-data/form-data/pull/402) + +### Commits + +- Updated: Certificate [`e90a76a`](https://github.com/form-data/form-data/commit/e90a76ab3dcaa63a6f3045f8255bfbb9c25a3e4e) +- Updated build/test/badges [`8512eef`](https://github.com/form-data/form-data/commit/8512eef436e28372f5bc88de3ca76a9cb46e6847) +- Bumped version 2.4.0 [`0f8da06`](https://github.com/form-data/form-data/commit/0f8da06c0b4c997bd2f6b09d78290d339616a950) +- docs(readme): remove unnecessary bracket [`4e3954d`](https://github.com/form-data/form-data/commit/4e3954dde304d27e3b95371d8c78002f3af5d5b2) +- Bumped version to 2.3.3 [`b16916a`](https://github.com/form-data/form-data/commit/b16916a568a0d06f3f8a16c31f9a8b89b7844094) + +## [v2.3.2](https://github.com/form-data/form-data/compare/v2.3.1...v2.3.2) - 2018-02-13 + +### Merged + +- Pulling in fixed combined-stream [`#379`](https://github.com/form-data/form-data/pull/379) + +### Commits + +- All the dev dependencies are breaking in old versions of node :'( [`c7dba6a`](https://github.com/form-data/form-data/commit/c7dba6a139d872d173454845e25e1850ed6b72b4) +- Updated badges [`19b6c7a`](https://github.com/form-data/form-data/commit/19b6c7a8a5c40f47f91c8a8da3e5e4dc3c449fa3) +- Try tests in node@4 [`872a326`](https://github.com/form-data/form-data/commit/872a326ab13e2740b660ff589b75232c3a85fcc9) +- Pull in final version [`9d44871`](https://github.com/form-data/form-data/commit/9d44871073d647995270b19dbc26f65671ce15c7) + +## [v2.3.1](https://github.com/form-data/form-data/compare/v2.3.0...v2.3.1) - 2017-08-24 + +### Commits + +- Updated readme with custom options example [`8e0a569`](https://github.com/form-data/form-data/commit/8e0a5697026016fe171e93bec43c2205279e23ca) +- Added support (tests) for node 8 [`d1d6f4a`](https://github.com/form-data/form-data/commit/d1d6f4ad4670d8ba84cc85b28e522ca0e93eb362) + +## [v2.3.0](https://github.com/form-data/form-data/compare/v2.2.0...v2.3.0) - 2017-08-24 + +### Merged + +- Added custom `options` support [`#368`](https://github.com/form-data/form-data/pull/368) +- Allow form.submit with url string param to use https [`#249`](https://github.com/form-data/form-data/pull/249) +- Proper header production [`#357`](https://github.com/form-data/form-data/pull/357) +- Fix wrong MIME type in example [`#285`](https://github.com/form-data/form-data/pull/285) + +### Commits + +- allow form.submit with url string param to use https [`c0390dc`](https://github.com/form-data/form-data/commit/c0390dcc623e15215308fa2bb0225aa431d9381e) +- update tests for url parsing [`eec0e80`](https://github.com/form-data/form-data/commit/eec0e807889d46697abd39a89ad9bf39996ba787) +- Uses for in to assign properties instead of Object.assign [`f6854ed`](https://github.com/form-data/form-data/commit/f6854edd85c708191bb9c89615a09fd0a9afe518) +- Adds test to check for option override [`61762f2`](https://github.com/form-data/form-data/commit/61762f2c5262e576d6a7f778b4ebab6546ef8582) +- Removes the 2mb maxDataSize limitation [`dc171c3`](https://github.com/form-data/form-data/commit/dc171c3ba49ac9b8813636fd4159d139b812315b) +- Ignore .DS_Store [`e8a05d3`](https://github.com/form-data/form-data/commit/e8a05d33361f7dca8927fe1d96433d049843de24) + +## [v2.2.0](https://github.com/form-data/form-data/compare/v2.1.4...v2.2.0) - 2017-06-11 + +### Merged + +- Filename can be a nested path [`#355`](https://github.com/form-data/form-data/pull/355) + +### Commits + +- Bumped version number. [`d7398c3`](https://github.com/form-data/form-data/commit/d7398c3e7cd81ed12ecc0b84363721bae467db02) + +## [v2.1.4](https://github.com/form-data/form-data/compare/2.1.3...v2.1.4) - 2017-04-08 + +## [2.1.3](https://github.com/form-data/form-data/compare/v2.1.3...2.1.3) - 2017-04-08 + +## [v2.1.3](https://github.com/form-data/form-data/compare/v2.1.2...v2.1.3) - 2017-04-08 + +### Merged + +- toString should output '[object FormData]' [`#346`](https://github.com/form-data/form-data/pull/346) + +## [v2.1.2](https://github.com/form-data/form-data/compare/v2.1.1...v2.1.2) - 2016-11-07 + +### Merged + +- #271 Added check for self and window objects + tests [`#282`](https://github.com/form-data/form-data/pull/282) + +### Commits + +- Added check for self and window objects + tests [`c99e4ec`](https://github.com/form-data/form-data/commit/c99e4ec32cd14d83776f2bdcc5a4e7384131c1b1) + +## [v2.1.1](https://github.com/form-data/form-data/compare/v2.1.0...v2.1.1) - 2016-10-03 + +### Merged + +- Bumped dependencies. [`#270`](https://github.com/form-data/form-data/pull/270) +- Update browser.js shim to use self instead of window [`#267`](https://github.com/form-data/form-data/pull/267) +- Boilerplate code rediction [`#265`](https://github.com/form-data/form-data/pull/265) +- eslint@3.7.0 [`#266`](https://github.com/form-data/form-data/pull/266) + +### Commits + +- code duplicates removed [`e9239fb`](https://github.com/form-data/form-data/commit/e9239fbe7d3c897b29fe3bde857d772469541c01) +- Changed according to requests [`aa99246`](https://github.com/form-data/form-data/commit/aa9924626bd9168334d73fea568c0ad9d8fbaa96) +- chore(package): update eslint to version 3.7.0 [`090a859`](https://github.com/form-data/form-data/commit/090a859835016cab0de49629140499e418db9c3a) + +## [v2.1.0](https://github.com/form-data/form-data/compare/v2.0.0...v2.1.0) - 2016-09-25 + +### Merged + +- Added `hasKnownLength` public method [`#263`](https://github.com/form-data/form-data/pull/263) + +### Commits + +- Added hasKnownLength public method [`655b959`](https://github.com/form-data/form-data/commit/655b95988ef2ed3399f8796b29b2a8673c1df11c) + +## [v2.0.0](https://github.com/form-data/form-data/compare/v1.0.0...v2.0.0) - 2016-09-16 + +### Merged + +- Replaced async with asynckit [`#258`](https://github.com/form-data/form-data/pull/258) +- Pre-release house cleaning [`#247`](https://github.com/form-data/form-data/pull/247) + +### Commits + +- Replaced async with asynckit. Modernized [`1749b78`](https://github.com/form-data/form-data/commit/1749b78d50580fbd080e65c1eb9702ad4f4fc0c0) +- Ignore .bak files [`c08190a`](https://github.com/form-data/form-data/commit/c08190a87d3e22a528b6e32b622193742a4c2672) +- Trying to be more chatty. :) [`c79eabb`](https://github.com/form-data/form-data/commit/c79eabb24eaf761069255a44abf4f540cfd47d40) + +## [v1.0.0](https://github.com/form-data/form-data/compare/v1.0.0-rc4...v1.0.0) - 2016-08-26 + +### Merged + +- Allow custom header fields to be set as an object. [`#190`](https://github.com/form-data/form-data/pull/190) +- v1.0.0-rc4 [`#182`](https://github.com/form-data/form-data/pull/182) +- Avoid undefined variable reference in older browsers [`#176`](https://github.com/form-data/form-data/pull/176) +- More housecleaning [`#164`](https://github.com/form-data/form-data/pull/164) +- More cleanup [`#159`](https://github.com/form-data/form-data/pull/159) +- Added windows testing. Some cleanup. [`#158`](https://github.com/form-data/form-data/pull/158) +- Housecleaning. Added test coverage. [`#156`](https://github.com/form-data/form-data/pull/156) +- Second iteration of cleanup. [`#145`](https://github.com/form-data/form-data/pull/145) + +### Commits + +- Pre-release house cleaning [`440d72b`](https://github.com/form-data/form-data/commit/440d72b5fd44dd132f42598c3183d46e5f35ce71) +- Updated deps, updated docs [`54b6114`](https://github.com/form-data/form-data/commit/54b61143e9ce66a656dd537a1e7b31319a4991be) +- make docs up-to-date [`5e383d7`](https://github.com/form-data/form-data/commit/5e383d7f1466713f7fcef58a6817e0cb466c8ba7) +- Added missing deps [`fe04862`](https://github.com/form-data/form-data/commit/fe04862000b2762245e2db69d5207696a08c1174) + +## [v1.0.0-rc4](https://github.com/form-data/form-data/compare/v1.0.0-rc3...v1.0.0-rc4) - 2016-03-15 + +### Merged + +- Housecleaning, preparing for the release [`#144`](https://github.com/form-data/form-data/pull/144) +- lib: emit error when failing to get length [`#127`](https://github.com/form-data/form-data/pull/127) +- Cleaning up for Codacity 2. [`#143`](https://github.com/form-data/form-data/pull/143) +- Cleaned up codacity concerns. [`#142`](https://github.com/form-data/form-data/pull/142) +- Should throw type error without new operator. [`#129`](https://github.com/form-data/form-data/pull/129) + +### Commits + +- More cleanup [`94b6565`](https://github.com/form-data/form-data/commit/94b6565bb98a387335c72feff5ed5c10da0a7f6f) +- Shuffling things around [`3c2f172`](https://github.com/form-data/form-data/commit/3c2f172eaddf0979b3eef5c73985d1a6fd3eee4a) +- Second iteration of cleanup. [`347c88e`](https://github.com/form-data/form-data/commit/347c88ef9a99a66b9bcf4278497425db2f0182b2) +- Housecleaning [`c335610`](https://github.com/form-data/form-data/commit/c3356100c054a4695e4dec8ed7072775cd745616) +- More housecleaning [`f573321`](https://github.com/form-data/form-data/commit/f573321824aae37ba2052a92cc889d533d9f8fb8) +- Trying to make far run on windows. + cleanup [`e426dfc`](https://github.com/form-data/form-data/commit/e426dfcefb07ee307d8a15dec04044cce62413e6) +- Playing with appveyor [`c9458a7`](https://github.com/form-data/form-data/commit/c9458a7c328782b19859bc1745e7d6b2005ede86) +- Updated dev dependencies. [`ceebe88`](https://github.com/form-data/form-data/commit/ceebe88872bb22da0a5a98daf384e3cc232928d3) +- Replaced win-spawn with cross-spawn [`405a69e`](https://github.com/form-data/form-data/commit/405a69ee34e235ee6561b5ff0140b561be40d1cc) +- Updated readme badges. [`12f282a`](https://github.com/form-data/form-data/commit/12f282a1310fcc2f70cc5669782283929c32a63d) +- Making paths windows friendly. [`f4bddc5`](https://github.com/form-data/form-data/commit/f4bddc5955e2472f8e23c892c9b4d7a08fcb85a3) +- [WIP] trying things for greater sanity [`8ad1f02`](https://github.com/form-data/form-data/commit/8ad1f02b0b3db4a0b00c5d6145ed69bcb7558213) +- Bending under Codacy [`bfff3bb`](https://github.com/form-data/form-data/commit/bfff3bb36052dc83f429949b4e6f9b146a49d996) +- Another attempt to make windows friendly [`f3eb628`](https://github.com/form-data/form-data/commit/f3eb628974ccb91ba0020f41df490207eeed77f6) +- Updated dependencies. [`f73996e`](https://github.com/form-data/form-data/commit/f73996e0508ee2d4b2b376276adfac1de4188ac2) +- Missed travis changes. [`67ee79f`](https://github.com/form-data/form-data/commit/67ee79f964fdabaf300bd41b0af0c1cfaca07687) +- Restructured badges. [`48444a1`](https://github.com/form-data/form-data/commit/48444a1ff156ba2c2c3cfd11047c2f2fd92d4474) +- Add similar type error as the browser for attempting to use form-data without new. [`5711320`](https://github.com/form-data/form-data/commit/5711320fb7c8cc620cfc79b24c7721526e23e539) +- Took out codeclimate-test-reporter [`a7e0c65`](https://github.com/form-data/form-data/commit/a7e0c6522afe85ca9974b0b4e1fca9c77c3e52b1) +- One more [`8e84cff`](https://github.com/form-data/form-data/commit/8e84cff3370526ecd3e175fd98e966242d81993c) + +## [v1.0.0-rc3](https://github.com/form-data/form-data/compare/v1.0.0-rc2...v1.0.0-rc3) - 2015-07-29 + +### Merged + +- House cleaning. Added `pre-commit`. [`#140`](https://github.com/form-data/form-data/pull/140) +- Allow custom content-type without setting a filename. [`#138`](https://github.com/form-data/form-data/pull/138) +- Add node-fetch to alternative submission methods. [`#132`](https://github.com/form-data/form-data/pull/132) +- Update dependencies [`#130`](https://github.com/form-data/form-data/pull/130) +- Switching to container based TravisCI [`#136`](https://github.com/form-data/form-data/pull/136) +- Default content-type to 'application/octect-stream' [`#128`](https://github.com/form-data/form-data/pull/128) +- Allow filename as third option of .append [`#125`](https://github.com/form-data/form-data/pull/125) + +### Commits + +- Allow custom content-type without setting a filename [`c8a77cc`](https://github.com/form-data/form-data/commit/c8a77cc0cf16d15f1ebf25272beaab639ce89f76) +- Fixed ranged test. [`a5ac58c`](https://github.com/form-data/form-data/commit/a5ac58cbafd0909f32fe8301998f689314fd4859) +- Allow filename as third option of #append [`d081005`](https://github.com/form-data/form-data/commit/d0810058c84764b3c463a18b15ebb37864de9260) +- Allow custom content-type without setting a filename [`8cb9709`](https://github.com/form-data/form-data/commit/8cb9709e5f1809cfde0cd707dbabf277138cd771) + +## [v1.0.0-rc2](https://github.com/form-data/form-data/compare/v1.0.0-rc1...v1.0.0-rc2) - 2015-07-21 + +### Merged + +- #109 Append proper line break [`#123`](https://github.com/form-data/form-data/pull/123) +- Add shim for browser (browserify/webpack). [`#122`](https://github.com/form-data/form-data/pull/122) +- Update license field [`#115`](https://github.com/form-data/form-data/pull/115) + +### Commits + +- Add shim for browser. [`87c33f4`](https://github.com/form-data/form-data/commit/87c33f4269a2211938f80ab3e53835362b1afee8) +- Bump version [`a3f5d88`](https://github.com/form-data/form-data/commit/a3f5d8872c810ce240c7d3838c69c3c9fcecc111) + +## [v1.0.0-rc1](https://github.com/form-data/form-data/compare/0.2...v1.0.0-rc1) - 2015-06-13 + +### Merged + +- v1.0.0-rc1 [`#114`](https://github.com/form-data/form-data/pull/114) +- Updated test targets [`#102`](https://github.com/form-data/form-data/pull/102) +- Remove duplicate plus sign [`#94`](https://github.com/form-data/form-data/pull/94) + +### Commits + +- Made https test local. Updated deps. [`afe1959`](https://github.com/form-data/form-data/commit/afe1959ec711f23e57038ab5cb20fedd86271f29) +- Proper self-signed ssl [`4d5ec50`](https://github.com/form-data/form-data/commit/4d5ec50e81109ad2addf3dbb56dc7c134df5ff87) +- Update HTTPS handling for modern days [`2c11b01`](https://github.com/form-data/form-data/commit/2c11b01ce2c06e205c84d7154fa2f27b66c94f3b) +- Made tests more local [`09633fa`](https://github.com/form-data/form-data/commit/09633fa249e7ce3ac581543aafe16ee9039a823b) +- Auto create tmp folder for Formidable [`28714b7`](https://github.com/form-data/form-data/commit/28714b7f71ad556064cdff88fabe6b92bd407ddd) +- remove duplicate plus sign [`36e09c6`](https://github.com/form-data/form-data/commit/36e09c695b0514d91a23f5cd64e6805404776fc7) + +## [0.2](https://github.com/form-data/form-data/compare/0.1.4...0.2) - 2014-12-06 + +### Merged + +- Bumped version [`#96`](https://github.com/form-data/form-data/pull/96) +- Replace mime library. [`#95`](https://github.com/form-data/form-data/pull/95) +- #71 Respect bytes range in a read stream. [`#73`](https://github.com/form-data/form-data/pull/73) + +## [0.1.4](https://github.com/form-data/form-data/compare/0.1.3...0.1.4) - 2014-06-23 + +### Merged + +- Updated version. [`#76`](https://github.com/form-data/form-data/pull/76) +- #71 Respect bytes range in a read stream. [`#75`](https://github.com/form-data/form-data/pull/75) + +## [0.1.3](https://github.com/form-data/form-data/compare/0.1.2...0.1.3) - 2014-06-17 + +### Merged + +- Updated versions. [`#69`](https://github.com/form-data/form-data/pull/69) +- Added custom headers support [`#60`](https://github.com/form-data/form-data/pull/60) +- Added test for Request. Small fixes. [`#56`](https://github.com/form-data/form-data/pull/56) + +### Commits + +- Added test for the custom header functionality [`bd50685`](https://github.com/form-data/form-data/commit/bd506855af62daf728ef1718cae88ed23bb732f3) +- Documented custom headers option [`77a024a`](https://github.com/form-data/form-data/commit/77a024a9375f93c246c35513d80f37d5e11d35ff) +- Removed 0.6 support. [`aee8dce`](https://github.com/form-data/form-data/commit/aee8dce604c595cfaacfc6efb12453d1691ac0d6) + +## [0.1.2](https://github.com/form-data/form-data/compare/0.1.1...0.1.2) - 2013-10-02 + +### Merged + +- Fixed default https port assignment, added tests. [`#52`](https://github.com/form-data/form-data/pull/52) +- #45 Added tests for multi-submit. Updated readme. [`#49`](https://github.com/form-data/form-data/pull/49) +- #47 return request from .submit() [`#48`](https://github.com/form-data/form-data/pull/48) + +### Commits + +- Bumped version. [`2b761b2`](https://github.com/form-data/form-data/commit/2b761b256ae607fc2121621f12c2e1042be26baf) + +## [0.1.1](https://github.com/form-data/form-data/compare/0.1.0...0.1.1) - 2013-08-21 + +### Merged + +- Added license type and reference to package.json [`#46`](https://github.com/form-data/form-data/pull/46) + +### Commits + +- #47 return request from .submit() [`1d61c2d`](https://github.com/form-data/form-data/commit/1d61c2da518bd5e136550faa3b5235bb540f1e06) +- #47 Updated readme. [`e3dae15`](https://github.com/form-data/form-data/commit/e3dae1526bd3c3b9d7aff6075abdaac12c3cc60f) + +## [0.1.0](https://github.com/form-data/form-data/compare/0.0.10...0.1.0) - 2013-07-08 + +### Merged + +- Update master to 0.1.0 [`#44`](https://github.com/form-data/form-data/pull/44) +- 0.1.0 - Added error handling. Streamlined edge cases behavior. [`#43`](https://github.com/form-data/form-data/pull/43) +- Pointed badges back to mothership. [`#39`](https://github.com/form-data/form-data/pull/39) +- Updated node-fake to support 0.11 tests. [`#37`](https://github.com/form-data/form-data/pull/37) +- Updated tests to play nice with 0.10 [`#36`](https://github.com/form-data/form-data/pull/36) +- #32 Added .npmignore [`#34`](https://github.com/form-data/form-data/pull/34) +- Spring cleaning [`#30`](https://github.com/form-data/form-data/pull/30) + +### Commits + +- Added error handling. Streamlined edge cases behavior. [`4da496e`](https://github.com/form-data/form-data/commit/4da496e577cb9bc0fd6c94cbf9333a0082ce353a) +- Made tests more deterministic. [`7fc009b`](https://github.com/form-data/form-data/commit/7fc009b8a2cc9232514a44b2808b9f89ce68f7d2) +- Fixed styling. [`d373b41`](https://github.com/form-data/form-data/commit/d373b417e779024bc3326073e176383cd08c0b18) +- #40 Updated Readme.md regarding getLengthSync() [`efb373f`](https://github.com/form-data/form-data/commit/efb373fd63814d977960e0299d23c92cd876cfef) +- Updated readme. [`527e3a6`](https://github.com/form-data/form-data/commit/527e3a63b032cb6f576f597ad7ff2ebcf8a0b9b4) + +## [0.0.10](https://github.com/form-data/form-data/compare/0.0.9...0.0.10) - 2013-05-08 + +### Commits + +- Updated tests to play nice with 0.10. [`932b39b`](https://github.com/form-data/form-data/commit/932b39b773e49edcb2c5d2e58fe389ab6c42f47c) +- Added dependency tracking. [`3131d7f`](https://github.com/form-data/form-data/commit/3131d7f6996cd519d50547e4de1587fd80d0fa07) + +## 0.0.9 - 2013-04-29 + +### Merged + +- Custom params for form.submit() should cover most edge cases. [`#22`](https://github.com/form-data/form-data/pull/22) +- Updated Readme and version number. [`#20`](https://github.com/form-data/form-data/pull/20) +- Allow custom headers and pre-known length in parts [`#17`](https://github.com/form-data/form-data/pull/17) +- Bumped version number. [`#12`](https://github.com/form-data/form-data/pull/12) +- Fix for #10 [`#11`](https://github.com/form-data/form-data/pull/11) +- Bumped version number. [`#8`](https://github.com/form-data/form-data/pull/8) +- Added support for https destination, http-response and mikeal's request streams. [`#7`](https://github.com/form-data/form-data/pull/7) +- Updated git url. [`#6`](https://github.com/form-data/form-data/pull/6) +- Version bump. [`#5`](https://github.com/form-data/form-data/pull/5) +- Changes to support custom content-type and getLengthSync. [`#4`](https://github.com/form-data/form-data/pull/4) +- make .submit(url) use host from url, not 'localhost' [`#2`](https://github.com/form-data/form-data/pull/2) +- Make package.json JSON [`#1`](https://github.com/form-data/form-data/pull/1) + +### Fixed + +- Add MIT license [`#14`](https://github.com/form-data/form-data/issues/14) + +### Commits + +- Spring cleaning. [`850ba1b`](https://github.com/form-data/form-data/commit/850ba1b649b6856b0fa87bbcb04bc70ece0137a6) +- Added custom request params to form.submit(). Made tests more stable. [`de3502f`](https://github.com/form-data/form-data/commit/de3502f6c4a509f6ed12a7dd9dc2ce9c2e0a8d23) +- Basic form (no files) working [`6ffdc34`](https://github.com/form-data/form-data/commit/6ffdc343e8594cfc2efe1e27653ea39d8980a14e) +- Got initial test to pass [`9a59d08`](https://github.com/form-data/form-data/commit/9a59d08c024479fd3c9d99ba2f0893a47b3980f0) +- Implement initial getLength [`9060c91`](https://github.com/form-data/form-data/commit/9060c91b861a6573b73beddd11e866db422b5830) +- Make getLength work with file streams [`6f6b1e9`](https://github.com/form-data/form-data/commit/6f6b1e9b65951e6314167db33b446351702f5558) +- Implemented a simplistic submit() function [`41e9cc1`](https://github.com/form-data/form-data/commit/41e9cc124124721e53bc1d1459d45db1410c44e6) +- added test for custom headers and content-length in parts (felixge/node-form-data/17) [`b16d14e`](https://github.com/form-data/form-data/commit/b16d14e693670f5d52babec32cdedd1aa07c1aa4) +- Fixed code styling. [`5847424`](https://github.com/form-data/form-data/commit/5847424c666970fc2060acd619e8a78678888a82) +- #29 Added custom filename and content-type options to support identity-less streams. [`adf8b4a`](https://github.com/form-data/form-data/commit/adf8b4a41530795682cd3e35ffaf26b30288ccda) +- Initial Readme and package.json [`8c744e5`](https://github.com/form-data/form-data/commit/8c744e58be4014bdf432e11b718ed87f03e217af) +- allow append() to completely override header and boundary [`3fb2ad4`](https://github.com/form-data/form-data/commit/3fb2ad491f66e4b4ff16130be25b462820b8c972) +- Syntax highlighting [`ab3a6a5`](https://github.com/form-data/form-data/commit/ab3a6a5ed1ab77a2943ce3befcb2bb3cd9ff0330) +- Updated Readme.md [`de8f441`](https://github.com/form-data/form-data/commit/de8f44122ca754cbfedc0d2748e84add5ff0b669) +- Added examples to Readme file. [`c406ac9`](https://github.com/form-data/form-data/commit/c406ac921d299cbc130464ed19338a9ef97cb650) +- pass options.knownLength to set length at beginning, w/o waiting for async size calculation [`e2ac039`](https://github.com/form-data/form-data/commit/e2ac0397ff7c37c3dca74fa9925b55f832e4fa0b) +- Updated dependencies and added test command. [`09bd7cd`](https://github.com/form-data/form-data/commit/09bd7cd86f1ad7a58df1b135eb6eef0d290894b4) +- Bumped version. Updated readme. [`4581140`](https://github.com/form-data/form-data/commit/4581140f322758c6fc92019d342c7d7d6c94af5c) +- Test runner [`1707ebb`](https://github.com/form-data/form-data/commit/1707ebbd180856e6ed44e80c46b02557e2425762) +- Added .npmignore, bumped version. [`2e033e0`](https://github.com/form-data/form-data/commit/2e033e0e4be7c1457be090cd9b2996f19d8fb665) +- FormData.prototype.append takes and passes along options (for header) [`b519203`](https://github.com/form-data/form-data/commit/b51920387ed4da7b4e106fc07b9459f26b5ae2f0) +- Make package.json JSON [`bf1b58d`](https://github.com/form-data/form-data/commit/bf1b58df794b10fda86ed013eb9237b1e5032085) +- Add dependencies to package.json [`7413d0b`](https://github.com/form-data/form-data/commit/7413d0b4cf5546312d47ea426db8180619083974) +- Add convenient submit() interface [`55855e4`](https://github.com/form-data/form-data/commit/55855e4bea14585d4a3faf9e7318a56696adbc7d) +- Fix content type [`08b6ae3`](https://github.com/form-data/form-data/commit/08b6ae337b23ef1ba457ead72c9b133047df213c) +- Combatting travis rvm calls. [`409adfd`](https://github.com/form-data/form-data/commit/409adfd100a3cf4968a632c05ba58d92d262d144) +- Fixed Issue #2 [`b3a5d66`](https://github.com/form-data/form-data/commit/b3a5d661739dcd6921b444b81d5cb3c32fab655d) +- Fix for #10. [`bab70b9`](https://github.com/form-data/form-data/commit/bab70b9e803e17287632762073d227d6c59989e0) +- Trying workarounds for formidable - 0.6 "love". [`25782a3`](https://github.com/form-data/form-data/commit/25782a3f183d9c30668ec2bca6247ed83f10611c) +- change whitespace to conform with felixge's style guide [`9fa34f4`](https://github.com/form-data/form-data/commit/9fa34f433bece85ef73086a874c6f0164ab7f1f6) +- Add async to deps [`b7d1a6b`](https://github.com/form-data/form-data/commit/b7d1a6b10ee74be831de24ed76843e5a6935f155) +- typo [`7860a9c`](https://github.com/form-data/form-data/commit/7860a9c8a582f0745ce0e4a0549f4bffc29c0b50) +- Bumped version. [`fa36c1b`](https://github.com/form-data/form-data/commit/fa36c1b4229c34b85d7efd41908429b6d1da3bfc) +- Updated .gitignore [`de567bd`](https://github.com/form-data/form-data/commit/de567bde620e53b8e9b0ed3506e79491525ec558) +- Don't rely on resume() being called by pipe [`1deae47`](https://github.com/form-data/form-data/commit/1deae47e042bcd170bd5dbe2b4a4fa5356bb8aa2) +- One more wrong content type [`28f166d`](https://github.com/form-data/form-data/commit/28f166d443e2eb77f2559324014670674b97e46e) +- Another typo [`b959b6a`](https://github.com/form-data/form-data/commit/b959b6a2be061cac17f8d329b89cea109f0f32be) +- Typo [`698fa0a`](https://github.com/form-data/form-data/commit/698fa0aa5dbf4eeb77377415acc202a6fbe3f4a2) +- Being simply dumb. [`b614db8`](https://github.com/form-data/form-data/commit/b614db85702061149fbd98418605106975e72ade) +- Fixed typo in the filename. [`30af6be`](https://github.com/form-data/form-data/commit/30af6be13fb0c9e92b32e935317680b9d7599928) diff --git a/package.json b/package.json index ce37435..eb906d4 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,9 @@ "restore-readme": "mv README.md.bak README.md", "prepublish": "not-in-publish || npm run prepublishOnly", "prepublishOnly": "npm run update-readme", - "postpublish": "npm run restore-readme" + "postpublish": "npm run restore-readme", + "version": "auto-changelog && git add CHANGELOG.md", + "postversion": "auto-changelog && git add CHANGELOG.md && git commit --no-edit --amend && git tag -f \"v$(node -e \"console.log(require('./package.json').version)\")\"" }, "engines": { "node": ">= 6" @@ -45,6 +47,7 @@ }, "devDependencies": { "@ljharb/eslint-config": "^21.2.0", + "auto-changelog": "^2.5.0", "browserify": "^13.3.0", "browserify-istanbul": "^2.0.0", "coveralls": "^3.1.1", @@ -62,5 +65,13 @@ "rimraf": "^2.7.1", "tape": "^5.9.0" }, - "license": "MIT" + "license": "MIT", + "auto-changelog": { + "output": "CHANGELOG.md", + "template": "keepachangelog", + "unreleased": false, + "commitLimit": false, + "backfillLimit": false, + "hideCredit": true + } } From fc38b4834a117a1856f3d877eb2f5b7496a24932 Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Wed, 16 Jul 2025 21:39:51 -0700 Subject: [PATCH 25/29] [meta] fix readme capitalization --- Readme.md => README.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename Readme.md => README.md (100%) diff --git a/Readme.md b/README.md similarity index 100% rename from Readme.md rename to README.md From 01508513ffb26fd662ae7027834b325af8efb9ea Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Wed, 16 Jul 2025 21:53:33 -0700 Subject: [PATCH 26/29] =?UTF-8?q?[meta]=20actually=20ensure=20the=20readme?= =?UTF-8?q?=20backup=20isn=E2=80=99t=20published?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .npmignore | 2 +- package.json | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/.npmignore b/.npmignore index f6eab27..d55b80c 100644 --- a/.npmignore +++ b/.npmignore @@ -9,4 +9,4 @@ node_modules/ test/ yarn.lock -README.md.bak +*.bak diff --git a/package.json b/package.json index eb906d4..57cdc25 100644 --- a/package.json +++ b/package.json @@ -28,10 +28,11 @@ "files": "pkgfiles --sort=name", "get-version": "node -e \"console.log(require('./package.json').version)\"", "update-readme": "sed -i.bak 's/\\/master\\.svg/\\/v'$(npm --silent run get-version)'.svg/g' README.md", - "restore-readme": "mv README.md.bak README.md", + "postupdate-readme": "mv README.md.bak READ.ME.md.bak", + "restore-readme": "mv READ.ME.md.bak README.md", "prepublish": "not-in-publish || npm run prepublishOnly", - "prepublishOnly": "npm run update-readme", - "postpublish": "npm run restore-readme", + "prepack": "npm run update-readme", + "postpack": "npm run restore-readme", "version": "auto-changelog && git add CHANGELOG.md", "postversion": "auto-changelog && git add CHANGELOG.md && git commit --no-edit --amend && git tag -f \"v$(node -e \"console.log(require('./package.json').version)\")\"" }, From c6ced61d4fae8f617ee2fd692133ed87baa5d0fd Mon Sep 17 00:00:00 2001 From: Ben Shonaldmann Date: Fri, 21 Feb 2025 21:20:43 -0500 Subject: [PATCH 27/29] [Fix] Switch to using `crypto` random for boundary values --- lib/form_data.js | 13 ++--- package.json | 3 ++ test/integration/test-boundary-prediction.js | 52 ++++++++++++++++++++ 3 files changed, 59 insertions(+), 9 deletions(-) create mode 100644 test/integration/test-boundary-prediction.js diff --git a/lib/form_data.js b/lib/form_data.js index d34eefe..5b80aa4 100644 --- a/lib/form_data.js +++ b/lib/form_data.js @@ -7,6 +7,7 @@ var http = require('http'); var https = require('https'); var parseUrl = require('url').parse; var fs = require('fs'); +var crypto = require('crypto'); var mime = require('mime-types'); var asynckit = require('asynckit'); var setToStringTag = require('es-set-tostringtag'); @@ -356,16 +357,10 @@ FormData.prototype.getBuffer = function () { }; FormData.prototype._generateBoundary = function () { - /* - * This generates a 50 character boundary similar to those used by Firefox. - * They are optimized for boyer-moore parsing. - */ - var boundary = '--------------------------'; - for (var i = 0; i < 24; i++) { - boundary += Math.floor(Math.random() * 10).toString(16); - } + // This generates a 50 character boundary similar to those used by Firefox. - this._boundary = boundary; + // They are optimized for boyer-moore parsing. + this._boundary = '--------------------------' + crypto.randomBytes(12).toString('hex'); }; /* diff --git a/package.json b/package.json index 57cdc25..7b83191 100644 --- a/package.json +++ b/package.json @@ -62,6 +62,9 @@ "istanbul": "^0.4.5", "obake": "^0.1.2", "pkgfiles": "^2.3.2", + "pre-commit": "^1.2.2", + "predict-v8-randomness": "^1.0.35", + "puppeteer": "^1.20.0", "request": "~2.87.0", "rimraf": "^2.7.1", "tape": "^5.9.0" diff --git a/test/integration/test-boundary-prediction.js b/test/integration/test-boundary-prediction.js new file mode 100644 index 0000000..026c42b --- /dev/null +++ b/test/integration/test-boundary-prediction.js @@ -0,0 +1,52 @@ +'use strict'; + +var common = require('../common'); +var assert = common.assert; +var FormData = require(common.dir.lib + '/form_data'); +var predictV8Randomness = require('predict-v8-randomness'); + +var initialSequence = [ + Math.random(), + Math.random(), + Math.random(), + Math.random(), +]; +var predictor = new predictV8Randomness.Predictor(initialSequence); + +predictor.predictNext(24).then(function (next24RandomOutputs) { + var predictedBoundary = next24RandomOutputs + .map(function (v) { + return Math.floor(v * 10).toString(16); + }) + .join(''); + + var boundaryIntro = '----------------------------'; + + var payload = 'zzz\r\n' + boundaryIntro + predictedBoundary + '\r\nContent-Disposition: form-data; name="is_admin"\r\n\r\ntrue\r\n' + boundaryIntro + predictedBoundary + '--\r\n'; + + var FIELDS = { + my_field: { + value: payload, + }, + }; + + // count total + var fieldsPassed = Object.keys(FIELDS).length; + + // prepare form-receiving http server + var server = common.testFields(FIELDS, function (fields) { + fieldsPassed = fields; + }); + + server.listen(common.port, function () { + var form = new FormData(); + + common.actions.populateFields(form, FIELDS); + + common.actions.submit(form, server); + }); + + process.on('exit', function () { + assert.strictEqual(fieldsPassed, 0); + }); +}); From e8c574cb07ff3a0de2ecc0912d783ef22e190c1f Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Wed, 16 Jul 2025 19:34:29 -0700 Subject: [PATCH 28/29] [Tests] handle predict-v8-randomness failures in node < 17 and node > 23 See https://github.com/matthewoestreich/predict-v8-randomness/issues/2 --- package.json | 1 + test/integration/test-boundary-prediction.js | 61 ++++++++++---------- 2 files changed, 33 insertions(+), 29 deletions(-) diff --git a/package.json b/package.json index 7b83191..34ca8e7 100644 --- a/package.json +++ b/package.json @@ -67,6 +67,7 @@ "puppeteer": "^1.20.0", "request": "~2.87.0", "rimraf": "^2.7.1", + "semver": "^6.3.1", "tape": "^5.9.0" }, "license": "MIT", diff --git a/test/integration/test-boundary-prediction.js b/test/integration/test-boundary-prediction.js index 026c42b..6b3cc82 100644 --- a/test/integration/test-boundary-prediction.js +++ b/test/integration/test-boundary-prediction.js @@ -3,7 +3,8 @@ var common = require('../common'); var assert = common.assert; var FormData = require(common.dir.lib + '/form_data'); -var predictV8Randomness = require('predict-v8-randomness'); +var satisfies = require('semver').satisfies; +var predictV8Randomness = satisfies(process.version, '^17 - ^23') && require('predict-v8-randomness'); // eslint-disable-line global-require var initialSequence = [ Math.random(), @@ -11,42 +12,44 @@ var initialSequence = [ Math.random(), Math.random(), ]; -var predictor = new predictV8Randomness.Predictor(initialSequence); +var predictor = predictV8Randomness && new predictV8Randomness.Predictor(initialSequence); -predictor.predictNext(24).then(function (next24RandomOutputs) { - var predictedBoundary = next24RandomOutputs - .map(function (v) { - return Math.floor(v * 10).toString(16); - }) - .join(''); +if (predictor) { + predictor.predictNext(24).then(function (next24RandomOutputs) { + var predictedBoundary = next24RandomOutputs + .map(function (v) { + return Math.floor(v * 10).toString(16); + }) + .join(''); - var boundaryIntro = '----------------------------'; + var boundaryIntro = '----------------------------'; - var payload = 'zzz\r\n' + boundaryIntro + predictedBoundary + '\r\nContent-Disposition: form-data; name="is_admin"\r\n\r\ntrue\r\n' + boundaryIntro + predictedBoundary + '--\r\n'; + var payload = 'zzz\r\n' + boundaryIntro + predictedBoundary + '\r\nContent-Disposition: form-data; name="is_admin"\r\n\r\ntrue\r\n' + boundaryIntro + predictedBoundary + '--\r\n'; - var FIELDS = { - my_field: { - value: payload, - }, - }; + var FIELDS = { + my_field: { + value: payload, + }, + }; - // count total - var fieldsPassed = Object.keys(FIELDS).length; + // count total + var fieldsPassed = Object.keys(FIELDS).length; - // prepare form-receiving http server - var server = common.testFields(FIELDS, function (fields) { - fieldsPassed = fields; - }); + // prepare form-receiving http server + var server = common.testFields(FIELDS, function (fields) { + fieldsPassed = fields; + }); - server.listen(common.port, function () { - var form = new FormData(); + server.listen(common.port, function () { + var form = new FormData(); - common.actions.populateFields(form, FIELDS); + common.actions.populateFields(form, FIELDS); - common.actions.submit(form, server); - }); + common.actions.submit(form, server); + }); - process.on('exit', function () { - assert.strictEqual(fieldsPassed, 0); + process.on('exit', function () { + assert.strictEqual(fieldsPassed, 0); + }); }); -}); +} From 9c82fcdf0858b2764060a87803a55375ffbee6ed Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Wed, 16 Jul 2025 23:16:43 -0700 Subject: [PATCH 29/29] v3.0.4 --- CHANGELOG.md | 35 ++++++++++++++++++++++++++++++++++- package.json | 2 +- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b57a80c..f779e96 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,18 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [v4.0.4](https://github.com/form-data/form-data/compare/v4.0.3...v4.0.4) - 2025-07-16 + +### Commits + +- [meta] add `auto-changelog` [`811f682`](https://github.com/form-data/form-data/commit/811f68282fab0315209d0e2d1c44b6c32ea0d479) +- [Tests] handle predict-v8-randomness failures in node < 17 and node > 23 [`1d11a76`](https://github.com/form-data/form-data/commit/1d11a76434d101f22fdb26b8aef8615f28b98402) +- [Fix] Switch to using `crypto` random for boundary values [`3d17230`](https://github.com/form-data/form-data/commit/3d1723080e6577a66f17f163ecd345a21d8d0fd0) +- [Tests] fix linting errors [`5e34080`](https://github.com/form-data/form-data/commit/5e340800b5f8914213e4e0378c084aae71cfd73a) +- [meta] actually ensure the readme backup isn’t published [`316c82b`](https://github.com/form-data/form-data/commit/316c82ba93fd4985af757b771b9a1f26d3b709ef) +- [Dev Deps] update `@ljharb/eslint-config` [`58c25d7`](https://github.com/form-data/form-data/commit/58c25d76406a5b0dfdf54045cf252563f2bbda8d) +- [meta] fix readme capitalization [`2300ca1`](https://github.com/form-data/form-data/commit/2300ca19595b0ee96431e868fe2a40db79e41c61) + ## [v4.0.3](https://github.com/form-data/form-data/compare/v4.0.2...v4.0.3) - 2025-06-05 ### Fixed @@ -74,7 +86,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - fix (npmignore): ignore temporary build files [`335ad19`](https://github.com/form-data/form-data/commit/335ad19c6e17dc2d7298ffe0e9b37ba63600e94b) - fix: move util.isArray to Array.isArray [`440d3be`](https://github.com/form-data/form-data/commit/440d3bed752ac2f9213b4c2229dbccefe140e5fa) -## [v4.0.0](https://github.com/form-data/form-data/compare/v3.0.3...v4.0.0) - 2021-02-15 +## [v4.0.0](https://github.com/form-data/form-data/compare/v3.0.4...v4.0.0) - 2021-02-15 ### Merged @@ -85,6 +97,27 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fix typo [`e705c0a`](https://github.com/form-data/form-data/commit/e705c0a1fdaf90d21501f56460b93e43a18bd435) - Update README for custom stream behavior [`6dd8624`](https://github.com/form-data/form-data/commit/6dd8624b2999e32768d62752c9aae5845a803b0d) +## [v3.0.4](https://github.com/form-data/form-data/compare/v3.0.3...v3.0.4) - 2025-07-16 + +### Fixed + +- [Fix] `append`: avoid a crash on nullish values [`#577`](https://github.com/form-data/form-data/issues/577) + +### Commits + +- [eslint] update linting config [`f5e7eb0`](https://github.com/form-data/form-data/commit/f5e7eb024bc3fc7e2074ff80f143a4f4cbc1dbda) +- [meta] add `auto-changelog` [`d2eb290`](https://github.com/form-data/form-data/commit/d2eb290a3e47ed5bcad7020d027daa15b3cf5ef5) +- [Tests] handle predict-v8-randomness failures in node < 17 and node > 23 [`e8c574c`](https://github.com/form-data/form-data/commit/e8c574cb07ff3a0de2ecc0912d783ef22e190c1f) +- [Fix] Switch to using `crypto` random for boundary values [`c6ced61`](https://github.com/form-data/form-data/commit/c6ced61d4fae8f617ee2fd692133ed87baa5d0fd) +- [Refactor] use `hasown` [`1a78b5d`](https://github.com/form-data/form-data/commit/1a78b5dd05e508d67e97764d812ac7c6d92ea88d) +- [Fix] validate boundary type in `setBoundary()` method [`70bbaa0`](https://github.com/form-data/form-data/commit/70bbaa0b395ca0fb975c309de8d7286979254cc4) +- [Tests] add tests to check the behavior of `getBoundary` with non-strings [`b22a64e`](https://github.com/form-data/form-data/commit/b22a64ef94ba4f3f6ff7d1ac72a54cca128567df) +- [meta] actually ensure the readme backup isn’t published [`0150851`](https://github.com/form-data/form-data/commit/01508513ffb26fd662ae7027834b325af8efb9ea) +- [meta] remove local commit hooks [`fc42bb9`](https://github.com/form-data/form-data/commit/fc42bb9315b641bfa6dae51cb4e188a86bb04769) +- [Dev Deps] remove unused deps [`a14d09e`](https://github.com/form-data/form-data/commit/a14d09ea8ed7e0a2e1705269ce6fb54bb7ee6bdb) +- [meta] fix scripts to use prepublishOnly [`11d9f73`](https://github.com/form-data/form-data/commit/11d9f7338f18a59b431832a3562b49baece0a432) +- [meta] fix readme capitalization [`fc38b48`](https://github.com/form-data/form-data/commit/fc38b4834a117a1856f3d877eb2f5b7496a24932) + ## [v3.0.3](https://github.com/form-data/form-data/compare/v3.0.2...v3.0.3) - 2025-02-14 ### Merged diff --git a/package.json b/package.json index 34ca8e7..0df491d 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "author": "Felix Geisendörfer (http://debuggable.com/)", "name": "form-data", "description": "A library to create readable \"multipart/form-data\" streams. Can be used to submit forms and file uploads to other web applications.", - "version": "3.0.3", + "version": "3.0.4", "repository": { "type": "git", "url": "git://github.com/form-data/form-data.git"