UNPKG

16.4 kBJavaScriptView Raw
1var Busboy = require('..');
2
3var path = require('path'),
4 inspect = require('util').inspect,
5 assert = require('assert');
6
7var EMPTY_FN = function() {};
8
9var t = 0,
10 group = path.basename(__filename, '.js') + '/';
11var tests = [
12 { source: [
13 ['-----------------------------paZqsnEHRufoShdX6fh0lUhXBP4k',
14 'Content-Disposition: form-data; name="file_name_0"',
15 '',
16 'super alpha file',
17 '-----------------------------paZqsnEHRufoShdX6fh0lUhXBP4k',
18 'Content-Disposition: form-data; name="file_name_1"',
19 '',
20 'super beta file',
21 '-----------------------------paZqsnEHRufoShdX6fh0lUhXBP4k',
22 'Content-Disposition: form-data; name="upload_file_0"; filename="1k_a.dat"',
23 'Content-Type: application/octet-stream',
24 '',
25 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA',
26 '-----------------------------paZqsnEHRufoShdX6fh0lUhXBP4k',
27 'Content-Disposition: form-data; name="upload_file_1"; filename="1k_b.dat"',
28 'Content-Type: application/octet-stream',
29 '',
30 'BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB',
31 '-----------------------------paZqsnEHRufoShdX6fh0lUhXBP4k--'
32 ].join('\r\n')
33 ],
34 boundary: '---------------------------paZqsnEHRufoShdX6fh0lUhXBP4k',
35 expected: [
36 ['field', 'file_name_0', 'super alpha file', false, false, '7bit', 'text/plain'],
37 ['field', 'file_name_1', 'super beta file', false, false, '7bit', 'text/plain'],
38 ['file', 'upload_file_0', 1023, 0, '1k_a.dat', '7bit', 'application/octet-stream'],
39 ['file', 'upload_file_1', 1023, 0, '1k_b.dat', '7bit', 'application/octet-stream']
40 ],
41 what: 'Fields and files'
42 },
43 { source: [
44 ['------WebKitFormBoundaryTB2MiQ36fnSJlrhY',
45 'Content-Disposition: form-data; name="cont"',
46 '',
47 'some random content',
48 '------WebKitFormBoundaryTB2MiQ36fnSJlrhY',
49 'Content-Disposition: form-data; name="pass"',
50 '',
51 'some random pass',
52 '------WebKitFormBoundaryTB2MiQ36fnSJlrhY',
53 'Content-Disposition: form-data; name="bit"',
54 '',
55 '2',
56 '------WebKitFormBoundaryTB2MiQ36fnSJlrhY--'
57 ].join('\r\n')
58 ],
59 boundary: '----WebKitFormBoundaryTB2MiQ36fnSJlrhY',
60 expected: [
61 ['field', 'cont', 'some random content', false, false, '7bit', 'text/plain'],
62 ['field', 'pass', 'some random pass', false, false, '7bit', 'text/plain'],
63 ['field', 'bit', '2', false, false, '7bit', 'text/plain']
64 ],
65 what: 'Fields only'
66 },
67 { source: [
68 ''
69 ],
70 boundary: '----WebKitFormBoundaryTB2MiQ36fnSJlrhY',
71 expected: [],
72 what: 'No fields and no files'
73 },
74 { source: [
75 ['-----------------------------paZqsnEHRufoShdX6fh0lUhXBP4k',
76 'Content-Disposition: form-data; name="file_name_0"',
77 '',
78 'super alpha file',
79 '-----------------------------paZqsnEHRufoShdX6fh0lUhXBP4k',
80 'Content-Disposition: form-data; name="upload_file_0"; filename="1k_a.dat"',
81 'Content-Type: application/octet-stream',
82 '',
83 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
84 '-----------------------------paZqsnEHRufoShdX6fh0lUhXBP4k--'
85 ].join('\r\n')
86 ],
87 boundary: '---------------------------paZqsnEHRufoShdX6fh0lUhXBP4k',
88 limits: {
89 fileSize: 13,
90 fieldSize: 5
91 },
92 expected: [
93 ['field', 'file_name_0', 'super', false, true, '7bit', 'text/plain'],
94 ['file', 'upload_file_0', 13, 2, '1k_a.dat', '7bit', 'application/octet-stream']
95 ],
96 what: 'Fields and files (limits)'
97 },
98 { source: [
99 ['-----------------------------paZqsnEHRufoShdX6fh0lUhXBP4k',
100 'Content-Disposition: form-data; name="file_name_0"',
101 '',
102 'super alpha file',
103 '-----------------------------paZqsnEHRufoShdX6fh0lUhXBP4k',
104 'Content-Disposition: form-data; name="upload_file_0"; filename="1k_a.dat"',
105 'Content-Type: application/octet-stream',
106 '',
107 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
108 '-----------------------------paZqsnEHRufoShdX6fh0lUhXBP4k--'
109 ].join('\r\n')
110 ],
111 boundary: '---------------------------paZqsnEHRufoShdX6fh0lUhXBP4k',
112 limits: {
113 files: 0
114 },
115 expected: [
116 ['field', 'file_name_0', 'super alpha file', false, false, '7bit', 'text/plain']
117 ],
118 what: 'Fields and files (limits: 0 files)'
119 },
120 { source: [
121 ['-----------------------------paZqsnEHRufoShdX6fh0lUhXBP4k',
122 'Content-Disposition: form-data; name="file_name_0"',
123 '',
124 'super alpha file',
125 '-----------------------------paZqsnEHRufoShdX6fh0lUhXBP4k',
126 'Content-Disposition: form-data; name="file_name_1"',
127 '',
128 'super beta file',
129 '-----------------------------paZqsnEHRufoShdX6fh0lUhXBP4k',
130 'Content-Disposition: form-data; name="upload_file_0"; filename="1k_a.dat"',
131 'Content-Type: application/octet-stream',
132 '',
133 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA',
134 '-----------------------------paZqsnEHRufoShdX6fh0lUhXBP4k',
135 'Content-Disposition: form-data; name="upload_file_1"; filename="1k_b.dat"',
136 'Content-Type: application/octet-stream',
137 '',
138 'BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB',
139 '-----------------------------paZqsnEHRufoShdX6fh0lUhXBP4k--'
140 ].join('\r\n')
141 ],
142 boundary: '---------------------------paZqsnEHRufoShdX6fh0lUhXBP4k',
143 expected: [
144 ['field', 'file_name_0', 'super alpha file', false, false, '7bit', 'text/plain'],
145 ['field', 'file_name_1', 'super beta file', false, false, '7bit', 'text/plain'],
146 ],
147 events: ['field'],
148 what: 'Fields and (ignored) files'
149 },
150 { source: [
151 ['-----------------------------paZqsnEHRufoShdX6fh0lUhXBP4k',
152 'Content-Disposition: form-data; name="upload_file_0"; filename="/tmp/1k_a.dat"',
153 'Content-Type: application/octet-stream',
154 '',
155 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
156 '-----------------------------paZqsnEHRufoShdX6fh0lUhXBP4k',
157 'Content-Disposition: form-data; name="upload_file_1"; filename="C:\\files\\1k_b.dat"',
158 'Content-Type: application/octet-stream',
159 '',
160 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
161 '-----------------------------paZqsnEHRufoShdX6fh0lUhXBP4k',
162 'Content-Disposition: form-data; name="upload_file_2"; filename="relative/1k_c.dat"',
163 'Content-Type: application/octet-stream',
164 '',
165 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
166 '-----------------------------paZqsnEHRufoShdX6fh0lUhXBP4k--'
167 ].join('\r\n')
168 ],
169 boundary: '---------------------------paZqsnEHRufoShdX6fh0lUhXBP4k',
170 expected: [
171 ['file', 'upload_file_0', 26, 0, '1k_a.dat', '7bit', 'application/octet-stream'],
172 ['file', 'upload_file_1', 26, 0, '1k_b.dat', '7bit', 'application/octet-stream'],
173 ['file', 'upload_file_2', 26, 0, '1k_c.dat', '7bit', 'application/octet-stream']
174 ],
175 what: 'Files with filenames containing paths'
176 },
177 { source: [
178 ['-----------------------------paZqsnEHRufoShdX6fh0lUhXBP4k',
179 'Content-Disposition: form-data; name="upload_file_0"; filename="/absolute/1k_a.dat"',
180 'Content-Type: application/octet-stream',
181 '',
182 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
183 '-----------------------------paZqsnEHRufoShdX6fh0lUhXBP4k',
184 'Content-Disposition: form-data; name="upload_file_1"; filename="C:\\absolute\\1k_b.dat"',
185 'Content-Type: application/octet-stream',
186 '',
187 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
188 '-----------------------------paZqsnEHRufoShdX6fh0lUhXBP4k',
189 'Content-Disposition: form-data; name="upload_file_2"; filename="relative/1k_c.dat"',
190 'Content-Type: application/octet-stream',
191 '',
192 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
193 '-----------------------------paZqsnEHRufoShdX6fh0lUhXBP4k--'
194 ].join('\r\n')
195 ],
196 boundary: '---------------------------paZqsnEHRufoShdX6fh0lUhXBP4k',
197 preservePath: true,
198 expected: [
199 ['file', 'upload_file_0', 26, 0, '/absolute/1k_a.dat', '7bit', 'application/octet-stream'],
200 ['file', 'upload_file_1', 26, 0, 'C:\\absolute\\1k_b.dat', '7bit', 'application/octet-stream'],
201 ['file', 'upload_file_2', 26, 0, 'relative/1k_c.dat', '7bit', 'application/octet-stream']
202 ],
203 what: 'Paths to be preserved through the preservePath option'
204 },
205 { source: [
206 ['------WebKitFormBoundaryTB2MiQ36fnSJlrhY',
207 'Content-Disposition: form-data; name="cont"',
208 'Content-Type: ',
209 '',
210 'some random content',
211 '------WebKitFormBoundaryTB2MiQ36fnSJlrhY',
212 'Content-Disposition: ',
213 '',
214 'some random pass',
215 '------WebKitFormBoundaryTB2MiQ36fnSJlrhY--'
216 ].join('\r\n')
217 ],
218 boundary: '----WebKitFormBoundaryTB2MiQ36fnSJlrhY',
219 expected: [
220 ['field', 'cont', 'some random content', false, false, '7bit', 'text/plain']
221 ],
222 what: 'Empty content-type and empty content-disposition'
223 },
224 { source: [
225 ['--asdasdasdasd\r\n',
226 'Content-Type: text/plain\r\n',
227 'Content-Disposition: form-data; name="foo"\r\n',
228 '\r\n',
229 'asd\r\n',
230 '--asdasdasdasd--'
231 ].join(':)')
232 ],
233 boundary: 'asdasdasdasd',
234 expected: [],
235 shouldError: 'Unexpected end of multipart data',
236 what: 'Stopped mid-header'
237 },
238 { source: [
239 ['------WebKitFormBoundaryTB2MiQ36fnSJlrhY',
240 'Content-Disposition: form-data; name="cont"',
241 'Content-Type: application/json',
242 '',
243 '{}',
244 '------WebKitFormBoundaryTB2MiQ36fnSJlrhY--',
245 ].join('\r\n')
246 ],
247 boundary: '----WebKitFormBoundaryTB2MiQ36fnSJlrhY',
248 expected: [
249 ['field', 'cont', '{}', false, false, '7bit', 'application/json']
250 ],
251 what: 'content-type for fields'
252 },
253 { source: [
254 '------WebKitFormBoundaryTB2MiQ36fnSJlrhY--\r\n'
255 ],
256 boundary: '----WebKitFormBoundaryTB2MiQ36fnSJlrhY',
257 expected: [],
258 what: 'empty form'
259 }
260];
261
262function next() {
263 if (t === tests.length)
264 return;
265
266 var v = tests[t];
267
268 var busboy = new Busboy({
269 limits: v.limits,
270 preservePath: v.preservePath,
271 headers: {
272 'content-type': 'multipart/form-data; boundary=' + v.boundary
273 }
274 }),
275 finishes = 0,
276 results = [];
277
278 if (v.events === undefined || v.events.indexOf('field') > -1) {
279 busboy.on('field', function(key, val, keyTrunc, valTrunc, encoding, contype) {
280 results.push(['field', key, val, keyTrunc, valTrunc, encoding, contype]);
281 });
282 }
283 if (v.events === undefined || v.events.indexOf('file') > -1) {
284 busboy.on('file', function(fieldname, stream, filename, encoding, mimeType) {
285 var nb = 0,
286 info = ['file',
287 fieldname,
288 nb,
289 0,
290 filename,
291 encoding,
292 mimeType];
293 results.push(info);
294 stream.on('data', function(d) {
295 nb += d.length;
296 }).on('limit', function() {
297 ++info[3];
298 }).on('end', function() {
299 info[2] = nb;
300 if (stream.truncated)
301 ++info[3];
302 });
303 });
304 }
305 busboy.on('finish', function() {
306 assert(finishes++ === 0, makeMsg(v.what, 'finish emitted multiple times'));
307 assert.deepEqual(results.length,
308 v.expected.length,
309 makeMsg(v.what, 'Parsed result count mismatch. Saw '
310 + results.length
311 + '. Expected: ' + v.expected.length));
312
313 results.forEach(function(result, i) {
314 assert.deepEqual(result,
315 v.expected[i],
316 makeMsg(v.what,
317 'Result mismatch:\nParsed: ' + inspect(result)
318 + '\nExpected: ' + inspect(v.expected[i]))
319 );
320 });
321 ++t;
322 next();
323 }).on('error', function(err) {
324 if (!v.shouldError || v.shouldError !== err.message)
325 assert(false, makeMsg(v.what, 'Unexpected error: ' + err));
326 });
327
328 v.source.forEach(function(s) {
329 busboy.write(Buffer.from(s, 'utf8'), EMPTY_FN);
330 });
331 busboy.end();
332}
333next();
334
335function makeMsg(what, msg) {
336 return '[' + group + what + ']: ' + msg;
337}
338
339process.on('exit', function() {
340 assert(t === tests.length,
341 makeMsg('_exit',
342 'Only finished ' + t + '/' + tests.length + ' tests'));
343});