Skip to content

Commit a3e191d

Browse files
committed
Handle custom stream
1 parent 0170178 commit a3e191d

File tree

4 files changed

+131
-4
lines changed

4 files changed

+131
-4
lines changed

lib/form_data.js

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ var http = require('http');
55
var https = require('https');
66
var parseUrl = require('url').parse;
77
var fs = require('fs');
8+
var Stream = require('stream').Stream;
89
var mime = require('mime-types');
910
var asynckit = require('asynckit');
1011
var populate = require('./populate.js');
@@ -100,8 +101,8 @@ FormData.prototype._trackLength = function(header, value, options) {
100101
Buffer.byteLength(header) +
101102
FormData.LINE_BREAK.length;
102103

103-
// empty or either doesn't have path or not an http response
104-
if (!value || ( !value.path && !(value.readable && value.hasOwnProperty('httpVersion')) )) {
104+
// empty or either doesn't have path or not an http response or not a stream
105+
if (!value || ( !value.path && !(value.readable && value.hasOwnProperty('httpVersion')) && !(value instanceof Stream))) {
105106
return;
106107
}
107108

@@ -426,13 +427,15 @@ FormData.prototype.submit = function(params, cb) {
426427

427428
// get content length and fire away
428429
this.getLength(function(err, length) {
429-
if (err) {
430+
if (err && err !== 'Unknown stream') {
430431
this._error(err);
431432
return;
432433
}
433434

434435
// add content length
435-
request.setHeader('Content-Length', length);
436+
if (length) {
437+
request.setHeader('Content-Length', length);
438+
}
436439

437440
this.pipe(request);
438441
if (cb) {

test/integration/test-form-get-length-sync.js

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ var common = require('../common');
22
var assert = common.assert;
33
var FormData = require(common.dir.lib + '/form_data');
44
var fs = require('fs');
5+
var Readable = require('stream').Readable;
56

67
(function testGetLengthSync() {
78
var fields = [
@@ -73,3 +74,34 @@ var fs = require('fs');
7374

7475
assert.equal(expectedLength, calculatedLength);
7576
})();
77+
78+
(function testReadableStreamData() {
79+
var form = new FormData();
80+
81+
var util = require('util');
82+
util.inherits(CustomReadable, Readable);
83+
84+
/**
85+
* Custion readable constructor
86+
* @param {Object} opt options
87+
* @constructor
88+
*/
89+
function CustomReadable(opt) {
90+
Readable.call(this, opt);
91+
this._max = 2;
92+
this._index = 1;
93+
}
94+
95+
CustomReadable.prototype._read = function() {
96+
var i = this._index++;
97+
if (i > this._max) {
98+
this.push(null);
99+
} else {
100+
this.push('' + i);
101+
}
102+
};
103+
form.append('my_txt', new CustomReadable());
104+
105+
assert.throws(function() { form.getLengthSync(); }, /Cannot calculate proper length in synchronous way/);
106+
107+
})();

test/integration/test-form-get-length.js

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ var assert = common.assert;
33
var FormData = require(common.dir.lib + '/form_data');
44
var fake = require('fake').create();
55
var fs = require('fs');
6+
var Readable = require('stream').Readable;
67

78
(function testEmptyForm() {
89
var form = new FormData();
@@ -89,3 +90,40 @@ var fs = require('fs');
8990
fake.expectAnytime(callback, [null, expectedLength]);
9091
form.getLength(callback);
9192
})();
93+
94+
(function testReadableStreamData() {
95+
var form = new FormData();
96+
// var expectedLength = 0;
97+
98+
var util = require('util');
99+
util.inherits(CustomReadable, Readable);
100+
101+
/**
102+
* Custion readable constructor
103+
* @param {Object} opt options
104+
* @constructor
105+
*/
106+
function CustomReadable(opt) {
107+
Readable.call(this, opt);
108+
this._max = 2;
109+
this._index = 1;
110+
}
111+
112+
CustomReadable.prototype._read = function() {
113+
var i = this._index++;
114+
if (i > this._max) {
115+
this.push(null);
116+
} else {
117+
this.push('' + i);
118+
}
119+
};
120+
form.append('my_txt', new CustomReadable());
121+
122+
// expectedLength += form._overheadLength + form._lastBoundary().length;
123+
124+
// there is no way to determine the length of this readable stream.
125+
var callback = fake.callback(arguments.callee.name + '-getLength');
126+
fake.expectAnytime(callback, ['Unknown stream', undefined]);
127+
form.getLength(function(err, len) { callback(err,len); });
128+
129+
})();
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
var common = require('../common');
2+
var assert = common.assert;
3+
var http = require('http');
4+
var FormData = require(common.dir.lib + '/form_data');
5+
var Readable = require('stream').Readable;
6+
7+
var server = http.createServer(function(req, res) {
8+
assert.strictEqual(req.headers['Content-Length'], undefined);
9+
res.writeHead(200);
10+
res.end('done');
11+
});
12+
13+
server.listen(common.port, function() {
14+
var form = new FormData();
15+
16+
var util = require('util');
17+
util.inherits(CustomReadable, Readable);
18+
19+
/**
20+
* Custion readable constructor
21+
* @param {Object} opt options
22+
* @constructor
23+
*/
24+
function CustomReadable(opt) {
25+
Readable.call(this, opt);
26+
this._max = 2;
27+
this._index = 1;
28+
}
29+
30+
CustomReadable.prototype._read = function() {
31+
var i = this._index++;
32+
// console.error('send back read data');
33+
if (i > this._max) {
34+
this.push(null);
35+
} else {
36+
this.push('' + i);
37+
}
38+
};
39+
form.append('readable', new CustomReadable());
40+
41+
form.submit('http://localhost:' + common.port + '/', function(err, res) {
42+
if (err) {
43+
throw err;
44+
}
45+
46+
assert.strictEqual(res.statusCode, 200);
47+
48+
// unstuck new streams
49+
res.resume();
50+
51+
server.close();
52+
});
53+
54+
});

0 commit comments

Comments
 (0)