diff --git a/.eslintrc b/.eslintrc index 111719d..5667dbe 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,10 +1,11 @@ { + "root": true, + + "extends": "@ljharb", + "rules": { - "indent": [2, 2, {"SwitchCase": 1}], - "quotes": [2, "single"], - "linebreak-style": [2, "unix"], - "semi": [2, "always"], - "curly": [2, "multi-line"], + "indent": [2, 2, {"SwitchCase": 2}], + // "curly": [2, "multi-line"], "handle-callback-err": [2, "^err"], "valid-jsdoc": [2, { "requireReturn": false, @@ -19,30 +20,35 @@ } }], "no-redeclare": [2, { "builtinGlobals": true }], - "no-shadow": [2, { "builtinGlobals": true, "hoist": "all" }], + "no-shadow": [2, { "builtinGlobals": false, "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 + + "no-underscore-dangle": 0, + "camelcase": 0, + "func-style": 0, + "max-lines": 0, + "id-length": 1, + "multiline-comment-style": 0, + + "no-plusplus": 1, + "no-caller": 1, }, + "env": { "node": true }, + "ignorePatterns": [ "node_modules/*", "index.d.ts", "coverage", - ] + ], } diff --git a/Readme.md b/Readme.md index b09df6a..262ccf5 100644 --- a/Readme.md +++ b/Readme.md @@ -42,7 +42,7 @@ var http = require('http'); var form = new FormData(); -http.request('http://nodejs.org/images/logo.png', function(response) { +http.request('http://nodejs.org/images/logo.png', function (response) { form.append('my_field', 'my value'); form.append('my_buffer', new Buffer(10)); form.append('my_logo', response); @@ -65,7 +65,7 @@ form.append('my_logo', request('http://nodejs.org/images/logo.png')); In order to submit this form to a web application, call ```submit(url, [callback])``` method: ``` javascript -form.submit('http://example.org/', function(err, res) { +form.submit('http://example.org/', function (err, res) { // res – response object (http.IncomingMessage) // res.resume(); }); @@ -104,7 +104,7 @@ var request = http.request({ form.pipe(request); -request.on('response', function(res) { +request.on('response', function (res) { console.log(res.statusCode); }); ``` @@ -112,7 +112,7 @@ request.on('response', function(res) { Or if you would prefer the `'Content-Length'` header to be set for you: ``` javascript -form.submit('example.org/upload', function(err, res) { +form.submit('example.org/upload', function (err, res) { console.log(res.statusCode); }); ``` @@ -130,7 +130,7 @@ var options = { form.append('my_buffer', buffer, options); -form.submit('http://example.com/', function(err, res) { +form.submit('http://example.com/', function (err, res) { if (err) throw err; console.log('Done'); }); @@ -139,7 +139,7 @@ form.submit('http://example.com/', function(err, res) { Form-Data can recognize and fetch all the required information from common types of streams (```fs.readStream```, ```http.response``` and ```mikeal's request```), for some other types of streams you'd need to provide "file"-related information manually: ``` javascript -someModule.stream(function(err, stdout, stderr) { +someModule.stream(function (err, stdout, stderr) { if (err) throw err; var form = new FormData(); @@ -151,7 +151,7 @@ someModule.stream(function(err, stdout, stderr) { knownLength: 19806 }); - form.submit('http://example.com/', function(err, res) { + form.submit('http://example.com/', function (err, res) { if (err) throw err; console.log('Done'); }); @@ -167,7 +167,7 @@ form.submit({ host: 'example.com', path: '/probably.php?extra=params', auth: 'username:password' -}, function(err, res) { +}, function (err, res) { console.log(res.statusCode); }); ``` @@ -178,8 +178,8 @@ In case you need to also send custom HTTP headers with the POST request, you can form.submit({ host: 'example.com', path: '/surelynot.php', - headers: {'x-test-header': 'test-header-value'} -}, function(err, res) { + headers: { 'x-test-header': 'test-header-value' } +}, function (err, res) { console.log(res.statusCode); }); ``` @@ -201,20 +201,20 @@ form.submit({ Append data to the form. You can submit about any format (string, integer, boolean, buffer, etc.). However, Arrays are not supported and need to be turned into strings by the user. ```javascript var form = new FormData(); -form.append( 'my_string', 'my value' ); -form.append( 'my_integer', 1 ); -form.append( 'my_boolean', true ); -form.append( 'my_buffer', new Buffer(10) ); -form.append( 'my_array_as_json', JSON.stringify( ['bird','cute'] ) ) +form.append('my_string', 'my value'); +form.append('my_integer', 1); +form.append('my_boolean', true); +form.append('my_buffer', new Buffer(10)); +form.append('my_array_as_json', JSON.stringify(['bird', 'cute'])); ``` You may provide a string for options, or an object. ```javascript // Set filename by providing a string for options -form.append( 'my_file', fs.createReadStream('/foo/bar.jpg'), 'bar.jpg' ); +form.append('my_file', fs.createReadStream('/foo/bar.jpg'), 'bar.jpg'); // provide an object. -form.append( 'my_file', fs.createReadStream('/foo/bar.jpg'), {filename: 'bar.jpg', contentType: 'image/jpeg', knownLength: 19806} ); +form.append('my_file', fs.createReadStream('/foo/bar.jpg'), { filename: 'bar.jpg', contentType: 'image/jpeg', knownLength: 19806 }); ``` #### _Headers_ getHeaders( [**Headers** _userHeaders_] ) @@ -236,13 +236,10 @@ _Note: The boundary must be unique and may not appear in the data._ Return the full formdata request package, as a Buffer. You can insert this Buffer in e.g. Axios to send multipart data. ```javascript var form = new FormData(); -form.append( 'my_buffer', Buffer.from([0x4a,0x42,0x20,0x52,0x6f,0x63,0x6b,0x73]) ); -form.append( 'my_file', fs.readFileSync('/foo/bar.jpg') ); +form.append('my_buffer', Buffer.from([0x4a,0x42,0x20,0x52,0x6f,0x63,0x6b,0x73])); +form.append('my_file', fs.readFileSync('/foo/bar.jpg')); -axios.post( 'https://example.com/path/to/api', - form.getBuffer(), - form.getHeaders() - ) +axios.post('https://example.com/path/to/api', form.getBuffer(), form.getHeaders()); ``` **Note:** Because the output is of type Buffer, you can only append types that are accepted by Buffer: *string, Buffer, ArrayBuffer, Array, or Array-like Object*. A ReadStream for example will result in an error. @@ -251,10 +248,10 @@ Same as `getLength` but synchronous. _Note: getLengthSync __doesn't__ calculate streams length._ -#### _Integer_ getLength( **function** _callback_ ) +#### _Integer_ getLength(**function** _callback_ ) Returns the `Content-Length` async. The callback is used to handle errors and continue once the length has been calculated ```javascript -this.getLength(function(err, length) { +this.getLength(function (err, length) { if (err) { this._error(err); return; @@ -270,13 +267,13 @@ this.getLength(function(err, length) { #### _Boolean_ hasKnownLength() Checks if the length of added values is known. -#### _Request_ submit( _params_, **function** _callback_ ) +#### _Request_ submit(_params_, **function** _callback_ ) Submit the form to a web application. ```javascript var form = new FormData(); -form.append( 'my_string', 'Hello World' ); +form.append('my_string', 'Hello World'); -form.submit( 'http://example.com/', function(err, res) { +form.submit('http://example.com/', function (err, res) { // res – response object (http.IncomingMessage) // res.resume(); } ); @@ -297,7 +294,7 @@ var formData = { my_file: fs.createReadStream(__dirname + '/unicycle.jpg'), }; -request.post({url:'http://service.com/upload', formData: formData}, function(err, httpResponse, body) { +request.post({url:'http://service.com/upload', formData: formData}, function (err, httpResponse, body) { if (err) { return console.error('upload failed:', err); } @@ -317,9 +314,9 @@ var form = new FormData(); form.append('a', 1); fetch('http://example.com', { method: 'POST', body: form }) - .then(function(res) { + .then(function (res) { return res.json(); - }).then(function(json) { + }).then(function (json) { console.log(json); }); ``` @@ -341,8 +338,8 @@ axios.post('http://example.com', form, { ...formHeaders, }, }) -.then(response => response) -.catch(error => error) + .then(response => response) + .catch(error => error) ``` ## Notes 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 3479d18..cbf498c 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'); @@ -9,21 +11,16 @@ var Stream = require('stream').Stream; var mime = require('mime-types'); var asynckit = require('asynckit'); var setToStringTag = require('es-set-tostringtag'); +var hasOwn = require('hasown'); 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 * and file uploads to other web applications. * * @constructor - * @param {Object} options - Properties to be added/overriden for FormData and CombinedStream + * @param {object} options - Properties to be added/overriden for FormData and CombinedStream */ function FormData(options) { if (!(this instanceof FormData)) { @@ -36,35 +33,39 @@ function FormData(options) { CombinedStream.call(this); - options = options || {}; - for (var option in options) { + options = options || {}; // eslint-disable-line no-param-reassign + 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) { - - options = options || {}; +FormData.prototype.append = function (field, value, options) { + options = options || {}; // eslint-disable-line no-param-reassign // allow filename as single option - if (typeof options == 'string') { - options = {filename: options}; + if (typeof options === 'string') { + options = { filename: options }; // eslint-disable-line no-param-reassign } 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); // eslint-disable-line no-param-reassign } // 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; } @@ -80,15 +81,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') { @@ -98,12 +101,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 or not a stream - if (!value || ( !value.path && !(value.readable && Object.prototype.hasOwnProperty.call(value, 'httpVersion')) && !(value instanceof Stream))) { + if (!value || (!value.path && !(value.readable && hasOwn(value, 'httpVersion')) && !(value instanceof Stream))) { return; } @@ -113,9 +114,8 @@ FormData.prototype._trackLength = function(header, value, options) { } }; -FormData.prototype._lengthRetriever = function(value, callback) { - if (Object.prototype.hasOwnProperty.call(value, 'fd')) { - +FormData.prototype._lengthRetriever = function (value, callback) { + if (hasOwn(value, 'fd')) { // take read range into a account // `end` = Infinity –> read file till the end // @@ -124,54 +124,52 @@ FormData.prototype._lengthRetriever = function(value, callback) { // 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 - callback(null, value.end + 1 - (value.start ? value.start : 0)); + callback(null, value.end + 1 - (value.start ? value.start : 0)); // eslint-disable-line callback-return - // not that fast snoopy + // not that fast snoopy } else { // still need to fetch file size from fs - fs.stat(value.path, function(err, stat) { - - var fileSize; - + fs.stat(value.path, function (err, stat) { if (err) { callback(err); return; } // update final size based on the range options - fileSize = stat.size - (value.start ? value.start : 0); + var fileSize = stat.size - (value.start ? value.start : 0); callback(null, fileSize); }); } - // or http response - } else if (Object.prototype.hasOwnProperty.call(value, 'httpVersion')) { - callback(null, +value.headers['content-length']); + // or http response + } else if (hasOwn(value, 'httpVersion')) { + callback(null, Number(value.headers['content-length'])); // eslint-disable-line callback-return - // or request stream http://github.com/mikeal/request - } else if (Object.prototype.hasOwnProperty.call(value, 'httpModule')) { + // or request stream http://github.com/mikeal/request + } 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(); - // something else + // something else } else { - callback('Unknown stream'); + callback('Unknown stream'); // eslint-disable-line callback-return } }; -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; } @@ -179,7 +177,7 @@ 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 @@ -187,18 +185,18 @@ FormData.prototype._multiPartHeader = function(field, value, options) { }; // 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 (Object.prototype.hasOwnProperty.call(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; + continue; // eslint-disable-line no-restricted-syntax, no-continue } // convert all headers to arrays. @@ -216,49 +214,45 @@ 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) { // eslint-disable-line consistent-return + var filename; 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 && Object.prototype.hasOwnProperty.call(value, '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 || ''); } if (filename) { - contentDisposition = 'filename="' + filename + '"'; + return 'filename="' + filename + '"'; } - - 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 && Object.prototype.hasOwnProperty.call(value, 'httpVersion')) { + if (!contentType && value && value.readable && hasOwn(value, 'httpVersion')) { contentType = value.headers['content-type']; } @@ -268,18 +262,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(); } @@ -288,18 +282,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() }; - for (header in userHeaders) { - if (Object.prototype.hasOwnProperty.call(userHeaders, header)) { + for (header in userHeaders) { // eslint-disable-line no-restricted-syntax + if (hasOwn(userHeaders, header)) { formHeaders[header.toLowerCase()] = userHeaders[header]; } } @@ -307,11 +301,14 @@ FormData.prototype.getHeaders = function(userHeaders) { return formHeaders; }; -FormData.prototype.setBoundary = function(boundary) { +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() { +FormData.prototype.getBoundary = function () { if (!this._boundary) { this._generateBoundary(); } @@ -319,34 +316,34 @@ FormData.prototype.getBoundary = function() { return this._boundary; }; -FormData.prototype.getBuffer = function() { - var dataBuffer = new Buffer.alloc(0); +FormData.prototype.getBuffer = function () { + var dataBuffer = new Buffer.alloc(0); // eslint-disable-line new-cap var boundary = this.getBoundary(); // Create the form content. Add Line breaks to the end of data. for (var i = 0, len = this._streams.length; i < len; i++) { 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++) { @@ -357,22 +354,22 @@ FormData.prototype._generateBoundary = 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() { +// 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.')); } @@ -382,7 +379,7 @@ FormData.prototype.getLengthSync = 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() { +FormData.prototype.hasKnownLength = function () { var hasKnownLength = true; if (this._valuesToMeasure.length) { @@ -392,7 +389,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) { @@ -404,13 +401,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; }); @@ -418,31 +415,26 @@ 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') { - - params = parseUrl(params); + // parse provided url if it's string or treat it as options object + if (typeof params === 'string') { + params = parseUrl(params); // eslint-disable-line no-param-reassign + /* eslint sort-keys: 0 */ options = populate({ port: params.port, path: params.pathname, host: params.hostname, protocol: params.protocol }, defaults); - - // use custom params - } else { - + } else { // use custom params 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; } } @@ -450,14 +442,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 && err !== 'Unknown stream') { this._error(err); return; @@ -476,7 +468,7 @@ FormData.prototype.submit = function(params, cb) { request.removeListener('error', callback); request.removeListener('response', onResponse); - return cb.call(this, error, responce); + return cb.call(this, error, responce); // eslint-disable-line no-invalid-this }; onResponse = callback.bind(this, null); @@ -489,7 +481,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(); @@ -501,3 +493,6 @@ FormData.prototype.toString = function () { return '[object FormData]'; }; setToStringTag(FormData, 'FormData'); + +// Public API +module.exports = FormData; diff --git a/lib/populate.js b/lib/populate.js index 4d35738..55ac3bb 100644 --- a/lib/populate.js +++ b/lib/populate.js @@ -1,9 +1,9 @@ -// populates missing values -module.exports = function(dst, src) { +'use strict'; - Object.keys(src).forEach(function(prop) - { - dst[prop] = dst[prop] || src[prop]; +// populates missing values +module.exports = function (dst, src) { + Object.keys(src).forEach(function (prop) { + dst[prop] = dst[prop] || src[prop]; // eslint-disable-line no-param-reassign }); return dst; diff --git a/package.json b/package.json index 47fc92b..6b3d971 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": "4.0.2", + "version": "4.0.3", "repository": { "type": "git", "url": "git://github.com/form-data/form-data.git" @@ -29,14 +29,10 @@ "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": [ - "lint", - "ci-test", - "check" - ], "engines": { "node": ">= 6" }, @@ -44,17 +40,16 @@ "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", "mime-types": "^2.1.12" }, "devDependencies": { - "@types/combined-stream": "^1.0.6", - "@types/mime-types": "^2.1.4", - "@types/node": "^12.20.55", + "@ljharb/eslint-config": "^21.1.1", "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", @@ -63,12 +58,9 @@ "istanbul": "^0.4.5", "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" } diff --git a/test/common.js b/test/common.js index f3d6371..53e27c3 100644 --- a/test/common.js +++ b/test/common.js @@ -5,6 +5,7 @@ var fake = require('fake'); var mime = require('mime-types'); var http = require('http'); var IncomingForm = require('formidable').IncomingForm; +var hasOwn = require('hasown'); var common = module.exports; @@ -32,18 +33,16 @@ common.httpsServerKey = fs.readFileSync(path.join(__dirname, './fixture/key.pem' common.httpsServerCert = fs.readFileSync(path.join(__dirname, './fixture/cert.pem')); common.testFields = function (FIELDS, callback) { - var fieldsPassed = Object.keys(FIELDS).length; 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); common.actions.checkForm(incomingForm, FIELDS, function (fieldsChecked) { // keep track of number of the processed fields - callback(fieldsPassed - fieldsChecked); + callback(fieldsPassed - fieldsChecked); // eslint-disable-line callback-return // finish it common.actions.formOnEnd(res); }); @@ -57,11 +56,11 @@ common.actions = {}; // generic form field population common.actions.populateFields = function (form, fields) { var field; - for (var name in fields) { - if (Object.prototype.hasOwnProperty.call(fields, name)) { + for (var name in fields) { // eslint-disable-line no-restricted-syntax + if (hasOwn(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,10 +69,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 +84,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) { + .on('field', function (name, value) { fieldChecked++; common.actions.formOnField(fields, name, value); }) - .on('file', function(name, file) { + .on('file', function (name, file) { fieldChecked++; 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 +120,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..ee3c424 100644 --- a/test/integration/test-custom-content-type.js +++ b/test/integration/test-custom-content-type.js @@ -1,42 +1,48 @@ +'use strict'; + var common = require('../common'); 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'); -// 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': { + no_type: { value: 'my_value' }, - 'custom_type': { + custom_type: { value: 'my_value', expectedType: 'image/png', options: { contentType: 'image/png' } }, - 'default_type': { + default_type: { expectedType: FormData.DEFAULT_CONTENT_TYPE, 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' }, - 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 +57,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 +69,14 @@ 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) { - if (Object.prototype.hasOwnProperty.call(FIELDS, name)) { + for (var name in FIELDS) { // eslint-disable-line no-restricted-syntax + if (hasOwn(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 +87,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..a88b037 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'); @@ -22,47 +24,45 @@ var options = { contentType: 'image/gif' }; -var server = http.createServer(function(req, res) { - - var form = new IncomingForm({uploadDir: common.dir.tmp}); +var server = http.createServer(function (req, res) { + 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 +72,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..2e0295a 100644 --- a/test/integration/test-custom-headers-object.js +++ b/test/integration/test-custom-headers-object.js @@ -1,7 +1,7 @@ /* -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 +13,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,15 +28,16 @@ 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) + /* + * override content-length, + * much lower than actual buffer size (1000) + */ knownLength: 1 }; diff --git a/test/integration/test-custom-headers-string.js b/test/integration/test-custom-headers-string.js index a664a1e..6dd8252 100644 --- a/test/integration/test-custom-headers-string.js +++ b/test/integration/test-custom-headers-string.js @@ -1,7 +1,7 @@ /* -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 +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) { @@ -31,18 +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: - CRLF + '--' + form.getBoundary() + CRLF + - testHeader + - CRLF + CRLF, + CRLF + '--' + form.getBoundary() + CRLF + testHeader + CRLF + CRLF, - // override content-length, - // much lower than actual buffer size (1000) + /* + * override content-length, + * much lower than actual buffer size (1000) + */ knownLength: 1 }; diff --git a/test/integration/test-errors.js b/test/integration/test-errors.js index 1129226..f01eed0 100644 --- a/test/integration/test-errors.js +++ b/test/integration/test-errors.js @@ -8,20 +8,18 @@ var http = require('http'); // https://github.com/felixge/node-form-data/issues/38 (function testAppendArray() { - var form = new FormData(); 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 = [ @@ -38,7 +36,7 @@ var http = require('http'); 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 +47,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 +59,7 @@ var http = require('http'); // getLengthSync DOESN'T calculate streams length assert.ok(expectedLength > calculatedLength); -})(); +}()); (function testStreamError() { var req; @@ -75,14 +72,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 9901c7e..bbb9120 100644 --- a/test/integration/test-form-get-length-sync.js +++ b/test/integration/test-form-get-length-sync.js @@ -1,8 +1,11 @@ +'use strict'; + var common = require('../common'); var assert = common.assert; var FormData = require(common.dir.lib + '/form_data'); var fs = require('fs'); var Readable = require('stream').Readable; +var util = require('util'); (function testGetLengthSync() { var fields = [ @@ -23,17 +26,16 @@ var Readable = require('stream').Readable; 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 = [ @@ -59,13 +61,13 @@ var Readable = require('stream').Readable; 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; @@ -73,17 +75,14 @@ var Readable = require('stream').Readable; var calculatedLength = form.getLengthSync(); assert.equal(expectedLength, calculatedLength); -})(); +}()); (function testReadableStreamData() { var form = new FormData(); - var util = require('util'); - util.inherits(CustomReadable, Readable); - /** * Custion readable constructor - * @param {Object} opt options + * @param {object} opt options * @constructor */ function CustomReadable(opt) { @@ -92,16 +91,17 @@ var Readable = require('stream').Readable; this._index = 1; } - CustomReadable.prototype._read = function() { + util.inherits(CustomReadable, Readable); + + CustomReadable.prototype._read = function () { var i = this._index++; if (i > this._max) { this.push(null); } else { - this.push('' + i); + this.push(String(i)); } }; form.append('my_txt', new CustomReadable()); - assert.throws(function() { form.getLengthSync(); }, /Cannot calculate proper length in synchronous way/); - -})(); + assert['throws'](function () { form.getLengthSync(); }, /Cannot calculate proper length in synchronous way/); +}()); diff --git a/test/integration/test-form-get-length.js b/test/integration/test-form-get-length.js index 6dabca7..b5da576 100644 --- a/test/integration/test-form-get-length.js +++ b/test/integration/test-form-get-length.js @@ -4,6 +4,7 @@ var FormData = require(common.dir.lib + '/form_data'); var fake = require('fake').create(); var fs = require('fs'); var Readable = require('stream').Readable; +var util = require('util'); (function testEmptyForm() { var form = new FormData(); @@ -14,7 +15,7 @@ var Readable = require('stream').Readable; // Make sure our response is async assert.strictEqual(calls.length, 0); -})(); +}()); (function testUtf8String() { var FIELD = 'my_field'; @@ -24,14 +25,11 @@ var Readable = require('stream').Readable; 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'; @@ -41,15 +39,11 @@ var Readable = require('stream').Readable; 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 = [ @@ -74,7 +68,7 @@ var Readable = require('stream').Readable; 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); @@ -89,18 +83,15 @@ var Readable = require('stream').Readable; var callback = fake.callback('testStringFileBufferFile-getLength'); fake.expectAnytime(callback, [null, expectedLength]); form.getLength(callback); -})(); +}()); (function testReadableStreamData() { var form = new FormData(); // var expectedLength = 0; - var util = require('util'); - util.inherits(CustomReadable, Readable); - /** * Custion readable constructor - * @param {Object} opt options + * @param {object} opt options * @constructor */ function CustomReadable(opt) { @@ -109,12 +100,14 @@ var Readable = require('stream').Readable; this._index = 1; } - CustomReadable.prototype._read = function() { + util.inherits(CustomReadable, Readable); + + CustomReadable.prototype._read = function () { var i = this._index++; if (i > this._max) { this.push(null); } else { - this.push('' + i); + this.push(String(i)); } }; form.append('my_txt', new CustomReadable()); @@ -122,8 +115,7 @@ var Readable = require('stream').Readable; // expectedLength += form._overheadLength + form._lastBoundary().length; // there is no way to determine the length of this readable stream. - var callback = fake.callback(arguments.callee.name + '-getLength'); + var callback = fake.callback(arguments.callee.name + '-getLength'); // eslint-disable-line no-restricted-properties fake.expectAnytime(callback, ['Unknown stream', undefined]); - form.getLength(function(err, len) { callback(err,len); }); - -})(); + form.getLength(function (err, len) { callback(err, len); }); +}()); 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..dfbf12f 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..8b06ead 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'); @@ -18,44 +20,41 @@ var options = { }; var FIELDS = { - 'my_field': { + my_field: { value: 'my_value' }, - 'my_buffer': { + my_buffer: { type: FormData.DEFAULT_CONTENT_TYPE, value: common.defaultTypeValue }, - 'remote_file': { + remote_file: { value: 'TBD', 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); }); - }).end(); // count total 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..ae4d510 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; @@ -8,7 +10,6 @@ var server; * Test submission of proper line ending */ function submitForm() { - var form = new FormData(); form.append('field', 'value'); @@ -17,18 +18,17 @@ 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..d4a5654 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'); @@ -6,38 +8,39 @@ var request = require('request'); var fs = require('fs'); var FormData = require(common.dir.lib + '/form_data'); var IncomingForm = require('formidable').IncomingForm; +var hasOwn = require('hasown'); 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': { + my_field: { value: 'my_value' }, - 'my_buffer': { + my_buffer: { type: FormData.DEFAULT_CONTENT_TYPE, 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 form = new IncomingForm({uploadDir: common.dir.tmp}); +var server = http.createServer(function (req, res) { + 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,14 @@ 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) { - if (Object.prototype.hasOwnProperty.call(FIELDS, name)) { + for (var name in FIELDS) { // eslint-disable-line no-restricted-syntax + if (hasOwn(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); @@ -69,8 +71,7 @@ server.listen(common.port, function() { form.pipe(req); - req.on('response', function(res) { - + req.on('response', function (res) { // unstuck new streams res.resume(); @@ -78,6 +79,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..39123ca 100644 --- a/test/integration/test-ranged-filestream.js +++ b/test/integration/test-ranged-filestream.js @@ -1,32 +1,35 @@ +'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 hasOwn = require('hasown'); -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': { + }, b_file: { file: 'veggies.txt', start: 6 - }, 'c_file': { + }, c_file: { file: 'veggies.txt', end: 16 - }, 'd_file': { + }, d_file: { file: 'veggies.txt', start: 0, end: 16 - }, 'e_file': { + }, e_file: { file: 'veggies.txt', start: 0, end: 0 @@ -36,52 +39,51 @@ var testSubjects = { /** * Accumulates read data size * - * @param {string} data - chunk of read data + * @param {string} data - chunk of read data */ function readSizeAccumulator(data) { - this.readSize += data.length; + this.readSize += data.length; // eslint-disable-line no-invalid-this } -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) { - if (Object.prototype.hasOwnProperty.call(testSubjects, name)) { - options = {encoding: 'utf8'}; + for (name in testSubjects) { // eslint-disable-line no-restricted-syntax + if (hasOwn(testSubjects, name)) { + options = { encoding: 'utf8' }; if (testSubjects[name].start) { options.start = testSubjects[name].start; } if (testSubjects[name].end) { options.end = testSubjects[name].end; } @@ -94,7 +96,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 +104,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..88200d3 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,52 +15,50 @@ 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) { - err.message = 'form-data: ' + err.message; + self._form.on('error', function (err) { + err.message = 'form-data: ' + err.message; // eslint-disable-line no-param-reassign self.emit('error', err); self.abort(); }); return self._form; }; -var server = http.createServer(function(req, res) { - - var form = new IncomingForm({uploadDir: common.dir.tmp}); +var server = http.createServer(function (req, res) { + 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 +71,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..b54cd01 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; @@ -15,17 +17,17 @@ var expectedLength; var dataSize = 1000000; -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,9 @@ 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 progress = 0; + var form = new FormData(); var bufferData = []; for (var z = 0; z < dataSize; z++) { @@ -50,7 +52,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) { + var R = form.submit('http://localhost:' + common.port + '/', function (err, res) { if (err) { throw err; } @@ -67,17 +69,16 @@ server.listen(common.port, function() { }); // augment into request - oWrite = R.write; - R.write = function(chunk) { - return oWrite.call(this, chunk, function() { + var oWrite = R.write; + 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..7b2fa45 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,16 @@ var FormData = require(common.dir.lib + '/form_data'); assert.equal(formA.getBoundary(), userBoundary); assert.notEqual(formA.getBoundary(), formB.getBoundary()); -})(); +}()); + +(function testSetBoundaryWithNonString() { + var form = new FormData(); + + var invalidValues = [123, null, undefined, { value: 123 }, ['---something']]; + + invalidValues.forEach(function (value) { + assert.throws(function () { + form.setBoundary(value); + }, TypeError); + }); +}()); diff --git a/test/integration/test-set-nonstring.js b/test/integration/test-set-nonstring.js new file mode 100644 index 0000000..c9f0f3b --- /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' + ]); +}()); diff --git a/test/integration/test-submit-custom-header.js b/test/integration/test-submit-custom-header.js index 6a6aff5..aa6d79e 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': { + my_field: { value: 'my_value' }, - 'my_buffer': { + my_buffer: { type: FormData.DEFAULT_CONTENT_TYPE, 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,8 +49,7 @@ var server = http.createServer(function(req, res) { }); }); -server.listen(common.port, function() { - +server.listen(common.port, function () { var form = new FormData(); common.actions.populateFields(form, FIELDS); @@ -59,7 +61,7 @@ server.listen(common.port, function() { headers: { 'x-test-header': 'test-header-value' } - }, function(error, result) { + }, function (error, result) { if (error) { throw error; } @@ -73,6 +75,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..eaf508d 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,23 +9,25 @@ 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': { + my_field: { value: 'my_value' }, - 'my_buffer': { + my_buffer: { type: FormData.DEFAULT_CONTENT_TYPE, 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); } } }; @@ -31,12 +35,11 @@ var FIELDS = { 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(); common.actions.populateFields(form, FIELDS); @@ -45,8 +48,7 @@ server.listen(common.port, function() { form.submit({ port: common.port, path: '/' - }, function(err, res) { - + }, function (err, res) { if (err) { throw err; } @@ -59,6 +61,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..e390416 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'); @@ -8,7 +11,6 @@ var server; * Test submission to HTTPS endpoint */ function submitForm() { - var form = new FormData(); form.append('field', 'value'); @@ -19,10 +21,9 @@ function submitForm() { port: common.httpsPort, pathname: '/', // for self-signed certs on localhost - secureOptions: require('constants').SSL_OP_NO_TLSv1_2, + secureOptions: constants.SSL_OP_NO_TLSv1_2, ca: common.httpsServerCert - }, function(err, res) { - + }, function (err, res) { if (err) { throw err; } @@ -41,13 +42,12 @@ function submitForm() { server = https.createServer({ key: common.httpsServerKey, cert: common.httpsServerCert -}, function(req, res) { - +}, 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..df1199a 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,41 +8,37 @@ 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}); + 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() { - var i; - - for (i = 0; i < times; i++) { +server.listen(common.port, function () { + for (var i = 0; i < times; i++) { var form = new FormData(); form.append('my_field', 'my_value'); form.submit('http://localhost:' + common.port + '/'); } - }); -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..b7a21b8 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,30 @@ 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}); + var form = new IncomingForm({ uploadDir: common.dir.tmp }); form.parse(req); @@ -45,14 +48,12 @@ server = http.createServer(function(req, res) { .on('end', common.actions.formOnEnd.bind(null, res)); }); -server.listen(common.port, function() { - var i; - - for (i = 0; i < times; i++) { +server.listen(common.port, function () { + for (var i = 0; i < times; i++) { submitForm(); } }); -process.on('exit', function() { +process.on('exit', function () { assert.strictEqual(times, 0); }); diff --git a/test/integration/test-submit-readable-stream.js b/test/integration/test-submit-readable-stream.js index 41896a4..3c3cd65 100644 --- a/test/integration/test-submit-readable-stream.js +++ b/test/integration/test-submit-readable-stream.js @@ -1,44 +1,45 @@ +'use strict'; + var common = require('../common'); var assert = common.assert; var http = require('http'); var FormData = require(common.dir.lib + '/form_data'); var Readable = require('stream').Readable; +var util = require('util'); -var server = http.createServer(function(req, res) { +var server = http.createServer(function (req, res) { assert.strictEqual(req.headers['Content-Length'], undefined); res.writeHead(200); res.end('done'); }); -server.listen(common.port, function() { +server.listen(common.port, function () { var form = new FormData(); - var util = require('util'); - util.inherits(CustomReadable, Readable); - /** * Custion readable constructor - * @param {Object} opt options + * @param {object} opt options * @constructor - */ + */ function CustomReadable(opt) { Readable.call(this, opt); this._max = 2; this._index = 1; } + util.inherits(CustomReadable, Readable); - CustomReadable.prototype._read = function() { + CustomReadable.prototype._read = function () { var i = this._index++; // console.error('send back read data'); if (i > this._max) { this.push(null); } else { - this.push('' + i); + this.push(String(i)); } }; form.append('readable', new CustomReadable()); - form.submit('http://localhost:' + common.port + '/', function(err, res) { + form.submit('http://localhost:' + common.port + '/', function (err, res) { if (err) { throw err; } diff --git a/test/integration/test-submit-url-parsing.js b/test/integration/test-submit-url-parsing.js index becc1d7..e9e1b31 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,19 @@ 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..f0780e4 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,23 +9,25 @@ 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': { + my_field: { value: 'my_value' }, - 'my_buffer': { + my_buffer: { type: FormData.DEFAULT_CONTENT_TYPE, 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); } } }; @@ -31,13 +35,11 @@ var FIELDS = { 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(); common.actions.populateFields(form, FIELDS); @@ -45,6 +47,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..8c97d9c 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]'); +assert(String(new FormData()) === '[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..c1091d4 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,16 +12,19 @@ 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, + '--root', + basePath, file ]); @@ -32,7 +38,7 @@ if (process.env.running_under_istanbul) { * @param {string} chunk - partial output */ function onOutput(chunk) { - if (this._verbose > 1) { + if (this._verbose > 1) { // eslint-disable-line no-invalid-this process.stderr.write(chunk); } else { output += chunk; @@ -42,7 +48,7 @@ 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) { + node.on('exit', function (code) { this._index++; this._printTestResult(file, code, output); this._executeNext(); @@ -52,11 +58,11 @@ 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) { - p = path.resolve(process.cwd(), p); + pathList.forEach(function (p) { + p = path.resolve(process.cwd(), p); // eslint-disable-line no-param-reassign if (!farPaths.isDirectory(p)) { expanded[p] = true; @@ -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..e03885b 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,11 +12,9 @@ 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);