@poppinss/multiparty 2.0.1 → 3.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -1
- package/index.js +82 -26
- package/package.json +3 -6
- package/HISTORY.md +0 -255
package/README.md
CHANGED
|
@@ -84,6 +84,9 @@ Creates a new form. Options:
|
|
|
84
84
|
* `maxFilesSize` - Only relevant when `autoFiles` is `true`. Limits the
|
|
85
85
|
total bytes accepted for all files combined. If this value is exceeded,
|
|
86
86
|
an `error` event is emitted. The default is `Infinity`.
|
|
87
|
+
* `maxHeaderSize` - Limits the size of header names and values for each part.
|
|
88
|
+
If this value is exceeded, an `error` event is emitted. The default size is
|
|
89
|
+
16KB.
|
|
87
90
|
* `autoFields` - Enables `field` events and disables `part` events for fields.
|
|
88
91
|
This is automatically set to `true` if you add a `field` listener.
|
|
89
92
|
* `autoFiles` - Enables `file` events and disables `part` events for files.
|
|
@@ -271,5 +274,5 @@ stream uploads to disk for you.
|
|
|
271
274
|
|
|
272
275
|
[npm-version-image]: https://img.shields.io/npm/v/@poppinss/multiparty?style=for-the-badge
|
|
273
276
|
|
|
274
|
-
[gh-workflow-image]: https://img.shields.io/github/workflow/status/poppinss/multiparty/test?style=for-the-badge
|
|
277
|
+
[gh-workflow-image]: https://img.shields.io/github/actions/workflow/status/poppinss/multiparty/test.yml?style=for-the-badge
|
|
275
278
|
[gh-workflow-url]: https://github.com/poppinss/multiparty/actions/workflows/test.yml "Github action"
|
package/index.js
CHANGED
|
@@ -9,13 +9,12 @@
|
|
|
9
9
|
'use strict'
|
|
10
10
|
|
|
11
11
|
var createError = require('http-errors')
|
|
12
|
-
var uid = require('uid-safe')
|
|
13
12
|
var stream = require('stream');
|
|
14
13
|
var util = require('util');
|
|
15
14
|
var fs = require('fs');
|
|
16
15
|
var path = require('path');
|
|
17
16
|
var os = require('os');
|
|
18
|
-
var
|
|
17
|
+
var crypto = require('crypto');
|
|
19
18
|
var StringDecoder = require('string_decoder').StringDecoder;
|
|
20
19
|
|
|
21
20
|
var START = 0;
|
|
@@ -40,14 +39,28 @@ var A = 97;
|
|
|
40
39
|
var Z = 122;
|
|
41
40
|
|
|
42
41
|
var CONTENT_TYPE_RE = /^multipart\/(?:form-data|related)(?:;|$)/i;
|
|
43
|
-
var
|
|
42
|
+
var CONTENT_TYPE_BOUNDARY_RE = /;[ \t]*boundary=(?:"([^"]*)"|([^;]+))/gi;
|
|
44
43
|
var FILE_EXT_RE = /(\.[_\-a-zA-Z0-9]{0,16})[\S\s]*/;
|
|
45
|
-
var FILENAME_PARAM_RE =
|
|
44
|
+
var FILENAME_PARAM_RE = /;[ \t]*filename=(?:"((?:[^"]|"(?![ \t]*(?:;|$)))*)"|([^;]+))/i
|
|
46
45
|
var LAST_BOUNDARY_SUFFIX_LEN = 4; // --\r\n
|
|
47
|
-
var NAME_PARAM_RE =
|
|
46
|
+
var NAME_PARAM_RE = /;[ \t]*name=(?:"([^"]*)"|([^;]+))/i
|
|
48
47
|
|
|
49
48
|
exports.Form = Form;
|
|
50
49
|
|
|
50
|
+
/**
|
|
51
|
+
* Generates a URL safe random string of a given size
|
|
52
|
+
*/
|
|
53
|
+
function randomUid(size) {
|
|
54
|
+
var bits = (size + 1) * 6
|
|
55
|
+
var buffer = crypto.randomBytes(Math.ceil(bits / 8))
|
|
56
|
+
return Buffer.from(buffer)
|
|
57
|
+
.toString('base64')
|
|
58
|
+
.replace(/\+/g, '-')
|
|
59
|
+
.replace(/\//g, '_')
|
|
60
|
+
.replace(/=/g, '')
|
|
61
|
+
.slice(0, size)
|
|
62
|
+
}
|
|
63
|
+
|
|
51
64
|
util.inherits(Form, stream.Writable);
|
|
52
65
|
function Form(options) {
|
|
53
66
|
var opts = options || {}
|
|
@@ -62,6 +75,7 @@ function Form(options) {
|
|
|
62
75
|
self.maxFields = opts.maxFields || 1000
|
|
63
76
|
self.maxFieldsSize = opts.maxFieldsSize || 2 * 1024 * 1024
|
|
64
77
|
self.maxFilesSize = opts.maxFilesSize || Infinity
|
|
78
|
+
self.maxHeaderSize = opts.maxHeaderSize || 16 * 1024
|
|
65
79
|
self.uploadDir = opts.uploadDir || os.tmpdir()
|
|
66
80
|
self.encoding = opts.encoding || 'utf8'
|
|
67
81
|
|
|
@@ -127,12 +141,24 @@ Form.prototype.parse = function(req, cb) {
|
|
|
127
141
|
});
|
|
128
142
|
});
|
|
129
143
|
self.on('field', function(name, value) {
|
|
130
|
-
var fieldsArray = fields
|
|
131
|
-
|
|
144
|
+
var fieldsArray = Object.prototype.hasOwnProperty.call(fields, name)
|
|
145
|
+
? fields[name]
|
|
146
|
+
: undefined;
|
|
147
|
+
if (Array.isArray(fieldsArray)) {
|
|
148
|
+
fieldsArray.push(value);
|
|
149
|
+
} else {
|
|
150
|
+
fields[name] = [value]
|
|
151
|
+
}
|
|
132
152
|
});
|
|
133
153
|
self.on('file', function(name, file) {
|
|
134
|
-
var filesArray = files
|
|
135
|
-
|
|
154
|
+
var filesArray = Object.prototype.hasOwnProperty.call(files, name)
|
|
155
|
+
? files[name]
|
|
156
|
+
: undefined;
|
|
157
|
+
if (Array.isArray(filesArray)) {
|
|
158
|
+
filesArray.push(file);
|
|
159
|
+
} else {
|
|
160
|
+
files[name] = [file]
|
|
161
|
+
}
|
|
136
162
|
});
|
|
137
163
|
self.on('close', function() {
|
|
138
164
|
end(function() {
|
|
@@ -172,10 +198,9 @@ Form.prototype.parse = function(req, cb) {
|
|
|
172
198
|
}
|
|
173
199
|
|
|
174
200
|
var boundary;
|
|
175
|
-
|
|
176
|
-
while ((m =
|
|
177
|
-
|
|
178
|
-
boundary = m[2] || m[3];
|
|
201
|
+
CONTENT_TYPE_BOUNDARY_RE.lastIndex = m.index + m[0].length - 1;
|
|
202
|
+
while ((m = CONTENT_TYPE_BOUNDARY_RE.exec(contentType))) {
|
|
203
|
+
boundary = m[1] || m[2];
|
|
179
204
|
break;
|
|
180
205
|
}
|
|
181
206
|
|
|
@@ -292,6 +317,7 @@ Form.prototype._write = function(buffer, encoding, cb) {
|
|
|
292
317
|
return;
|
|
293
318
|
}
|
|
294
319
|
self.onParseHeaderField(buffer.slice(self.headerFieldMark, i));
|
|
320
|
+
if (self.error) return;
|
|
295
321
|
self.headerFieldMark = null;
|
|
296
322
|
state = HEADER_VALUE_START;
|
|
297
323
|
break;
|
|
@@ -312,6 +338,7 @@ Form.prototype._write = function(buffer, encoding, cb) {
|
|
|
312
338
|
case HEADER_VALUE:
|
|
313
339
|
if (c === CR) {
|
|
314
340
|
self.onParseHeaderValue(buffer.slice(self.headerValueMark, i));
|
|
341
|
+
if (self.error) return;
|
|
315
342
|
self.headerValueMark = null;
|
|
316
343
|
self.onParseHeaderEnd();
|
|
317
344
|
state = HEADER_VALUE_ALMOST_DONE;
|
|
@@ -447,10 +474,20 @@ Form.prototype.onParsePartBegin = function() {
|
|
|
447
474
|
}
|
|
448
475
|
|
|
449
476
|
Form.prototype.onParseHeaderField = function(b) {
|
|
477
|
+
this.partHeadersSize += b.length;
|
|
478
|
+
if (this.partHeadersSize > this.maxHeaderSize) {
|
|
479
|
+
this.handleError(createError(413, 'maxHeaderSize ' + this.maxHeaderSize + ' exceeded'));
|
|
480
|
+
return;
|
|
481
|
+
}
|
|
450
482
|
this.headerField += this.headerFieldDecoder.write(b);
|
|
451
483
|
}
|
|
452
484
|
|
|
453
485
|
Form.prototype.onParseHeaderValue = function(b) {
|
|
486
|
+
this.partHeadersSize += b.length;
|
|
487
|
+
if (this.partHeadersSize > this.maxHeaderSize) {
|
|
488
|
+
this.handleError(createError(413, 'maxHeaderSize ' + this.maxHeaderSize + ' exceeded'));
|
|
489
|
+
return;
|
|
490
|
+
}
|
|
454
491
|
this.headerValue += this.headerValueDecoder.write(b);
|
|
455
492
|
}
|
|
456
493
|
|
|
@@ -476,7 +513,13 @@ Form.prototype.onParseHeaderEnd = function() {
|
|
|
476
513
|
|
|
477
514
|
Form.prototype.onParsePartData = function(b) {
|
|
478
515
|
if (this.partTransferEncoding === 'base64') {
|
|
479
|
-
|
|
516
|
+
// Count base64 characters, not whitespace, and retain incomplete groups.
|
|
517
|
+
var data = this.partRemainder + b.toString('binary').replace(/[\t\n\v\f\r ]/g, '');
|
|
518
|
+
var length = data.length - (data.length % 4);
|
|
519
|
+
this.partRemainder = data.slice(length);
|
|
520
|
+
if (length > 0) {
|
|
521
|
+
this.backpressure = ! this.destStream.write(data.slice(0, length), this.partTransferEncoding);
|
|
522
|
+
}
|
|
480
523
|
} else {
|
|
481
524
|
this.backpressure = ! this.destStream.write(b);
|
|
482
525
|
}
|
|
@@ -486,8 +529,10 @@ Form.prototype.onParsePartEnd = function() {
|
|
|
486
529
|
if (this.destStream) {
|
|
487
530
|
flushWriteCbs(this);
|
|
488
531
|
var s = this.destStream;
|
|
532
|
+
var remainder = this.partRemainder;
|
|
533
|
+
var encoding = this.partTransferEncoding;
|
|
489
534
|
process.nextTick(function() {
|
|
490
|
-
s.end();
|
|
535
|
+
s.end(remainder, encoding);
|
|
491
536
|
});
|
|
492
537
|
}
|
|
493
538
|
clearPartVars(this);
|
|
@@ -742,15 +787,16 @@ function handleField(self, fieldStream) {
|
|
|
742
787
|
self.handleError(err);
|
|
743
788
|
});
|
|
744
789
|
fieldStream.on('readable', function() {
|
|
745
|
-
var buffer
|
|
746
|
-
|
|
790
|
+
var buffer;
|
|
791
|
+
while ((buffer = fieldStream.read()) !== null) {
|
|
792
|
+
self.totalFieldSize += buffer.length;
|
|
793
|
+
if (self.totalFieldSize > self.maxFieldsSize) {
|
|
794
|
+
self.handleError(createError(413, 'maxFieldsSize ' + self.maxFieldsSize + ' exceeded'));
|
|
795
|
+
return;
|
|
796
|
+
}
|
|
747
797
|
|
|
748
|
-
|
|
749
|
-
if (self.totalFieldSize > self.maxFieldsSize) {
|
|
750
|
-
self.handleError(createError(413, 'maxFieldsSize ' + self.maxFieldsSize + ' exceeded'));
|
|
751
|
-
return;
|
|
798
|
+
value += decoder.write(buffer);
|
|
752
799
|
}
|
|
753
|
-
value += decoder.write(buffer);
|
|
754
800
|
});
|
|
755
801
|
|
|
756
802
|
fieldStream.on('end', function() {
|
|
@@ -783,9 +829,11 @@ function hasListeners (emitter, type) {
|
|
|
783
829
|
|
|
784
830
|
function clearPartVars(self) {
|
|
785
831
|
self.partHeaders = {};
|
|
832
|
+
self.partHeadersSize = 0;
|
|
786
833
|
self.partName = null;
|
|
787
834
|
self.partFilename = null;
|
|
788
835
|
self.partTransferEncoding = 'binary';
|
|
836
|
+
self.partRemainder = '';
|
|
789
837
|
self.destStream = null;
|
|
790
838
|
|
|
791
839
|
self.headerFieldDecoder = new StringDecoder(self.encoding);
|
|
@@ -819,16 +867,16 @@ function setUpParser(self, boundary) {
|
|
|
819
867
|
|
|
820
868
|
function uploadPath(baseDir, filename) {
|
|
821
869
|
var ext = path.extname(filename).replace(FILE_EXT_RE, '$1');
|
|
822
|
-
var name =
|
|
870
|
+
var name = randomUid(18) + ext
|
|
823
871
|
return path.join(baseDir, name);
|
|
824
872
|
}
|
|
825
873
|
|
|
826
874
|
function parseFilename(headerValue) {
|
|
827
875
|
var m = FILENAME_PARAM_RE.exec(headerValue)
|
|
828
876
|
if (!m) {
|
|
829
|
-
m = headerValue.match(
|
|
877
|
+
m = headerValue.match(/;[ \t]*filename\*=utf-8''([^;]*)/i)
|
|
830
878
|
if (m) {
|
|
831
|
-
m[1] =
|
|
879
|
+
m[1] = tryDecode(m[1]);
|
|
832
880
|
} else {
|
|
833
881
|
return;
|
|
834
882
|
}
|
|
@@ -836,7 +884,7 @@ function parseFilename(headerValue) {
|
|
|
836
884
|
|
|
837
885
|
var filename = m[1] || m[2] || '';
|
|
838
886
|
filename = filename.replace(/%22|\\"/g, '"');
|
|
839
|
-
filename = filename.replace(/&#([
|
|
887
|
+
filename = filename.replace(/&#([0-9]{1,5});/g, function(m, code) {
|
|
840
888
|
return String.fromCharCode(code);
|
|
841
889
|
});
|
|
842
890
|
return filename.substr(filename.lastIndexOf('\\') + 1);
|
|
@@ -845,3 +893,11 @@ function parseFilename(headerValue) {
|
|
|
845
893
|
function lower(c) {
|
|
846
894
|
return c | 0x20;
|
|
847
895
|
}
|
|
896
|
+
|
|
897
|
+
function tryDecode(value) {
|
|
898
|
+
try {
|
|
899
|
+
return decodeURIComponent(value);
|
|
900
|
+
} catch (e) {
|
|
901
|
+
return undefined;
|
|
902
|
+
}
|
|
903
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@poppinss/multiparty",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.1",
|
|
4
4
|
"description": "multipart/form-data parser which supports streaming",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"contributors": [
|
|
@@ -16,15 +16,13 @@
|
|
|
16
16
|
"s3"
|
|
17
17
|
],
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"http-errors": "^2.0.0"
|
|
20
|
-
"safe-buffer": "5.2.1",
|
|
21
|
-
"uid-safe": "2.1.5"
|
|
19
|
+
"http-errors": "^2.0.0"
|
|
22
20
|
},
|
|
23
21
|
"devDependencies": {
|
|
24
22
|
"eslint": "^8.9.0",
|
|
25
23
|
"eslint-plugin-markdown": "2.2.1",
|
|
26
24
|
"mkdirp": "^1.0.4",
|
|
27
|
-
"mocha": "^
|
|
25
|
+
"mocha": "^10.8.2",
|
|
28
26
|
"nyc": "15.1.0",
|
|
29
27
|
"pend": "1.2.0",
|
|
30
28
|
"require-all": "3.0.0",
|
|
@@ -32,7 +30,6 @@
|
|
|
32
30
|
"superagent": "^7.1.1"
|
|
33
31
|
},
|
|
34
32
|
"files": [
|
|
35
|
-
"HISTORY.md",
|
|
36
33
|
"LICENSE",
|
|
37
34
|
"README.md",
|
|
38
35
|
"index.js"
|
package/HISTORY.md
DELETED
|
@@ -1,255 +0,0 @@
|
|
|
1
|
-
unreleased
|
|
2
|
-
==========
|
|
3
|
-
|
|
4
|
-
* Fix form parsing when no `part` event listener added
|
|
5
|
-
|
|
6
|
-
4.2.3 / 2022-01-20
|
|
7
|
-
==================
|
|
8
|
-
|
|
9
|
-
* Fix handling of unquoted values in `Content-Disposition`
|
|
10
|
-
* deps: http-errors@~1.8.1
|
|
11
|
-
- deps: toidentifier@1.0.1
|
|
12
|
-
|
|
13
|
-
4.2.2 / 2020-07-27
|
|
14
|
-
==================
|
|
15
|
-
|
|
16
|
-
* Fix empty files on Node.js 14.x
|
|
17
|
-
* Fix form emitting aborted error after close
|
|
18
|
-
* Replace `fd-slicer` module with internal transform stream
|
|
19
|
-
* deps: http-errors@~1.8.0
|
|
20
|
-
- Fix error creating objects in some environments
|
|
21
|
-
- deps: inherits@2.0.4
|
|
22
|
-
- deps: setprototypeof@1.2.0
|
|
23
|
-
* deps: safe-buffer@5.2.1
|
|
24
|
-
|
|
25
|
-
4.2.1 / 2018-08-12
|
|
26
|
-
==================
|
|
27
|
-
|
|
28
|
-
* Use `uid-safe` module to for temp file names
|
|
29
|
-
* deps: fd-slicer@1.1.0
|
|
30
|
-
* deps: http-errors@~1.7.0
|
|
31
|
-
|
|
32
|
-
4.2.0 / 2018-07-30
|
|
33
|
-
==================
|
|
34
|
-
|
|
35
|
-
* Use `http-errors` for raised errors
|
|
36
|
-
* Use `random-bytes` module for polyfill
|
|
37
|
-
* perf: remove parameter reassignment
|
|
38
|
-
|
|
39
|
-
4.1.4 / 2018-05-11
|
|
40
|
-
==================
|
|
41
|
-
|
|
42
|
-
* Fix file extension filtering stopping on certain whitespace characters
|
|
43
|
-
* Use `safe-buffer` for improved API safety
|
|
44
|
-
* perf: enable strict mode
|
|
45
|
-
|
|
46
|
-
4.1.3 / 2017-01-22
|
|
47
|
-
==================
|
|
48
|
-
|
|
49
|
-
* Use `os.tmpdir()` instead of `os.tmpDir()`
|
|
50
|
-
* deps: fd-slicer@1.0.1
|
|
51
|
-
|
|
52
|
-
4.1.2 / 2015-05-09
|
|
53
|
-
==================
|
|
54
|
-
|
|
55
|
-
* Do not emit error on part prior to emitting part
|
|
56
|
-
* Fix filename with quotes truncating from certain clients
|
|
57
|
-
|
|
58
|
-
4.1.1 / 2015-01-18
|
|
59
|
-
==================
|
|
60
|
-
|
|
61
|
-
* Do not clobber existing temporary files
|
|
62
|
-
|
|
63
|
-
4.1.0 / 2014-12-04
|
|
64
|
-
==================
|
|
65
|
-
|
|
66
|
-
* Add `statusCode` field to HTTP-related errors
|
|
67
|
-
* deps: fd-slicer@1.0.0
|
|
68
|
-
|
|
69
|
-
4.0.0 / 2014-10-14
|
|
70
|
-
==================
|
|
71
|
-
|
|
72
|
-
* `part` events for fields no longer fire if `autoFields` is on
|
|
73
|
-
* `part` events for files no longer fire if `autoFiles` is on
|
|
74
|
-
* `field`, `file`, and `part` events are guaranteed to emit in the
|
|
75
|
-
correct order - the order that the user places the parts in the
|
|
76
|
-
request. Each `part` `end` event is guaranteed to emit before the
|
|
77
|
-
next `part` event is emitted.
|
|
78
|
-
* Drop Node.js 0.8.x support
|
|
79
|
-
* Improve random temp file names
|
|
80
|
-
- Now using 18 bytes of randomness instead of 8.
|
|
81
|
-
* More robust `maxFilesSize` implementation
|
|
82
|
-
- Before it was possible for race conditions to cause more than
|
|
83
|
-
`maxFilesSize` bytes to get written to disk. That is now fixed.
|
|
84
|
-
* Now `part` objects emit `error` events
|
|
85
|
-
- This makes streaming work better since the part stream will emit
|
|
86
|
-
an error when it is no longer streaming.
|
|
87
|
-
* Remove support for generating the hash digest of a part
|
|
88
|
-
- If you want this, do it in your own code.
|
|
89
|
-
* Remove undocumented `ws` property from `file` objects
|
|
90
|
-
* Require the close boundary
|
|
91
|
-
- This makes multiparty more RFC-compliant and makes some invalid
|
|
92
|
-
requests which used to work, now emit an error instead.
|
|
93
|
-
|
|
94
|
-
3.3.2 / 2014-08-07
|
|
95
|
-
==================
|
|
96
|
-
|
|
97
|
-
* Do not invoke callback after close
|
|
98
|
-
* Share callback ending logic between error and close
|
|
99
|
-
|
|
100
|
-
3.3.1 / 2014-07-22
|
|
101
|
-
==================
|
|
102
|
-
|
|
103
|
-
* Remove problematic test fixtures
|
|
104
|
-
|
|
105
|
-
3.3.0 / 2014-07-03
|
|
106
|
-
==================
|
|
107
|
-
|
|
108
|
-
* Always emit close after all parts ended
|
|
109
|
-
|
|
110
|
-
3.2.10 / 2014-07-03
|
|
111
|
-
===================
|
|
112
|
-
|
|
113
|
-
* Fix callback hang in node.js 0.8 on errors
|
|
114
|
-
* Remove execute bit from files
|
|
115
|
-
|
|
116
|
-
3.2.9 / 2014-06-16
|
|
117
|
-
==================
|
|
118
|
-
|
|
119
|
-
* Fix attaching error listeners directly after form.parse
|
|
120
|
-
* Fix to not synchronously invoke callback to form.parse on error
|
|
121
|
-
|
|
122
|
-
3.2.8 / 2014-06-01
|
|
123
|
-
==================
|
|
124
|
-
|
|
125
|
-
* Fix developer accidentally corrupting data
|
|
126
|
-
* Fix handling epilogue in a separate chunk
|
|
127
|
-
* Fix initial check errors to use supplied callback
|
|
128
|
-
|
|
129
|
-
3.2.7 / 2014-05-26
|
|
130
|
-
==================
|
|
131
|
-
|
|
132
|
-
* Fix errors hanging responses in callback-style
|
|
133
|
-
|
|
134
|
-
3.2.6 / 2014-05-13
|
|
135
|
-
==================
|
|
136
|
-
|
|
137
|
-
* Fix `maxFields` to error on field after max
|
|
138
|
-
|
|
139
|
-
3.2.5 / 2014-05-11
|
|
140
|
-
==================
|
|
141
|
-
|
|
142
|
-
* Support boundary containing equal sign
|
|
143
|
-
|
|
144
|
-
3.2.4 / 2014-03-26
|
|
145
|
-
==================
|
|
146
|
-
|
|
147
|
-
* Keep `part.byteCount` undefined in chunked encoding
|
|
148
|
-
* Fix temp files not always cleaned up
|
|
149
|
-
|
|
150
|
-
3.2.3 / 2014-02-20
|
|
151
|
-
==================
|
|
152
|
-
|
|
153
|
-
* Improve parsing boundary attribute from `Content-Type`
|
|
154
|
-
|
|
155
|
-
3.2.2 / 2014-01-29
|
|
156
|
-
==================
|
|
157
|
-
|
|
158
|
-
* Fix error on empty payloads
|
|
159
|
-
|
|
160
|
-
3.2.1 / 2014-01-27
|
|
161
|
-
==================
|
|
162
|
-
|
|
163
|
-
* Fix `maxFilesSize` overcalculation bug
|
|
164
|
-
|
|
165
|
-
3.2.0 / 2014-01-17
|
|
166
|
-
==================
|
|
167
|
-
|
|
168
|
-
* Add `maxFilesSize` for `autoFiles`
|
|
169
|
-
|
|
170
|
-
3.1.2 / 2014-01-13
|
|
171
|
-
==================
|
|
172
|
-
|
|
173
|
-
* Fix incorrectly using `autoFields` value for `autoFiles`
|
|
174
|
-
|
|
175
|
-
3.1.1 / 2013-12-13
|
|
176
|
-
==================
|
|
177
|
-
|
|
178
|
-
* Fix not emitting `close` after all part `end` events
|
|
179
|
-
|
|
180
|
-
3.1.0 / 2013-11-10
|
|
181
|
-
==================
|
|
182
|
-
|
|
183
|
-
* Support UTF-8 filename in `Content-Disposition`
|
|
184
|
-
|
|
185
|
-
3.0.0 / 2013-10-25
|
|
186
|
-
==================
|
|
187
|
-
|
|
188
|
-
* `form.parse` callback API changed in a compatibility-breaking manner
|
|
189
|
-
|
|
190
|
-
2.2.0 / 2013-10-15
|
|
191
|
-
==================
|
|
192
|
-
|
|
193
|
-
* Add callback API to support multiple files with same field name
|
|
194
|
-
* Fix assertion crash when max field count is exceeded
|
|
195
|
-
* Fix assertion crash when client aborts an invalid request
|
|
196
|
-
* Fix assertion crash when `EMFILE` occurrs
|
|
197
|
-
* Switch from assertions to only `error` events
|
|
198
|
-
* Unpipe the request when an error occurs to save resources
|
|
199
|
-
* Update readable-stream to ~1.1.9
|
|
200
|
-
|
|
201
|
-
2.1.9 / 2013-10-06
|
|
202
|
-
==================
|
|
203
|
-
|
|
204
|
-
* relax `Content-Type` detection regex
|
|
205
|
-
|
|
206
|
-
2.1.8 / 2013-08-26
|
|
207
|
-
==================
|
|
208
|
-
|
|
209
|
-
* Replace deprecated `Buffer.write()`
|
|
210
|
-
|
|
211
|
-
2.1.7 / 2013-05-23
|
|
212
|
-
==================
|
|
213
|
-
|
|
214
|
-
* Add repository field to package.json
|
|
215
|
-
|
|
216
|
-
2.1.6 / 2013-04-30
|
|
217
|
-
==================
|
|
218
|
-
|
|
219
|
-
* Expose `hash` as an option to `Form`
|
|
220
|
-
|
|
221
|
-
2.1.5 / 2013-04-10
|
|
222
|
-
==================
|
|
223
|
-
|
|
224
|
-
* Fix possible `close` event before all temp files are done
|
|
225
|
-
|
|
226
|
-
2.1.4 / 2013-04-09
|
|
227
|
-
==================
|
|
228
|
-
|
|
229
|
-
* Fix crash for invalid requests
|
|
230
|
-
|
|
231
|
-
2.1.3 / 2013-04-09
|
|
232
|
-
==================
|
|
233
|
-
|
|
234
|
-
* Add `file.size`
|
|
235
|
-
|
|
236
|
-
2.1.2 / 2013-04-08
|
|
237
|
-
==================
|
|
238
|
-
|
|
239
|
-
* Add proper backpressure support
|
|
240
|
-
|
|
241
|
-
2.1.1 / 2013-04-05
|
|
242
|
-
==================
|
|
243
|
-
|
|
244
|
-
* Add `part.byteCount` and `part.byteOffset`
|
|
245
|
-
* Fix uploads larger than 2KB
|
|
246
|
-
|
|
247
|
-
2.1.0 / 2013-04-04
|
|
248
|
-
==================
|
|
249
|
-
|
|
250
|
-
* Complete rewrite. See README for changes and new API.
|
|
251
|
-
|
|
252
|
-
2.0.0 / 2013-04-02
|
|
253
|
-
==================
|
|
254
|
-
|
|
255
|
-
* Fork and rewrite from `formidable`
|