1 | 'use strict';
|
2 |
|
3 | const assert = require('assert');
|
4 | const { randomFillSync } = require('crypto');
|
5 | const { inspect } = require('util');
|
6 |
|
7 | const busboy = require('..');
|
8 |
|
9 | const { mustCall } = require('./common.js');
|
10 |
|
11 | const BOUNDARY = 'u2KxIV5yF1y+xUspOQCCZopaVgeV6Jxihv35XQJmuTx8X3sh';
|
12 |
|
13 | function formDataSection(key, value) {
|
14 | return Buffer.from(
|
15 | `\r\n--${BOUNDARY}`
|
16 | + `\r\nContent-Disposition: form-data; name="${key}"`
|
17 | + `\r\n\r\n${value}`
|
18 | );
|
19 | }
|
20 |
|
21 | function formDataFile(key, filename, contentType) {
|
22 | const buf = Buffer.allocUnsafe(100000);
|
23 | return Buffer.concat([
|
24 | Buffer.from(`\r\n--${BOUNDARY}\r\n`),
|
25 | Buffer.from(`Content-Disposition: form-data; name="${key}"`
|
26 | + `; filename="${filename}"\r\n`),
|
27 | Buffer.from(`Content-Type: ${contentType}\r\n\r\n`),
|
28 | randomFillSync(buf)
|
29 | ]);
|
30 | }
|
31 |
|
32 | const reqChunks = [
|
33 | Buffer.concat([
|
34 | formDataFile('file', 'file.bin', 'application/octet-stream'),
|
35 | formDataSection('foo', 'foo value'),
|
36 | ]),
|
37 | formDataSection('bar', 'bar value'),
|
38 | Buffer.from(`\r\n--${BOUNDARY}--\r\n`)
|
39 | ];
|
40 | const bb = busboy({
|
41 | headers: {
|
42 | 'content-type': `multipart/form-data; boundary=${BOUNDARY}`
|
43 | }
|
44 | });
|
45 | const expected = [
|
46 | { type: 'file',
|
47 | name: 'file',
|
48 | info: {
|
49 | filename: 'file.bin',
|
50 | encoding: '7bit',
|
51 | mimeType: 'application/octet-stream',
|
52 | },
|
53 | },
|
54 | { type: 'field',
|
55 | name: 'foo',
|
56 | val: 'foo value',
|
57 | info: {
|
58 | nameTruncated: false,
|
59 | valueTruncated: false,
|
60 | encoding: '7bit',
|
61 | mimeType: 'text/plain',
|
62 | },
|
63 | },
|
64 | { type: 'field',
|
65 | name: 'bar',
|
66 | val: 'bar value',
|
67 | info: {
|
68 | nameTruncated: false,
|
69 | valueTruncated: false,
|
70 | encoding: '7bit',
|
71 | mimeType: 'text/plain',
|
72 | },
|
73 | },
|
74 | ];
|
75 | const results = [];
|
76 |
|
77 | bb.on('field', (name, val, info) => {
|
78 | results.push({ type: 'field', name, val, info });
|
79 | });
|
80 |
|
81 | bb.on('file', (name, stream, info) => {
|
82 | results.push({ type: 'file', name, info });
|
83 |
|
84 |
|
85 | setTimeout(() => {
|
86 | stream.resume();
|
87 | }, 10);
|
88 | });
|
89 |
|
90 | bb.on('close', mustCall(() => {
|
91 | assert.deepStrictEqual(
|
92 | results,
|
93 | expected,
|
94 | 'Results mismatch.\n'
|
95 | + `Parsed: ${inspect(results)}\n`
|
96 | + `Expected: ${inspect(expected)}`
|
97 | );
|
98 | }));
|
99 |
|
100 | for (const chunk of reqChunks)
|
101 | bb.write(chunk);
|
102 | bb.end();
|