Bump form-data from 2.5.1 to 2.5.5 in the npm_and_yarn group (#2982)

* Bump form-data from 2.5.1 to 2.5.5 in the npm_and_yarn group

Bumps the npm_and_yarn group with 1 update: [form-data](https://github.com/form-data/form-data).


Updates `form-data` from 2.5.1 to 2.5.5
- [Release notes](https://github.com/form-data/form-data/releases)
- [Changelog](https://github.com/form-data/form-data/blob/v2.5.5/CHANGELOG.md)
- [Commits](https://github.com/form-data/form-data/compare/v2.5.1...v2.5.5)

---
updated-dependencies:
- dependency-name: form-data
  dependency-version: 2.5.5
  dependency-type: indirect
  dependency-group: npm_and_yarn
...

Signed-off-by: dependabot[bot] <support@github.com>

* Update checked-in dependencies

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Michael B. Gale <mbg@github.com>
This commit is contained in:
dependabot[bot]
2025-07-30 16:14:48 +01:00
committed by GitHub
parent 20c7f06b9a
commit b9b3b12fa2
9 changed files with 888 additions and 562 deletions

View File

@@ -1,3 +1,5 @@
'use strict';
var CombinedStream = require('combined-stream');
var util = require('util');
var path = require('path');
@@ -5,15 +7,13 @@ 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 hasOwn = require('hasown');
var setToStringTag = require('es-set-tostringtag');
var populate = require('./populate.js');
// Public API
module.exports = FormData;
// make it a Stream
util.inherits(FormData, CombinedStream);
var Buffer = require('safe-buffer').Buffer;
/**
* Create readable "multipart/form-data" streams.
@@ -35,34 +35,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 == null) {
value = String(value);
}
// https://github.com/felixge/node-form-data/issues/38
if (util.isArray(value)) {
// Please convert your array into string
// the way web server expects it
if (Array.isArray(value)) {
/*
* Please convert your array into string
* the way web server expects it
*/
this._error(new Error('Arrays are not supported.'));
return;
}
@@ -78,15 +83,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') {
@@ -96,12 +103,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 && value.hasOwnProperty('httpVersion')) )) {
if (!value || (!value.path && !(value.readable && hasOwn(value, 'httpVersion')))) {
return;
}
@@ -111,28 +116,31 @@ FormData.prototype._trackLength = function(header, value, options) {
}
};
FormData.prototype._lengthRetriever = function(value, callback) {
FormData.prototype._lengthRetriever = function (value, callback) {
if (hasOwn(value, 'fd')) {
if (value.hasOwnProperty('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 != null && value.end !== Infinity && value.start != null) {
// 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
/*
* 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;
@@ -148,15 +156,15 @@ FormData.prototype._lengthRetriever = function(value, callback) {
}
// or http response
} else if (value.hasOwnProperty('httpVersion')) {
callback(null, +value.headers['content-length']);
} else if (hasOwn(value, 'httpVersion')) {
callback(null, Number(value.headers['content-length']));
// or request stream http://github.com/mikeal/request
} else if (value.hasOwnProperty('httpModule')) {
} else if (hasOwn(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 +174,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,57 +188,58 @@ 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) {
if (!headers.hasOwnProperty(prop)) continue;
header = headers[prop];
for (var prop in headers) { // eslint-disable-line no-restricted-syntax
if (hasOwn(headers, prop)) {
header = headers[prop];
// skip nullish headers.
if (header == null) {
continue;
}
// skip nullish headers.
if (header == null) {
continue; // eslint-disable-line no-continue, no-restricted-syntax
}
// 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;
}
}
}
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
filename = path.basename(options.filename || value.name || value.path);
} else if (value.readable && value.hasOwnProperty('httpVersion')) {
} 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 && (value.name || value.path)));
} else if (value && value.readable && hasOwn(value, 'httpVersion')) {
// or try http response
filename = path.basename(value.client._httpMessage.path || '');
}
@@ -240,23 +251,23 @@ 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;
// 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 && value.hasOwnProperty('httpVersion')) {
if (!contentType && value && value.readable && hasOwn(value, 'httpVersion')) {
contentType = value.headers['content-type'];
}
@@ -266,18 +277,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 && value && 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();
}
@@ -286,18 +297,18 @@ 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) {
if (userHeaders.hasOwnProperty(header)) {
for (header in userHeaders) { // eslint-disable-line no-restricted-syntax
if (hasOwn(userHeaders, header)) {
formHeaders[header.toLowerCase()] = userHeaders[header];
}
}
@@ -305,7 +316,14 @@ FormData.prototype.getHeaders = function(userHeaders) {
return formHeaders;
};
FormData.prototype.getBoundary = function() {
FormData.prototype.setBoundary = function (boundary) {
if (typeof boundary !== 'string') {
throw new TypeError('FormData boundary must be a string');
}
this._boundary = boundary;
};
FormData.prototype.getBoundary = function () {
if (!this._boundary) {
this._generateBoundary();
}
@@ -313,8 +331,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.
@@ -322,61 +340,65 @@ 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() {
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._boundary = boundary;
// They are optimized for boyer-moore parsing.
this._boundary = '--------------------------' + crypto.randomBytes(12).toString('hex');
};
// 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) {
@@ -386,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) {
@@ -398,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;
});
@@ -412,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
@@ -436,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;
}
}
@@ -444,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;
@@ -470,7 +493,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();
@@ -481,3 +504,6 @@ FormData.prototype._error = function(err) {
FormData.prototype.toString = function () {
return '[object FormData]';
};
setToStringTag(FormData, 'FormData');
module.exports = FormData;