diff --git a/lib/client.js b/lib/client.js index 24417ec17..5dd132ded 100644 --- a/lib/client.js +++ b/lib/client.js @@ -877,7 +877,7 @@ Request.prototype.end = function(fn){ if (this._withCredentials) xhr.withCredentials = true; // body - if ('GET' != this.method && 'HEAD' != this.method && 'string' != typeof data && !this._isHost(data)) { + if (!this._formData && 'GET' != this.method && 'HEAD' != this.method && 'string' != typeof data && !this._isHost(data)) { // serialize stuff var contentType = this._header['content-type']; var serialize = this._serializer || request.serialize[contentType ? contentType.split(';')[0] : '']; diff --git a/lib/request-base.js b/lib/request-base.js index f053946d3..358bc541b 100644 --- a/lib/request-base.js +++ b/lib/request-base.js @@ -233,10 +233,20 @@ RequestBase.prototype.field = function(name, val) { return this; } + if (Array.isArray(val)) { + for (var i in val) { + this.field(name, val[i]); + } + return this; + } + // val should be defined now if (null === val || undefined === val) { throw new Error('.field(name, val) val can not be empty'); } + if ('boolean' === typeof val) { + val = '' + val; + } this._getFormData().append(name, val); return this; }; diff --git a/package.json b/package.json index 764cc7873..390309226 100644 --- a/package.json +++ b/package.json @@ -45,6 +45,7 @@ "express-session": "^1.13.0", "marked": "^0.3.5", "mocha": "^3.1.2", + "multer": "^1.2.0", "should": "^11.1.1", "should-http": "^0.0.4", "zuul": "^3.11.1" diff --git a/test/form.js b/test/form.js index 5db150e7e..be17e39f1 100644 --- a/test/form.js +++ b/test/form.js @@ -3,6 +3,11 @@ var base = setup.uri; var should = require('should'); var request = require('../'); +var assert = require('assert'); +if (!assert.deepStrictEqual) assert.deepStrictEqual = assert.deepEqual; + +var formDataSupported = setup.NODE || 'undefined' !== FormData; + describe('req.send(Object) as "form"', function(){ describe('with req.type() set to form', function(){ it('should send x-www-form-urlencoded data', function(done){ @@ -35,6 +40,67 @@ describe('req.send(Object) as "form"', function(){ }) describe('req.field', function(){ + it('allow bools', function(done){ + if (!formDataSupported) { + return done(); + } + + request + .post(base + '/formecho') + .field('bools', true) + .field('strings', 'true') + .end(function(err, res){ + assert.ifError(err); + assert.deepStrictEqual(res.body, {bools:'true', strings:'true'}); + done(); + }); + }); + + it('allow objects', function(done){ + if (!formDataSupported) { + return done(); + } + + request + .post(base + '/formecho') + .field({bools: true, strings: 'true'}) + .end(function(err, res){ + assert.ifError(err); + assert.deepStrictEqual(res.body, {bools:'true', strings:'true'}); + done(); + }); + }); + + it('works with arrays in objects', function(done){ + if (!formDataSupported) { + return done(); + } + + request + .post(base + '/formecho') + .field({numbers: [1,2,3]}) + .end(function(err, res){ + assert.ifError(err); + assert.deepStrictEqual(res.body, {numbers:['1','2','3']}); + done(); + }); + }); + + it('works with arrays', function(done){ + if (!formDataSupported) { + return done(); + } + + request + .post(base + '/formecho') + .field('letters', ['a', 'b', 'c']) + .end(function(err, res){ + assert.ifError(err); + assert.deepStrictEqual(res.body, {letters: ['a', 'b', 'c']}); + done(); + }); + }); + it('throw when empty', function(){ should.throws(function(){ request @@ -48,4 +114,4 @@ describe('req.field', function(){ .field('name') }, /val/); }); -}); \ No newline at end of file +}); diff --git a/test/support/server.js b/test/support/server.js index d77424211..6d8a21564 100644 --- a/test/support/server.js +++ b/test/support/server.js @@ -1,4 +1,5 @@ var express = require('express'); +var multer = require('multer'); var bodyParser = require('body-parser'); var cookieParser = require('cookie-parser'); var basicAuth = require('basic-auth-connect'); @@ -25,6 +26,15 @@ app.all('/unique', function(req, res){ }); app.use(bodyParser.urlencoded({ extended: true })); +app.use(multer().none()); + +app.all('/formecho', function(req, res){ + if (!/application\/x-www-form-urlencoded|multipart\/form-data/.test(req.headers['content-type'])) { + return res.status(400).end("wrong type"); + } + res.json(req.body); +}); + app.use(bodyParser.json()); app.use(cookieParser());