UNPKG

16.2 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];
254
255function next() {
256 if (t === tests.length)
257 return;
258
259 var v = tests[t];
260
261 var busboy = new Busboy({
262 limits: v.limits,
263 preservePath: v.preservePath,
264 headers: {
265 'content-type': 'multipart/form-data; boundary=' + v.boundary
266 }
267 }),
268 finishes = 0,
269 results = [];
270
271 if (v.events === undefined || v.events.indexOf('field') > -1) {
272 busboy.on('field', function(key, val, keyTrunc, valTrunc, encoding, contype) {
273 results.push(['field', key, val, keyTrunc, valTrunc, encoding, contype]);
274 });
275 }
276 if (v.events === undefined || v.events.indexOf('file') > -1) {
277 busboy.on('file', function(fieldname, stream, filename, encoding, mimeType) {
278 var nb = 0,
279 info = ['file',
280 fieldname,
281 nb,
282 0,
283 filename,
284 encoding,
285 mimeType];
286 results.push(info);
287 stream.on('data', function(d) {
288 nb += d.length;
289 }).on('limit', function() {
290 ++info[3];
291 }).on('end', function() {
292 info[2] = nb;
293 if (stream.truncated)
294 ++info[3];
295 });
296 });
297 }
298 busboy.on('finish', function() {
299 assert(finishes++ === 0, makeMsg(v.what, 'finish emitted multiple times'));
300 assert.deepEqual(results.length,
301 v.expected.length,
302 makeMsg(v.what, 'Parsed result count mismatch. Saw '
303 + results.length
304 + '. Expected: ' + v.expected.length));
305
306 results.forEach(function(result, i) {
307 assert.deepEqual(result,
308 v.expected[i],
309 makeMsg(v.what,
310 'Result mismatch:\nParsed: ' + inspect(result)
311 + '\nExpected: ' + inspect(v.expected[i]))
312 );
313 });
314 ++t;
315 next();
316 }).on('error', function(err) {
317 if (!v.shouldError || v.shouldError !== err.message)
318 assert(false, makeMsg(v.what, 'Unexpected error: ' + err));
319 });
320
321 v.source.forEach(function(s) {
322 busboy.write(new Buffer(s, 'utf8'), EMPTY_FN);
323 });
324 busboy.end();
325}
326next();
327
328function makeMsg(what, msg) {
329 return '[' + group + what + ']: ' + msg;
330}
331
332process.on('exit', function() {
333 assert(t === tests.length,
334 makeMsg('_exit',
335 'Only finished ' + t + '/' + tests.length + ' tests'));
336});