Skip to content

Commit 9060c91

Browse files
committed
Implement initial getLength
Doesn't deal with file streams yet
1 parent 7413d0b commit 9060c91

2 files changed

Lines changed: 109 additions & 21 deletions

File tree

lib/form_data.js

Lines changed: 58 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5,46 +5,73 @@ var mime = require('mime');
55

66
module.exports = FormData;
77
function FormData() {
8+
this._overheadLength = 0;
9+
this._valueLength = 0;
10+
811
CombinedStream.call(this);
912
}
1013
util.inherits(FormData, CombinedStream);
1114

15+
FormData.LINE_BREAK = '\r\n';
16+
1217
FormData.prototype.append = function(field, value) {
13-
var parentAppend = CombinedStream.prototype.append;
18+
var append = CombinedStream.prototype.append.bind(this);
19+
20+
var header = this._multiPartHeader(field, value);
21+
var footer = this._multiPartFooter(field, value);
1422

15-
parentAppend.call(this, this._multiPartHeader.bind(this, field, value));
16-
parentAppend.call(this, value);
17-
parentAppend.call(this, this._multiPartFooter.bind(this, field, value));
23+
append(header);
24+
append(value);
25+
append(footer);
26+
27+
this._trackLength(header, value)
1828
};
1929

20-
FormData.prototype._multiPartHeader = function(field, value, next) {
21-
var boundary = this.getBoundary();
30+
FormData.prototype._trackLength = function(header, value) {
31+
var valueLength = 0;
32+
if (Buffer.isBuffer(value)) {
33+
valueLength = value.length;
34+
} else if (typeof value === 'string') {
35+
valueLength = Buffer.byteLength(value);
36+
}
37+
38+
this._valueLength += valueLength;
39+
this._overheadLength +=
40+
Buffer.byteLength(header) +
41+
+ FormData.LINE_BREAK.length;
42+
};
2243

44+
FormData.prototype._multiPartHeader = function(field, value) {
45+
var boundary = this.getBoundary();
2346
var header =
24-
'--' + boundary
25-
+ '\r\n'
26-
+ 'Content-Disposition: form-data; name="' + field + '"';
47+
'--' + boundary + FormData.LINE_BREAK +
48+
'Content-Disposition: form-data; name="' + field + '"';
2749

2850
if (value.path) {
2951
header +=
30-
'; filename="' + path.basename(value.path) + '"\r\n'
31-
+ 'Content-Type: ' + mime.lookup(value.path);
52+
'; filename="' + path.basename(value.path) + '"' + FormData.LINE_BREAK +
53+
'Content-Type: ' + mime.lookup(value.path);
3254
}
3355

34-
header += '\r\n\r\n';
35-
36-
next(header);
56+
header += FormData.LINE_BREAK + FormData.LINE_BREAK;
57+
return header;
3758
};
3859

39-
FormData.prototype._multiPartFooter = function(field, value, next) {
40-
var footer = '\r\n';
60+
FormData.prototype._multiPartFooter = function(field, value) {
61+
return function(next) {
62+
var footer = FormData.LINE_BREAK;
4163

42-
var lastPart = (this._streams.length === 0);
43-
if (lastPart) {
44-
footer += '--' + this.getBoundary() + '--';
45-
}
64+
var lastPart = (this._streams.length === 0);
65+
if (lastPart) {
66+
footer += this._lastBoundary();
67+
}
4668

47-
next(footer);
69+
next(footer);
70+
}.bind(this);
71+
};
72+
73+
FormData.prototype._lastBoundary = function() {
74+
return '--' + this.getBoundary() + '--';
4875
};
4976

5077
FormData.prototype.getHeaders = function(userHeaders) {
@@ -77,3 +104,13 @@ FormData.prototype._generateBoundary = function() {
77104

78105
this._boundary = boundary;
79106
};
107+
108+
FormData.prototype.getLength = function(cb) {
109+
var knownLength = this._overheadLength + this._valueLength;
110+
111+
if (this._streams.length) {
112+
knownLength += this._lastBoundary().length;
113+
}
114+
115+
process.nextTick(cb.bind(this, null, knownLength));
116+
};
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
var common = require('../common');
2+
var assert = common.assert;
3+
var FormData = require(common.dir.lib + '/form_data');
4+
var fake = require('fake').create();
5+
6+
(function testEmptyForm() {
7+
var form = new FormData();
8+
var callback = fake.callback(arguments.callee.name + '-getLength');
9+
var calls = fake.expect(callback, [null, 0]).calls;
10+
11+
form.getLength(callback);
12+
13+
// Make sure our response is async
14+
assert.strictEqual(calls.length, 0);
15+
})();
16+
17+
(function testUtf8String() {
18+
var FIELD = 'my_field';
19+
var VALUE = 'May the € be with you';
20+
21+
var form = new FormData();
22+
form.append(FIELD, VALUE);
23+
var callback = fake.callback(arguments.callee.name + '-getLength');
24+
25+
var expectedLength =
26+
form._overheadLength +
27+
Buffer.byteLength(VALUE) +
28+
form._lastBoundary().length;
29+
30+
fake.expect(callback, [null, expectedLength]);
31+
form.getLength(callback);
32+
})();
33+
34+
(function testBuffer() {
35+
var FIELD = 'my_field';
36+
var VALUE = new Buffer(23);
37+
38+
var form = new FormData();
39+
form.append(FIELD, VALUE);
40+
var callback = fake.callback(arguments.callee.name + '-getLength');
41+
42+
var expectedLength =
43+
form._overheadLength +
44+
VALUE.length +
45+
form._lastBoundary().length;
46+
47+
fake.expect(callback, [null, expectedLength]);
48+
form.getLength(callback);
49+
})();
50+
51+

0 commit comments

Comments
 (0)