UNPKG

3.34 kBJavaScriptView Raw
1'use strict';
2
3function createMultipartBuffers(boundary, sizes) {
4 const bufs = [];
5 for (let i = 0; i < sizes.length; ++i) {
6 const mb = sizes[i] * 1024 * 1024;
7 bufs.push(Buffer.from([
8 `--${boundary}`,
9 `content-disposition: form-data; name="file${i + 1}"; `
10 + `filename="random${i + 1}.bin"`,
11 'content-type: application/octet-stream',
12 '',
13 '0'.repeat(mb),
14 '',
15 ].join('\r\n')));
16 }
17 bufs.push(Buffer.from([
18 `--${boundary}--`,
19 '',
20 ].join('\r\n')));
21 return bufs;
22}
23
24const boundary = '-----------------------------168072824752491622650073';
25const buffers = createMultipartBuffers(boundary, (new Array(100)).fill(1));
26const calls = {
27 partBegin: 0,
28 headerField: 0,
29 headerValue: 0,
30 headerEnd: 0,
31 headersEnd: 0,
32 partData: 0,
33 partEnd: 0,
34 end: 0,
35};
36
37const moduleName = process.argv[2];
38switch (moduleName) {
39 case 'busboy': {
40 const busboy = require('busboy');
41
42 const parser = busboy({
43 limits: {
44 fieldSizeLimit: Infinity,
45 },
46 headers: {
47 'content-type': `multipart/form-data; boundary=${boundary}`,
48 },
49 });
50 parser.on('file', (name, stream, info) => {
51 ++calls.partBegin;
52 stream.on('data', (chunk) => {
53 ++calls.partData;
54 }).on('end', () => {
55 ++calls.partEnd;
56 });
57 }).on('close', () => {
58 ++calls.end;
59 console.timeEnd(moduleName);
60 });
61
62 console.time(moduleName);
63 for (const buf of buffers)
64 parser.write(buf);
65 break;
66 }
67
68 case 'formidable': {
69 const { MultipartParser } = require('formidable');
70
71 const parser = new MultipartParser();
72 parser.initWithBoundary(boundary);
73 parser.on('data', ({ name }) => {
74 ++calls[name];
75 if (name === 'end')
76 console.timeEnd(moduleName);
77 });
78
79 console.time(moduleName);
80 for (const buf of buffers)
81 parser.write(buf);
82
83 break;
84 }
85
86 case 'multiparty': {
87 const { Readable } = require('stream');
88
89 const { Form } = require('multiparty');
90
91 const form = new Form({
92 maxFieldsSize: Infinity,
93 maxFields: Infinity,
94 maxFilesSize: Infinity,
95 autoFields: false,
96 autoFiles: false,
97 });
98
99 const req = new Readable({ read: () => {} });
100 req.headers = {
101 'content-type': `multipart/form-data; boundary=${boundary}`,
102 };
103
104 function hijack(name, fn) {
105 const oldFn = form[name];
106 form[name] = function() {
107 fn();
108 return oldFn.apply(this, arguments);
109 };
110 }
111
112 hijack('onParseHeaderField', () => {
113 ++calls.headerField;
114 });
115 hijack('onParseHeaderValue', () => {
116 ++calls.headerValue;
117 });
118 hijack('onParsePartBegin', () => {
119 ++calls.partBegin;
120 });
121 hijack('onParsePartData', () => {
122 ++calls.partData;
123 });
124 hijack('onParsePartEnd', () => {
125 ++calls.partEnd;
126 });
127
128 form.on('close', () => {
129 ++calls.end;
130 console.timeEnd(moduleName);
131 }).on('part', (p) => p.resume());
132
133 console.time(moduleName);
134 form.parse(req);
135 for (const buf of buffers)
136 req.push(buf);
137 req.push(null);
138
139 break;
140 }
141
142 default:
143 if (moduleName === undefined)
144 console.error('Missing parser module name');
145 else
146 console.error(`Invalid parser module name: ${moduleName}`);
147 process.exit(1);
148}