test-types-multipart-stream-pause.js 2.3 KB

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