Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Custom params for form.submit() should cover most edge cases. #22

Merged
merged 2 commits into from

1 participant

@alexindigo
Collaborator
  • Made tests more stable by calling fs.createReadStream within same tick of form.append().
@alexindigo alexindigo merged commit 5277bb3 into from
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
View
13 Readme.md
@@ -102,4 +102,17 @@ form.submit('http://example.com/', function(err, res) {
});
```
+For edge cases, like POST request to URL with query string or to pass HTTP auth creadentials, object can be passed to `form.submit()` as first parameter:
+
+``` javascript
+form.submit({
+ host: 'example.com',
+ path: '/probably.php?extra=params',
+ auth: 'username:password'
+}, function(err, res) {
+ console.log(res.statusCode);
+});
+```
+
+
[xhr2-fd]: http://dev.w3.org/2006/webapi/XMLHttpRequest-2/Overview.html#the-formdata-interface
View
54 lib/form_data.js
@@ -41,7 +41,7 @@ FormData.prototype.append = function(field, value, options) {
FormData.prototype._trackLength = function(header, value, options) {
var valueLength = 0;
-
+
// used w/ trackLengthSync(), when length is known.
// e.g. for streaming directly from a remote server,
// w/ a known file a size, and not wanting to wait for
@@ -232,21 +232,37 @@ FormData.prototype.getLength = function(cb) {
});
};
-FormData.prototype.submit = function(url, cb) {
+FormData.prototype.submit = function(params, cb) {
this.getLength(function(err, length) {
+
var request
- , parsedUrl = parseUrl(url)
- , options = {
- method: 'post',
- port: parsedUrl.port || 80,
- path: parsedUrl.pathname,
- headers: this.getHeaders({'Content-Length': length}),
- host: parsedUrl.hostname
- };
-
- if (parsedUrl.protocol == 'https:') {
+ , options
+ , defaults = {
+ method : 'post',
+ port : 80,
+ headers: this.getHeaders({'Content-Length': length})
+ };
+
+ // parse provided url if it's string
+ // or treat it as options object
+ if (typeof params == 'string') {
+ params = parseUrl(params);
+
+ options = populate({
+ port: params.port,
+ path: params.pathname,
+ host: params.hostname
+ }, defaults);
+ }
+ else // use custom params
+ {
+ options = populate(params, defaults);
+ }
+
+ // https if specified, fallback to http in any other case
+ if (params.protocol == 'https:') {
// override default port
- if (!parsedUrl.port) options.port = 443;
+ if (!params.port) options.port = 443;
request = https.request(options);
} else {
request = http.request(options);
@@ -261,3 +277,15 @@ FormData.prototype.submit = function(url, cb) {
return request;
}.bind(this));
};
+
+/*
+ * Santa's little helpers
+ */
+
+// populates missing values
+function populate(dst, src) {
+ for (var prop in src) {
+ if (!dst[prop]) dst[prop] = src[prop];
+ }
+ return dst;
+}
View
2  package.json
@@ -2,7 +2,7 @@
"author": "Felix Geisendörfer <felix@debuggable.com> (http://debuggable.com/)",
"name": "form-data",
"description": "A module to create readable `\"multipart/form-data\"` streams. Can be used to submit forms and file uploads to other web applications.",
- "version": "0.0.5",
+ "version": "0.0.6",
"repository": {
"type": "git",
"url": "git://github.com/felixge/node-form-data.git"
View
17 test/integration/test-pipe.js
@@ -10,16 +10,20 @@ var IncomingForm = require('formidable').IncomingForm;
var remoteFile = 'http://nodejs.org/images/logo.png';
+// wrap non simple values into function
+// just to deal with ReadStream "autostart"
+// Can't wait for 0.10
var FIELDS = [
{name: 'my_field', value: 'my_value'},
- {name: 'my_buffer', value: new Buffer([1, 2, 3])},
- {name: 'my_file', value: fs.createReadStream(common.dir.fixture + '/unicycle.jpg')},
- {name: 'remote_file', value: request(remoteFile) }
+ {name: 'my_buffer', value: function(){ return new Buffer([1, 2, 3])} },
+ {name: 'my_file', value: function(){ return fs.createReadStream(common.dir.fixture + '/unicycle.jpg')} },
+ {name: 'remote_file', value: function(){ return request(remoteFile)} }
];
var server = http.createServer(function(req, res) {
- // formidable is broken so let's do it manual way
+ // formidable is fixed on github
+ // but still 7 month old in npm
//
// var form = new IncomingForm();
// form.uploadDir = common.dir.tmp;
@@ -66,6 +70,7 @@ var server = http.createServer(function(req, res) {
var field = FIELDS.shift();
assert.ok( data.indexOf('form-data; name="'+field.name+'"') != -1 );
assert.ok( data.indexOf('; filename="'+path.basename(field.value.path)+'"') != -1 );
+
// check for unicycle.jpg traces
assert.ok( data.indexOf('2005:06:21 01:44:12') != -1 );
assert.ok( data.indexOf('Content-Type: '+mime.lookup(field.value.path) ) != -1 );
@@ -89,6 +94,10 @@ var server = http.createServer(function(req, res) {
server.listen(common.port, function() {
var form = new FormData();
FIELDS.forEach(function(field) {
+ // important to append ReadStreams within the same tick
+ if ((typeof field.value == 'function')) {
+ field.value = field.value();
+ }
form.append(field.name, field.value);
});
View
121 test/integration/test-submit-custom.js
@@ -0,0 +1,121 @@
+var common = require('../common');
+var assert = common.assert;
+var http = require('http');
+var path = require('path');
+var mime = require('mime');
+var request = require('request');
+var fs = require('fs');
+var FormData = require(common.dir.lib + '/form_data');
+var IncomingForm = require('formidable').IncomingForm;
+
+var remoteFile = 'http://nodejs.org/images/logo.png';
+
+// wrap non simple values into function
+// just to deal with ReadStream "autostart"
+// Can't wait for 0.10
+var FIELDS = [
+ {name: 'my_field', value: 'my_value'},
+ {name: 'my_buffer', value: function(){ return new Buffer([1, 2, 3])} },
+ {name: 'my_file', value: function(){ return fs.createReadStream(common.dir.fixture + '/unicycle.jpg')} },
+ {name: 'remote_file', value: function(){ return request(remoteFile)} }
+];
+
+var server = http.createServer(function(req, res) {
+
+ // formidable is fixed on github
+ // but still 7 month old in npm
+ //
+ // var form = new IncomingForm();
+ // form.uploadDir = common.dir.tmp;
+ // form.parse(req);
+ // form
+ // .on('field', function(name, value) {
+ // var field = FIELDS.shift();
+ // assert.strictEqual(name, field.name);
+ // assert.strictEqual(value, field.value+'');
+ // })
+ // .on('file', function(name, file) {
+ // var field = FIELDS.shift();
+ // assert.strictEqual(name, field.name);
+ // assert.strictEqual(file.name, path.basename(field.value.path));
+ // // mime.lookup file.NAME == 'my_file' ?
+ // assert.strictEqual(file.type, mime.lookup(file.name));
+ // })
+ // .on('end', function() {
+ // res.writeHead(200);
+ // res.end('done');
+ // });
+
+ // temp workaround
+ var data = '';
+ req.setEncoding('utf8');
+ req.on('data', function(d) {
+ data += d;
+ });
+ req.on('end', function() {
+ // check for the fields' traces
+
+ // 1st field : my_field
+ var field = FIELDS.shift();
+ assert.ok( data.indexOf('form-data; name="'+field.name+'"') != -1 );
+ assert.ok( data.indexOf(field.value) != -1 );
+
+ // 2nd field : my_buffer
+ var field = FIELDS.shift();
+ assert.ok( data.indexOf('form-data; name="'+field.name+'"') != -1 );
+ assert.ok( data.indexOf(field.value) != -1 );
+
+ // 3rd field : my_file
+ var field = FIELDS.shift();
+ assert.ok( data.indexOf('form-data; name="'+field.name+'"') != -1 );
+ assert.ok( data.indexOf('; filename="'+path.basename(field.value.path)+'"') != -1 );
+ // check for unicycle.jpg traces
+ assert.ok( data.indexOf('2005:06:21 01:44:12') != -1 );
+ assert.ok( data.indexOf('Content-Type: '+mime.lookup(field.value.path) ) != -1 );
+
+ // 4th field : remote_file
+ var field = FIELDS.shift();
+ assert.ok( data.indexOf('form-data; name="'+field.name+'"') != -1 );
+ assert.ok( data.indexOf('; filename="'+path.basename(field.value.path)+'"') != -1 );
+ // check for http://nodejs.org/images/logo.png traces
+ assert.ok( data.indexOf('ImageReady') != -1 );
+ assert.ok( data.indexOf('Content-Type: '+mime.lookup(remoteFile) ) != -1 );
+
+ res.writeHead(200);
+ res.end('done');
+
+ });
+
+});
+
+server.listen(common.port, function() {
+
+ var form = new FormData();
+
+ FIELDS.forEach(function(field) {
+ // important to append ReadStreams within the same tick
+ if ((typeof field.value == 'function')) {
+ field.value = field.value();
+ }
+ form.append(field.name, field.value);
+ });
+
+ // custom params object passed to submit
+ form.submit({
+ port: common.port,
+ path: '/'
+ }, function(err, res) {
+
+ if (err) {
+ throw err;
+ }
+
+ assert.strictEqual(res.statusCode, 200);
+ server.close();
+ });
+
+});
+
+process.on('exit', function() {
+ assert.strictEqual(FIELDS.length, 0);
+});
View
18 test/integration/test-submit.js
@@ -10,16 +10,20 @@ var IncomingForm = require('formidable').IncomingForm;
var remoteFile = 'http://nodejs.org/images/logo.png';
+// wrap non simple values into function
+// just to deal with ReadStream "autostart"
+// Can't wait for 0.10
var FIELDS = [
{name: 'my_field', value: 'my_value'},
- {name: 'my_buffer', value: new Buffer([1, 2, 3])},
- {name: 'my_file', value: fs.createReadStream(common.dir.fixture + '/unicycle.jpg') },
- {name: 'remote_file', value: request(remoteFile) }
+ {name: 'my_buffer', value: function(){ return new Buffer([1, 2, 3])} },
+ {name: 'my_file', value: function(){ return fs.createReadStream(common.dir.fixture + '/unicycle.jpg')} },
+ {name: 'remote_file', value: function(){ return request(remoteFile)} }
];
var server = http.createServer(function(req, res) {
- // formidable is broken so let's do it manual way
+ // formidable is fixed on github
+ // but still 7 month old in npm
//
// var form = new IncomingForm();
// form.uploadDir = common.dir.tmp;
@@ -85,8 +89,14 @@ var server = http.createServer(function(req, res) {
});
server.listen(common.port, function() {
+
var form = new FormData();
+
FIELDS.forEach(function(field) {
+ // important to append ReadStreams within the same tick
+ if ((typeof field.value == 'function')) {
+ field.value = field.value();
+ }
form.append(field.name, field.value);
});
Something went wrong with that request. Please try again.