UNPKG

3.35 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, [
26 10,
27 10,
28 10,
29 20,
30 50,
31]);
32const calls = {
33 partBegin: 0,
34 headerField: 0,
35 headerValue: 0,
36 headerEnd: 0,
37 headersEnd: 0,
38 partData: 0,
39 partEnd: 0,
40 end: 0,
41};
42
43const moduleName = process.argv[2];
44switch (moduleName) {
45 case 'busboy': {
46 const busboy = require('busboy');
47
48 const parser = busboy({
49 limits: {
50 fieldSizeLimit: Infinity,
51 },
52 headers: {
53 'content-type': `multipart/form-data; boundary=${boundary}`,
54 },
55 });
56 parser.on('file', (name, stream, info) => {
57 ++calls.partBegin;
58 stream.on('data', (chunk) => {
59 ++calls.partData;
60 }).on('end', () => {
61 ++calls.partEnd;
62 });
63 }).on('close', () => {
64 ++calls.end;
65 console.timeEnd(moduleName);
66 });
67
68 console.time(moduleName);
69 for (const buf of buffers)
70 parser.write(buf);
71 break;
72 }
73
74 case 'formidable': {
75 const { MultipartParser } = require('formidable');
76
77 const parser = new MultipartParser();
78 parser.initWithBoundary(boundary);
79 parser.on('data', ({ name }) => {
80 ++calls[name];
81 if (name === 'end')
82 console.timeEnd(moduleName);
83 });
84
85 console.time(moduleName);
86 for (const buf of buffers)
87 parser.write(buf);
88
89 break;
90 }
91
92 case 'multiparty': {
93 const { Readable } = require('stream');
94
95 const { Form } = require('multiparty');
96
97 const form = new Form({
98 maxFieldsSize: Infinity,
99 maxFields: Infinity,
100 maxFilesSize: Infinity,
101 autoFields: false,
102 autoFiles: false,
103 });
104
105 const req = new Readable({ read: () => {} });
106 req.headers = {
107 'content-type': `multipart/form-data; boundary=${boundary}`,
108 };
109
110 function hijack(name, fn) {
111 const oldFn = form[name];
112 form[name] = function() {
113 fn();
114 return oldFn.apply(this, arguments);
115 };
116 }
117
118 hijack('onParseHeaderField', () => {
119 ++calls.headerField;
120 });
121 hijack('onParseHeaderValue', () => {
122 ++calls.headerValue;
123 });
124 hijack('onParsePartBegin', () => {
125 ++calls.partBegin;
126 });
127 hijack('onParsePartData', () => {
128 ++calls.partData;
129 });
130 hijack('onParsePartEnd', () => {
131 ++calls.partEnd;
132 });
133
134 form.on('close', () => {
135 ++calls.end;
136 console.timeEnd(moduleName);
137 }).on('part', (p) => p.resume());
138
139 console.time(moduleName);
140 form.parse(req);
141 for (const buf of buffers)
142 req.push(buf);
143 req.push(null);
144
145 break;
146 }
147
148 default:
149 if (moduleName === undefined)
150 console.error('Missing parser module name');
151 else
152 console.error(`Invalid parser module name: ${moduleName}`);
153 process.exit(1);
154}