summaryrefslogtreecommitdiffstats
path: root/fastify-busboy/bench
diff options
context:
space:
mode:
Diffstat (limited to 'fastify-busboy/bench')
-rw-r--r--fastify-busboy/bench/busboy-form-bench-latin1.js32
-rw-r--r--fastify-busboy/bench/busboy-form-bench-utf8.js32
-rw-r--r--fastify-busboy/bench/createMultipartBufferForEncodingBench.js23
-rw-r--r--fastify-busboy/bench/dicer/dicer-bench-multipart-parser.js60
-rw-r--r--fastify-busboy/bench/dicer/formidable-bench-multipart-parser.js71
-rw-r--r--fastify-busboy/bench/dicer/multipartser-bench-multipart-parser.js57
-rw-r--r--fastify-busboy/bench/dicer/multiparty-bench-multipart-parser.js78
-rw-r--r--fastify-busboy/bench/dicer/parted-bench-multipart-parser.js65
-rw-r--r--fastify-busboy/bench/dicer/parted-multipart.js486
-rw-r--r--fastify-busboy/bench/fastify-busboy-form-bench-latin1.js31
-rw-r--r--fastify-busboy/bench/fastify-busboy-form-bench-utf8.js31
-rw-r--r--fastify-busboy/bench/parse-params.js21
12 files changed, 987 insertions, 0 deletions
diff --git a/fastify-busboy/bench/busboy-form-bench-latin1.js b/fastify-busboy/bench/busboy-form-bench-latin1.js
new file mode 100644
index 0000000..33634ad
--- /dev/null
+++ b/fastify-busboy/bench/busboy-form-bench-latin1.js
@@ -0,0 +1,32 @@
+'use strict'
+
+const Busboy = require('busboy');
+const { createMultipartBufferForEncodingBench } = require("./createMultipartBufferForEncodingBench");
+
+ for (var i = 0, il = 10000; i < il; i++) { // eslint-disable-line no-var
+ const boundary = '-----------------------------168072824752491622650073',
+ busboy = new Busboy({
+ headers: {
+ 'content-type': 'multipart/form-data; boundary=' + boundary
+ }
+ }),
+ buffer = createMultipartBufferForEncodingBench(boundary, 100, 'iso-8859-1'),
+ mb = buffer.length / 1048576;
+
+ let processedData = 0;
+ busboy.on('file', (field, file, filename, encoding, mimetype) => {
+ file.resume()
+ })
+
+ busboy.on('error', function (err) {
+ })
+ busboy.on('finish', function () {
+ })
+
+ const start = +new Date();
+ const result = busboy.write(buffer, () => { });
+ busboy.end();
+ const duration = +new Date - start;
+ const mbPerSec = (mb / (duration / 1000)).toFixed(2);
+ console.log(mbPerSec + ' mb/sec');
+ } \ No newline at end of file
diff --git a/fastify-busboy/bench/busboy-form-bench-utf8.js b/fastify-busboy/bench/busboy-form-bench-utf8.js
new file mode 100644
index 0000000..1e6e0b7
--- /dev/null
+++ b/fastify-busboy/bench/busboy-form-bench-utf8.js
@@ -0,0 +1,32 @@
+'use strict'
+
+const Busboy = require('busboy');
+const { createMultipartBufferForEncodingBench } = require("./createMultipartBufferForEncodingBench");
+
+ for (var i = 0, il = 10000; i < il; i++) { // eslint-disable-line no-var
+ const boundary = '-----------------------------168072824752491622650073',
+ busboy = new Busboy({
+ headers: {
+ 'content-type': 'multipart/form-data; boundary=' + boundary
+ }
+ }),
+ buffer = createMultipartBufferForEncodingBench(boundary, 100, 'utf-8'),
+ mb = buffer.length / 1048576;
+
+ let processedData = 0;
+ busboy.on('file', (field, file, filename, encoding, mimetype) => {
+ file.resume()
+ })
+
+ busboy.on('error', function (err) {
+ })
+ busboy.on('finish', function () {
+ })
+
+ const start = +new Date();
+ const result = busboy.write(buffer, () => { });
+ busboy.end();
+ const duration = +new Date - start;
+ const mbPerSec = (mb / (duration / 1000)).toFixed(2);
+ console.log(mbPerSec + ' mb/sec');
+ } \ No newline at end of file
diff --git a/fastify-busboy/bench/createMultipartBufferForEncodingBench.js b/fastify-busboy/bench/createMultipartBufferForEncodingBench.js
new file mode 100644
index 0000000..9d20f8f
--- /dev/null
+++ b/fastify-busboy/bench/createMultipartBufferForEncodingBench.js
@@ -0,0 +1,23 @@
+'use strict'
+
+function createMultipartBufferForEncodingBench(boundary, amount, charset) {
+ const filename = charset === 'utf-8' ? 'utf-8\'\'%c2%a3%20and%20%e2%82%ac%20rates' : `${charset}\'en\'%A3%20rates`;
+ const head = '--' + boundary + '\r\n'
+ + 'content-disposition: form-data; name="field1"\r\n'
+ + 'content-type: text/plain;charset=' + charset + '; filename*=' + filename + '\r\n'
+ + '\r\n', tail = '\r\n--' + boundary + '--\r\n', buffer = Buffer.concat([Buffer.from(head), Buffer.from(`
+Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus pretium leo ex, vitae dignissim felis viverra non. Praesent id quam ac elit tincidunt porttitor sed eget magna. Vivamus nibh ipsum, malesuada in eros sit amet, rutrum mattis leo. Ut nunc justo, ornare a finibus in, consectetur euismod sapien. Praesent facilisis, odio consectetur facilisis varius, tellus justo tristique sapien, non porttitor eros massa quis nibh. Nam blandit orci ac efficitur cursus. Nunc non mollis sapien, sit amet pretium odio. Nam vestibulum lectus ac orci egestas aliquet. Duis nec nibh quis augue consequat vulputate a a dui.
+
+Aenean nec laoreet dolor, commodo aliquam leo. Quisque at placerat sem. In scelerisque cursus dolor, ac aliquam metus malesuada in. Vestibulum lacinia dolor purus, at convallis ipsum iaculis id. Integer bibendum sem neque, at bibendum enim lobortis eu. Cras pretium arcu eget congue cursus. Curabitur blandit ultricies mollis. Sed lacinia quis felis ut fringilla.
+
+Nulla vitae lobortis metus. Morbi gravida risus tortor, in pulvinar massa lobortis vitae. Etiam vitae massa libero. Sed id tincidunt elit. Quisque congue felis vel aliquam varius. Sed a massa vitae lectus vehicula lacinia vitae ac justo. In commodo sodales nisi finibus vulputate. Suspendisse viverra, est eget fringilla gravida, nulla justo vulputate lorem, at eleifend nisi urna a eros. Sed sit amet ipsum vehicula, venenatis urna ac, interdum felis.
+
+Cras semper mi magna, nec iaculis neque rhoncus at. In sit amet odio sed libero fringilla commodo. Sed hendrerit pulvinar turpis sed porta. Pellentesque consequat scelerisque sapien nec iaculis. Aenean sed nunc a purus laoreet efficitur id eu orci. Mauris tincidunt auctor congue. Aliquam nisi ligula, facilisis a molestie sed, luctus vitae mauris. Mauris at facilisis elit. Maecenas sodales pretium nisi in sodales. Cras nec blandit enim. Praesent in lacus et nibh varius suscipit in sit amet nibh.
+
+Nam hendrerit justo eu lectus molestie, sit amet fringilla ipsum semper. Maecenas sit amet nunc elementum, interdum nunc eu, euismod ipsum. Vestibulum ut mauris sapien. Praesent nec felis ex. Fusce vel leo lobortis, mattis sem a, ullamcorper dolor. Aliquam erat volutpat. Fusce feugiat odio ut feugiat volutpat. Vestibulum magna ante, tempor in volutpat ut, gravida vitae justo. Praesent vitae eleifend eros. Integer feugiat molestie dolor, et pretium enim accumsan sit amet. Sed quis suscipit dui. Integer gravida dolor elit, sit amet fringilla odio commodo at. Quisque ut eleifend risus. Nunc mollis velit quis lectus laoreet pellentesque.\r\n\r\n`)]);
+
+ const buffers = new Array(amount).fill(buffer);
+ buffers.push(Buffer.from(tail));
+ return Buffer.concat(buffers);
+}
+exports.createMultipartBufferForEncodingBench = createMultipartBufferForEncodingBench;
diff --git a/fastify-busboy/bench/dicer/dicer-bench-multipart-parser.js b/fastify-busboy/bench/dicer/dicer-bench-multipart-parser.js
new file mode 100644
index 0000000..d24f599
--- /dev/null
+++ b/fastify-busboy/bench/dicer/dicer-bench-multipart-parser.js
@@ -0,0 +1,60 @@
+'use strict'
+
+const Dicer = require('../../deps/dicer/lib/Dicer')
+
+function createMultipartBuffer(boundary, size) {
+ const head =
+ '--' + boundary + '\r\n'
+ + 'content-disposition: form-data; name="field1"\r\n'
+ + '\r\n'
+ , tail = '\r\n--' + boundary + '--\r\n'
+ , buffer = Buffer.allocUnsafe(size);
+
+ buffer.write(head, 0, 'ascii');
+ buffer.write(tail, buffer.length - tail.length, 'ascii');
+ return buffer;
+}
+
+for (var i = 0, il = 10; i < il; i++) { // eslint-disable-line no-var
+ const boundary = '-----------------------------168072824752491622650073',
+ d = new Dicer({ boundary: boundary }),
+ mb = 100,
+ buffer = createMultipartBuffer(boundary, mb * 1024 * 1024),
+ callbacks =
+ {
+ partBegin: -1,
+ partEnd: -1,
+ headerField: -1,
+ headerValue: -1,
+ partData: -1,
+ end: -1,
+ };
+
+
+ d.on('part', function (p) {
+ callbacks.partBegin++;
+ p.on('header', function (header) {
+ /*for (var h in header)
+ console.log('Part header: k: ' + inspect(h) + ', v: ' + inspect(header[h]));*/
+ });
+ p.on('data', function (data) {
+ callbacks.partData++;
+ //console.log('Part data: ' + inspect(data.toString()));
+ });
+ p.on('end', function () {
+ //console.log('End of part\n');
+ callbacks.partEnd++;
+ });
+ });
+ d.on('end', function () {
+ //console.log('End of parts');
+ callbacks.end++;
+ });
+
+ const start = +new Date();
+ d.write(buffer);
+ const duration = +new Date - start;
+ const mbPerSec = (mb / (duration / 1000)).toFixed(2);
+
+ console.log(mbPerSec + ' mb/sec');
+}
diff --git a/fastify-busboy/bench/dicer/formidable-bench-multipart-parser.js b/fastify-busboy/bench/dicer/formidable-bench-multipart-parser.js
new file mode 100644
index 0000000..0470771
--- /dev/null
+++ b/fastify-busboy/bench/dicer/formidable-bench-multipart-parser.js
@@ -0,0 +1,71 @@
+'use strict'
+
+require('../node_modules/formidable/test/common');
+var multipartParser = require('../node_modules/formidable/lib/multipart_parser'),
+ MultipartParser = multipartParser.MultipartParser,
+ parser = new MultipartParser(),
+ boundary = '-----------------------------168072824752491622650073',
+ mb = 100,
+ buffer = createMultipartBuffer(boundary, mb * 1024 * 1024),
+ callbacks =
+ { partBegin: -1,
+ partEnd: -1,
+ headerField: -1,
+ headerValue: -1,
+ partData: -1,
+ end: -1,
+ };
+
+
+parser.initWithBoundary(boundary);
+parser.onHeaderField = function() {
+ callbacks.headerField++;
+};
+
+parser.onHeaderValue = function() {
+ callbacks.headerValue++;
+};
+
+parser.onPartBegin = function() {
+ callbacks.partBegin++;
+};
+
+parser.onPartData = function() {
+ callbacks.partData++;
+};
+
+parser.onPartEnd = function() {
+ callbacks.partEnd++;
+};
+
+parser.onEnd = function() {
+ callbacks.end++;
+};
+
+var start = +new Date(),
+ nparsed = parser.write(buffer),
+ duration = +new Date - start,
+ mbPerSec = (mb / (duration / 1000)).toFixed(2);
+
+console.log(mbPerSec+' mb/sec');
+
+//assert.equal(nparsed, buffer.length);
+
+function createMultipartBuffer(boundary, size) {
+ var head =
+ '--'+boundary+'\r\n'
+ + 'content-disposition: form-data; name="field1"\r\n'
+ + '\r\n'
+ , tail = '\r\n--'+boundary+'--\r\n'
+ , buffer = Buffer.allocUnsafe(size);
+
+ buffer.write(head, 'ascii', 0);
+ buffer.write(tail, 'ascii', buffer.length - tail.length);
+ return buffer;
+}
+
+process.on('exit', function() {
+ /*for (var k in callbacks) {
+ assert.equal(0, callbacks[k], k+' count off by '+callbacks[k]);
+ }*/
+});
diff --git a/fastify-busboy/bench/dicer/multipartser-bench-multipart-parser.js b/fastify-busboy/bench/dicer/multipartser-bench-multipart-parser.js
new file mode 100644
index 0000000..40ca00b
--- /dev/null
+++ b/fastify-busboy/bench/dicer/multipartser-bench-multipart-parser.js
@@ -0,0 +1,57 @@
+'use strict'
+
+var multipartser = require('multipartser'),
+ boundary = '-----------------------------168072824752491622650073',
+ parser = multipartser(),
+ mb = 100,
+ buffer = createMultipartBuffer(boundary, mb * 1024 * 1024),
+ callbacks =
+ { partBegin: -1,
+ partEnd: -1,
+ headerField: -1,
+ headerValue: -1,
+ partData: -1,
+ end: -1,
+ };
+
+parser.boundary( boundary );
+
+parser.on( 'part', function ( part ) {
+});
+
+parser.on( 'end', function () {
+ //console.log( 'completed parsing' );
+});
+
+parser.on( 'error', function ( error ) {
+ console.error( error );
+});
+
+var start = +new Date(),
+ nparsed = parser.data(buffer),
+ nend = parser.end(),
+ duration = +new Date - start,
+ mbPerSec = (mb / (duration / 1000)).toFixed(2);
+
+console.log(mbPerSec+' mb/sec');
+
+//assert.equal(nparsed, buffer.length);
+
+function createMultipartBuffer(boundary, size) {
+ var head =
+ '--'+boundary+'\r\n'
+ + 'content-disposition: form-data; name="field1"\r\n'
+ + '\r\n'
+ , tail = '\r\n--'+boundary+'--\r\n'
+ , buffer = Buffer.allocUnsafe(size);
+
+ buffer.write(head, 'ascii', 0);
+ buffer.write(tail, 'ascii', buffer.length - tail.length);
+ return buffer;
+}
+
+process.on('exit', function() {
+ /*for (var k in callbacks) {
+ assert.equal(0, callbacks[k], k+' count off by '+callbacks[k]);
+ }*/
+});
diff --git a/fastify-busboy/bench/dicer/multiparty-bench-multipart-parser.js b/fastify-busboy/bench/dicer/multiparty-bench-multipart-parser.js
new file mode 100644
index 0000000..ab79ec0
--- /dev/null
+++ b/fastify-busboy/bench/dicer/multiparty-bench-multipart-parser.js
@@ -0,0 +1,78 @@
+'use strict'
+
+var assert = require('node:assert'),
+ Form = require('multiparty').Form,
+ boundary = '-----------------------------168072824752491622650073',
+ mb = 100,
+ buffer = createMultipartBuffer(boundary, mb * 1024 * 1024),
+ callbacks =
+ { partBegin: -1,
+ partEnd: -1,
+ headerField: -1,
+ headerValue: -1,
+ partData: -1,
+ end: -1,
+ };
+
+var form = new Form({ boundary: boundary });
+
+hijack('onParseHeaderField', function() {
+ callbacks.headerField++;
+});
+
+hijack('onParseHeaderValue', function() {
+ callbacks.headerValue++;
+});
+
+hijack('onParsePartBegin', function() {
+ callbacks.partBegin++;
+});
+
+hijack('onParsePartData', function() {
+ callbacks.partData++;
+});
+
+hijack('onParsePartEnd', function() {
+ callbacks.partEnd++;
+});
+
+form.on('finish', function() {
+ callbacks.end++;
+});
+
+var start = new Date();
+form.write(buffer, function(err) {
+ var duration = new Date() - start;
+ assert.ifError(err);
+ var mbPerSec = (mb / (duration / 1000)).toFixed(2);
+ console.log(mbPerSec+' mb/sec');
+});
+
+//assert.equal(nparsed, buffer.length);
+
+function createMultipartBuffer(boundary, size) {
+ var head =
+ '--'+boundary+'\r\n'
+ + 'content-disposition: form-data; name="field1"\r\n'
+ + '\r\n'
+ , tail = '\r\n--'+boundary+'--\r\n'
+ , buffer = Buffer.allocUnsafe(size);
+
+ buffer.write(head, 'ascii', 0);
+ buffer.write(tail, 'ascii', buffer.length - tail.length);
+ return buffer;
+}
+
+process.on('exit', function() {
+ /*for (var k in callbacks) {
+ assert.equal(0, callbacks[k], k+' count off by '+callbacks[k]);
+ }*/
+});
+
+function hijack(name, fn) {
+ var oldFn = form[name];
+ form[name] = function() {
+ fn();
+ return oldFn.apply(this, arguments);
+ };
+}
diff --git a/fastify-busboy/bench/dicer/parted-bench-multipart-parser.js b/fastify-busboy/bench/dicer/parted-bench-multipart-parser.js
new file mode 100644
index 0000000..e0a4670
--- /dev/null
+++ b/fastify-busboy/bench/dicer/parted-bench-multipart-parser.js
@@ -0,0 +1,65 @@
+'use strict'
+
+// A special, edited version of the multipart parser from parted is needed here
+// because otherwise it attempts to do some things above and beyond just parsing
+// -- like saving to disk and whatnot
+
+var assert = require('node:assert');
+var Parser = require('./parted-multipart'),
+ boundary = '-----------------------------168072824752491622650073',
+ parser = new Parser('boundary=' + boundary),
+ mb = 100,
+ buffer = createMultipartBuffer(boundary, mb * 1024 * 1024),
+ callbacks =
+ { partBegin: -1,
+ partEnd: -1,
+ headerField: -1,
+ headerValue: -1,
+ partData: -1,
+ end: -1,
+ };
+
+
+parser.on('header', function() {
+ //callbacks.headerField++;
+});
+
+parser.on('data', function() {
+ //callbacks.partBegin++;
+});
+
+parser.on('part', function() {
+
+});
+
+parser.on('end', function() {
+ //callbacks.end++;
+});
+
+var start = +new Date(),
+ nparsed = parser.write(buffer),
+ duration = +new Date - start,
+ mbPerSec = (mb / (duration / 1000)).toFixed(2);
+
+console.log(mbPerSec+' mb/sec');
+
+//assert.equal(nparsed, buffer.length);
+
+function createMultipartBuffer(boundary, size) {
+ var head =
+ '--'+boundary+'\r\n'
+ + 'content-disposition: form-data; name="field1"\r\n'
+ + '\r\n'
+ , tail = '\r\n--'+boundary+'--\r\n'
+ , buffer = Buffer.allocUnsafe(size);
+
+ buffer.write(head, 'ascii', 0);
+ buffer.write(tail, 'ascii', buffer.length - tail.length);
+ return buffer;
+}
+
+process.on('exit', function() {
+ /*for (var k in callbacks) {
+ assert.equal(0, callbacks[k], k+' count off by '+callbacks[k]);
+ }*/
+});
diff --git a/fastify-busboy/bench/dicer/parted-multipart.js b/fastify-busboy/bench/dicer/parted-multipart.js
new file mode 100644
index 0000000..f214ff4
--- /dev/null
+++ b/fastify-busboy/bench/dicer/parted-multipart.js
@@ -0,0 +1,486 @@
+'use strict'
+
+/**
+ * Parted (https://github.com/chjj/parted)
+ * A streaming multipart state parser.
+ * Copyright (c) 2011, Christopher Jeffrey. (MIT Licensed)
+ */
+
+var fs = require('node:fs')
+ , path = require('node:path')
+ , EventEmitter = require('node:events').EventEmitter
+ , StringDecoder = require('node:string_decoder').StringDecoder
+ , set = require('qs').set
+ , each = Array.prototype.forEach;
+
+/**
+ * Character Constants
+ */
+
+var DASH = '-'.charCodeAt(0)
+ , CR = '\r'.charCodeAt(0)
+ , LF = '\n'.charCodeAt(0)
+ , COLON = ':'.charCodeAt(0)
+ , SPACE = ' '.charCodeAt(0);
+
+/**
+ * Parser
+ */
+
+var Parser = function(type, options) {
+ if (!(this instanceof Parser)) {
+ return new Parser(type, options);
+ }
+
+ EventEmitter.call(this);
+
+ this.writable = true;
+ this.readable = true;
+
+ this.options = options || {};
+
+ var key = grab(type, 'boundary');
+ if (!key) {
+ return this._error('No boundary key found.');
+ }
+
+ this.key = Buffer.allocUnsafe('\r\n--' + key);
+
+ this._key = {};
+ each.call(this.key, function(ch) {
+ this._key[ch] = true;
+ }, this);
+
+ this.state = 'start';
+ this.pending = 0;
+ this.written = 0;
+ this.writtenDisk = 0;
+ this.buff = Buffer.allocUnsafe(200);
+
+ this.preamble = true;
+ this.epilogue = false;
+
+ this._reset();
+};
+
+Parser.prototype.__proto__ = EventEmitter.prototype;
+
+/**
+ * Parsing
+ */
+
+Parser.prototype.write = function(data) {
+ if (!this.writable
+ || this.epilogue) return;
+
+ try {
+ this._parse(data);
+ } catch (e) {
+ this._error(e);
+ }
+
+ return true;
+};
+
+Parser.prototype.end = function(data) {
+ if (!this.writable) return;
+
+ if (data) this.write(data);
+
+ if (!this.epilogue) {
+ return this._error('Message underflow.');
+ }
+
+ return true;
+};
+
+Parser.prototype._parse = function(data) {
+ var i = 0
+ , len = data.length
+ , buff = this.buff
+ , key = this.key
+ , ch
+ , val
+ , j;
+
+ for (; i < len; i++) {
+ if (this.pos >= 200) {
+ return this._error('Potential buffer overflow.');
+ }
+
+ ch = data[i];
+
+ switch (this.state) {
+ case 'start':
+ switch (ch) {
+ case DASH:
+ this.pos = 3;
+ this.state = 'key';
+ break;
+ default:
+ break;
+ }
+ break;
+ case 'key':
+ if (this.pos === key.length) {
+ this.state = 'key_end';
+ i--;
+ } else if (ch !== key[this.pos]) {
+ if (this.preamble) {
+ this.state = 'start';
+ i--;
+ } else {
+ this.state = 'body';
+ val = this.pos - i;
+ if (val > 0) {
+ this._write(key.slice(0, val));
+ }
+ i--;
+ }
+ } else {
+ this.pos++;
+ }
+ break;
+ case 'key_end':
+ switch (ch) {
+ case CR:
+ this.state = 'key_line_end';
+ break;
+ case DASH:
+ this.state = 'key_dash_end';
+ break;
+ default:
+ return this._error('Expected CR or DASH.');
+ }
+ break;
+ case 'key_line_end':
+ switch (ch) {
+ case LF:
+ if (this.preamble) {
+ this.preamble = false;
+ } else {
+ this._finish();
+ }
+ this.state = 'header_name';
+ this.pos = 0;
+ break;
+ default:
+ return this._error('Expected CR.');
+ }
+ break;
+ case 'key_dash_end':
+ switch (ch) {
+ case DASH:
+ this.epilogue = true;
+ this._finish();
+ return;
+ default:
+ return this._error('Expected DASH.');
+ }
+ case 'header_name':
+ switch (ch) {
+ case COLON:
+ this.header = buff.toString('ascii', 0, this.pos);
+ this.pos = 0;
+ this.state = 'header_val';
+ break;
+ default:
+ buff[this.pos++] = ch | 32;
+ break;
+ }
+ break;
+ case 'header_val':
+ switch (ch) {
+ case CR:
+ this.state = 'header_val_end';
+ break;
+ case SPACE:
+ if (this.pos === 0) {
+ break;
+ }
+ // FALL-THROUGH
+ default:
+ buff[this.pos++] = ch;
+ break;
+ }
+ break;
+ case 'header_val_end':
+ switch (ch) {
+ case LF:
+ val = buff.toString('ascii', 0, this.pos);
+ this._header(this.header, val);
+ this.pos = 0;
+ this.state = 'header_end';
+ break;
+ default:
+ return this._error('Expected LF.');
+ }
+ break;
+ case 'header_end':
+ switch (ch) {
+ case CR:
+ this.state = 'head_end';
+ break;
+ default:
+ this.state = 'header_name';
+ i--;
+ break;
+ }
+ break;
+ case 'head_end':
+ switch (ch) {
+ case LF:
+ this.state = 'body';
+ i++;
+ if (i >= len) return;
+ data = data.slice(i);
+ i = -1;
+ len = data.length;
+ break;
+ default:
+ return this._error('Expected LF.');
+ }
+ break;
+ case 'body':
+ switch (ch) {
+ case CR:
+ if (i > 0) {
+ this._write(data.slice(0, i));
+ }
+ this.pos = 1;
+ this.state = 'key';
+ data = data.slice(i);
+ i = 0;
+ len = data.length;
+ break;
+ default:
+ // boyer-moore-like algorithm
+ // at felixge's suggestion
+ while ((j = i + key.length - 1) < len) {
+ if (this._key[data[j]]) break;
+ i = j;
+ }
+ break;
+ }
+ break;
+ }
+ }
+
+ if (this.state === 'body') {
+ this._write(data);
+ }
+};
+
+Parser.prototype._header = function(name, val) {
+ /*if (name === 'content-disposition') {
+ this.field = grab(val, 'name');
+ this.file = grab(val, 'filename');
+
+ if (this.file) {
+ this.data = stream(this.file, this.options.path);
+ } else {
+ this.decode = new StringDecoder('utf8');
+ this.data = '';
+ }
+ }*/
+
+ return this.emit('header', name, val);
+};
+
+Parser.prototype._write = function(data) {
+ /*if (this.data == null) {
+ return this._error('No disposition.');
+ }
+
+ if (this.file) {
+ this.data.write(data);
+ this.writtenDisk += data.length;
+ } else {
+ this.data += this.decode.write(data);
+ this.written += data.length;
+ }*/
+
+ this.emit('data', data);
+};
+
+Parser.prototype._reset = function() {
+ this.pos = 0;
+ this.decode = null;
+ this.field = null;
+ this.data = null;
+ this.file = null;
+ this.header = null;
+};
+
+Parser.prototype._error = function(err) {
+ this.destroy();
+ this.emit('error', typeof err === 'string'
+ ? new Error(err)
+ : err);
+};
+
+Parser.prototype.destroy = function(err) {
+ this.writable = false;
+ this.readable = false;
+ this._reset();
+};
+
+Parser.prototype._finish = function() {
+ var self = this
+ , field = this.field
+ , data = this.data
+ , file = this.file
+ , part;
+
+ this.pending++;
+
+ this._reset();
+
+ if (data && data.path) {
+ part = data.path;
+ data.end(next);
+ } else {
+ part = data;
+ next();
+ }
+
+ function next() {
+ if (!self.readable) return;
+
+ self.pending--;
+
+ self.emit('part', field, part);
+
+ if (data && data.path) {
+ self.emit('file', field, part, file);
+ }
+
+ if (self.epilogue && !self.pending) {
+ self.emit('end');
+ self.destroy();
+ }
+ }
+};
+
+/**
+ * Uploads
+ */
+
+Parser.root = process.platform === 'win32'
+ ? 'C:/Temp'
+ : '/tmp';
+
+/**
+ * Middleware
+ */
+
+Parser.middleware = function(options) {
+ options = options || {};
+ return function(req, res, next) {
+ if (options.ensureBody) {
+ req.body = {};
+ }
+
+ if (req.method === 'GET'
+ || req.method === 'HEAD'
+ || req._multipart) return next();
+
+ req._multipart = true;
+
+ var type = req.headers['content-type'];
+
+ if (type) type = type.split(';', 1)[0].trim().toLowerCase();
+
+ if (type === 'multipart/form-data') {
+ Parser.handle(req, res, next, options);
+ } else {
+ next();
+ }
+ };
+};
+
+/**
+ * Handler
+ */
+
+Parser.handle = function(req, res, next, options) {
+ var parser = new Parser(req.headers['content-type'], options)
+ , diskLimit = options.diskLimit
+ , limit = options.limit
+ , parts = {}
+ , files = {};
+
+ parser.on('error', function(err) {
+ req.destroy();
+ next(err);
+ });
+
+ parser.on('part', function(field, part) {
+ set(parts, field, part);
+ });
+
+ parser.on('file', function(field, path, name) {
+ set(files, field, {
+ path: path,
+ name: name,
+ toString: function() {
+ return path;
+ }
+ });
+ });
+
+ parser.on('data', function() {
+ if (this.writtenDisk > diskLimit || this.written > limit) {
+ this.emit('error', new Error('Overflow.'));
+ this.destroy();
+ }
+ });
+
+ parser.on('end', next);
+
+ req.body = parts;
+ req.files = files;
+ req.pipe(parser);
+};
+
+/**
+ * Helpers
+ */
+
+var isWindows = process.platform === 'win32';
+
+var stream = function(name, dir) {
+ var ext = path.extname(name) || ''
+ , name = path.basename(name, ext) || ''
+ , dir = dir || Parser.root
+ , tag;
+
+ tag = Math.random().toString(36).substring(2);
+
+ name = name.substring(0, 200) + '.' + tag;
+ name = path.join(dir, name) + ext.substring(0, 6);
+ name = name.replace(/\0/g, '');
+
+ if (isWindows) {
+ name = name.replace(/[:*<>|"?]/g, '');
+ }
+
+ return fs.createWriteStream(name);
+};
+
+var grab = function(str, name) {
+ if (!str) return;
+
+ var rx = new RegExp('\\b' + name + '\\s*=\\s*("[^"]+"|\'[^\']+\'|[^;,]+)', 'i')
+ , cap = rx.exec(str);
+
+ if (cap) {
+ return cap[1].trim().replace(/^['"]|['"]$/g, '');
+ }
+};
+
+/**
+ * Expose
+ */
+
+module.exports = Parser;
diff --git a/fastify-busboy/bench/fastify-busboy-form-bench-latin1.js b/fastify-busboy/bench/fastify-busboy-form-bench-latin1.js
new file mode 100644
index 0000000..7ca5f44
--- /dev/null
+++ b/fastify-busboy/bench/fastify-busboy-form-bench-latin1.js
@@ -0,0 +1,31 @@
+'use strict'
+
+const Busboy = require('../lib/main');
+const { createMultipartBufferForEncodingBench } = require("./createMultipartBufferForEncodingBench");
+
+ for (var i = 0, il = 10000; i < il; i++) { // eslint-disable-line no-var
+ const boundary = '-----------------------------168072824752491622650073',
+ busboy = new Busboy({
+ headers: {
+ 'content-type': 'multipart/form-data; boundary=' + boundary
+ }
+ }),
+ buffer = createMultipartBufferForEncodingBench(boundary, 100, 'iso-8859-1'),
+ mb = buffer.length / 1048576;
+
+ busboy.on('file', (field, file, filename, encoding, mimetype) => {
+ file.resume()
+ })
+
+ busboy.on('error', function (err) {
+ })
+ busboy.on('finish', function () {
+ })
+
+ const start = +new Date();
+ busboy.write(buffer, () => { });
+ busboy.end();
+ const duration = +new Date - start;
+ const mbPerSec = (mb / (duration / 1000)).toFixed(2);
+ console.log(mbPerSec + ' mb/sec');
+ }
diff --git a/fastify-busboy/bench/fastify-busboy-form-bench-utf8.js b/fastify-busboy/bench/fastify-busboy-form-bench-utf8.js
new file mode 100644
index 0000000..6c35071
--- /dev/null
+++ b/fastify-busboy/bench/fastify-busboy-form-bench-utf8.js
@@ -0,0 +1,31 @@
+'use strict'
+
+const Busboy = require('../lib/main');
+const { createMultipartBufferForEncodingBench } = require("./createMultipartBufferForEncodingBench");
+
+ for (var i = 0, il = 10000; i < il; i++) { // eslint-disable-line no-var
+ const boundary = '-----------------------------168072824752491622650073',
+ busboy = new Busboy({
+ headers: {
+ 'content-type': 'multipart/form-data; boundary=' + boundary
+ }
+ }),
+ buffer = createMultipartBufferForEncodingBench(boundary, 100, 'utf-8'),
+ mb = buffer.length / 1048576;
+
+ busboy.on('file', (field, file, filename, encoding, mimetype) => {
+ file.resume()
+ })
+
+ busboy.on('error', function (err) {
+ })
+ busboy.on('finish', function () {
+ })
+
+ const start = +new Date();
+ busboy.write(buffer, () => { });
+ busboy.end();
+ const duration = +new Date - start;
+ const mbPerSec = (mb / (duration / 1000)).toFixed(2);
+ console.log(mbPerSec + ' mb/sec');
+ }
diff --git a/fastify-busboy/bench/parse-params.js b/fastify-busboy/bench/parse-params.js
new file mode 100644
index 0000000..439a372
--- /dev/null
+++ b/fastify-busboy/bench/parse-params.js
@@ -0,0 +1,21 @@
+'use strict'
+
+const parseParams = require('../lib/utils/parseParams')
+const { Bench } = require('tinybench');
+const bench = new Bench();
+
+const simple = 'video/ogg'
+const complex = "'text/plain; filename*=utf-8''%c2%a3%20and%20%e2%82%ac%20rates'"
+
+bench
+ .add(simple, function () { parseParams(simple) })
+ .add(complex, function () { parseParams(complex) })
+ .run()
+ .then((tasks) => {
+ const errors = tasks.map(t => t.result?.error).filter((t) => t)
+ if (errors.length) {
+ errors.map((e) => console.error(e))
+ } else {
+ console.table(bench.table())
+ }
+ })