StreamingQuerystring.cjs 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. 'use strict';
  2. Object.defineProperty(exports, '__esModule', { value: true });
  3. var node_stream = require('node:stream');
  4. const maxFieldsSizeExceeded = 1006;
  5. const FormidableError = class extends Error {
  6. constructor(message, internalCode, httpCode = 500) {
  7. super(message);
  8. this.code = internalCode;
  9. this.httpCode = httpCode;
  10. }
  11. };
  12. // not used
  13. /* eslint-disable no-underscore-dangle */
  14. const AMPERSAND = 38;
  15. const EQUALS = 61;
  16. class QuerystringParser extends node_stream.Transform {
  17. constructor(options = {}) {
  18. super({ readableObjectMode: true });
  19. const { maxFieldSize } = options;
  20. this.maxFieldLength = maxFieldSize;
  21. this.buffer = Buffer.from('');
  22. this.fieldCount = 0;
  23. this.sectionStart = 0;
  24. this.key = '';
  25. this.readingKey = true;
  26. }
  27. _transform(buffer, encoding, callback) {
  28. let len = buffer.length;
  29. if (this.buffer && this.buffer.length) {
  30. // we have some data left over from the last write which we are in the middle of processing
  31. len += this.buffer.length;
  32. buffer = Buffer.concat([this.buffer, buffer], len);
  33. }
  34. for (let i = this.buffer.length || 0; i < len; i += 1) {
  35. const c = buffer[i];
  36. if (this.readingKey) {
  37. // KEY, check for =
  38. if (c === EQUALS) {
  39. this.key = this.getSection(buffer, i);
  40. this.readingKey = false;
  41. this.sectionStart = i + 1;
  42. } else if (c === AMPERSAND) {
  43. // just key, no value. Prepare to read another key
  44. this.emitField(this.getSection(buffer, i));
  45. this.sectionStart = i + 1;
  46. }
  47. // VALUE, check for &
  48. } else if (c === AMPERSAND) {
  49. this.emitField(this.key, this.getSection(buffer, i));
  50. this.sectionStart = i + 1;
  51. }
  52. if (
  53. this.maxFieldLength &&
  54. i - this.sectionStart === this.maxFieldLength
  55. ) {
  56. callback(
  57. new FormidableError(
  58. `${
  59. this.readingKey ? 'Key' : `Value for ${this.key}`
  60. } longer than maxFieldLength`,
  61. ),
  62. maxFieldsSizeExceeded,
  63. 413,
  64. );
  65. }
  66. }
  67. // Prepare the remaining key or value (from sectionStart to the end) for the next write() or for end()
  68. len -= this.sectionStart;
  69. if (len) {
  70. // i.e. Unless the last character was a & or =
  71. this.buffer = Buffer.from(this.buffer, 0, this.sectionStart);
  72. } else this.buffer = null;
  73. this.sectionStart = 0;
  74. callback();
  75. }
  76. _flush(callback) {
  77. // Emit the last field
  78. if (this.readingKey) {
  79. // we only have a key if there's something in the buffer. We definitely have no value
  80. if (this.buffer && this.buffer.length) {
  81. this.emitField(this.buffer.toString('ascii'));
  82. }
  83. } else {
  84. // We have a key, we may or may not have a value
  85. this.emitField(
  86. this.key,
  87. this.buffer && this.buffer.length && this.buffer.toString('ascii'),
  88. );
  89. }
  90. this.buffer = '';
  91. callback();
  92. }
  93. getSection(buffer, i) {
  94. if (i === this.sectionStart) return '';
  95. return buffer.toString('ascii', this.sectionStart, i);
  96. }
  97. emitField(key, val) {
  98. this.key = '';
  99. this.readingKey = true;
  100. this.push({ key, value: val || '' });
  101. }
  102. }
  103. // const q = new QuerystringParser({maxFieldSize: 100});
  104. // (async function() {
  105. // for await (const chunk of q) {
  106. // console.log(chunk);
  107. // }
  108. // })();
  109. // q.write("a=b&c=d")
  110. // q.end()
  111. exports.default = QuerystringParser;