150 lines
3.1 KiB
JavaScript
150 lines
3.1 KiB
JavaScript
'use strict';
|
|
|
|
function createMultipartBuffers(boundary, sizes) {
|
|
const bufs = [];
|
|
for (let i = 0; i < sizes.length; ++i) {
|
|
const mb = sizes[i] * 1024 * 1024;
|
|
bufs.push(Buffer.from([
|
|
`--${boundary}`,
|
|
`content-disposition: form-data; name="field${i + 1}"`,
|
|
'',
|
|
'0'.repeat(mb),
|
|
'',
|
|
].join('\r\n')));
|
|
}
|
|
bufs.push(Buffer.from([
|
|
`--${boundary}--`,
|
|
'',
|
|
].join('\r\n')));
|
|
return bufs;
|
|
}
|
|
|
|
const boundary = '-----------------------------168072824752491622650073';
|
|
const buffers = createMultipartBuffers(boundary, [
|
|
10,
|
|
10,
|
|
10,
|
|
20,
|
|
50,
|
|
]);
|
|
const calls = {
|
|
partBegin: 0,
|
|
headerField: 0,
|
|
headerValue: 0,
|
|
headerEnd: 0,
|
|
headersEnd: 0,
|
|
partData: 0,
|
|
partEnd: 0,
|
|
end: 0,
|
|
};
|
|
|
|
const moduleName = process.argv[2];
|
|
switch (moduleName) {
|
|
case 'busboy': {
|
|
const busboy = require('busboy');
|
|
|
|
const parser = busboy({
|
|
limits: {
|
|
fieldSizeLimit: Infinity,
|
|
},
|
|
headers: {
|
|
'content-type': `multipart/form-data; boundary=${boundary}`,
|
|
},
|
|
});
|
|
parser.on('field', (name, val, info) => {
|
|
++calls.partBegin;
|
|
++calls.partData;
|
|
++calls.partEnd;
|
|
}).on('close', () => {
|
|
++calls.end;
|
|
console.timeEnd(moduleName);
|
|
});
|
|
|
|
console.time(moduleName);
|
|
for (const buf of buffers)
|
|
parser.write(buf);
|
|
break;
|
|
}
|
|
|
|
case 'formidable': {
|
|
const { MultipartParser } = require('formidable');
|
|
|
|
const parser = new MultipartParser();
|
|
parser.initWithBoundary(boundary);
|
|
parser.on('data', ({ name }) => {
|
|
++calls[name];
|
|
if (name === 'end')
|
|
console.timeEnd(moduleName);
|
|
});
|
|
|
|
console.time(moduleName);
|
|
for (const buf of buffers)
|
|
parser.write(buf);
|
|
|
|
break;
|
|
}
|
|
|
|
case 'multiparty': {
|
|
const { Readable } = require('stream');
|
|
|
|
const { Form } = require('multiparty');
|
|
|
|
const form = new Form({
|
|
maxFieldsSize: Infinity,
|
|
maxFields: Infinity,
|
|
maxFilesSize: Infinity,
|
|
autoFields: false,
|
|
autoFiles: false,
|
|
});
|
|
|
|
const req = new Readable({ read: () => {} });
|
|
req.headers = {
|
|
'content-type': `multipart/form-data; boundary=${boundary}`,
|
|
};
|
|
|
|
function hijack(name, fn) {
|
|
const oldFn = form[name];
|
|
form[name] = function() {
|
|
fn();
|
|
return oldFn.apply(this, arguments);
|
|
};
|
|
}
|
|
|
|
hijack('onParseHeaderField', () => {
|
|
++calls.headerField;
|
|
});
|
|
hijack('onParseHeaderValue', () => {
|
|
++calls.headerValue;
|
|
});
|
|
hijack('onParsePartBegin', () => {
|
|
++calls.partBegin;
|
|
});
|
|
hijack('onParsePartData', () => {
|
|
++calls.partData;
|
|
});
|
|
hijack('onParsePartEnd', () => {
|
|
++calls.partEnd;
|
|
});
|
|
|
|
form.on('close', () => {
|
|
++calls.end;
|
|
console.timeEnd(moduleName);
|
|
}).on('part', (p) => p.resume());
|
|
|
|
console.time(moduleName);
|
|
form.parse(req);
|
|
for (const buf of buffers)
|
|
req.push(buf);
|
|
req.push(null);
|
|
|
|
break;
|
|
}
|
|
|
|
default:
|
|
if (moduleName === undefined)
|
|
console.error('Missing parser module name');
|
|
else
|
|
console.error(`Invalid parser module name: ${moduleName}`);
|
|
process.exit(1);
|
|
}
|