Skip to content

Commit

Permalink
Drop support for body being an Array when form: true
Browse files Browse the repository at this point in the history
`new URLSearchParams()` doesn't support this and it's a weird use-case. If you need support for this, just don't set `form: true` and handle stringifying yourself.
  • Loading branch information
sindresorhus committed Jul 5, 2018
1 parent 013e668 commit dfe5b1c
Show file tree
Hide file tree
Showing 4 changed files with 15 additions and 14 deletions.
16 changes: 9 additions & 7 deletions index.js
Expand Up @@ -6,7 +6,6 @@ const https = require('https');
const {PassThrough, Transform} = require('stream');
const urlLib = require('url');
const fs = require('fs');
const querystring = require('querystring');
const URLSearchParamsGlobal = typeof URLSearchParams === 'undefined' ? require('url').URLSearchParams : URLSearchParams; // TODO: Use the `URL` global when targeting Node.js 10
const extend = require('extend');
const CacheableRequest = require('cacheable-request');
Expand Down Expand Up @@ -580,18 +579,21 @@ function normalizeArguments(url, opts) {
throw new TypeError('The `body` option must be a stream.Readable, string or Buffer');
}

const canBodyBeStringified = is.plainObject(body) || is.array(body);
if ((opts.form || opts.json) && !canBodyBeStringified) {
throw new TypeError('The `body` option must be a plain Object or Array when the `form` or `json` option is used');
if (opts.json && !(is.plainObject(body) || is.array(body))) {
throw new TypeError('The `body` option must be a plain Object or Array when the `json` option is used');
}

if (opts.form && !is.plainObject(body)) {
throw new TypeError('The `body` option must be a plain Object when the `form` option is used');
}

if (isFormData(body)) {
// Special case for https://github.com/form-data/form-data
headers['content-type'] = headers['content-type'] || `multipart/form-data; boundary=${body.getBoundary()}`;
} else if (opts.form && canBodyBeStringified) {
} else if (opts.form && is.plainObject(body)) {
headers['content-type'] = headers['content-type'] || 'application/x-www-form-urlencoded';
opts.body = querystring.stringify(body);
} else if (opts.json && canBodyBeStringified) {
opts.body = (new URLSearchParamsGlobal(body)).toString();
} else if (opts.json && (is.plainObject(body) || is.array(body))) {
headers['content-type'] = headers['content-type'] || 'application/json';
opts.body = JSON.stringify(body);
}
Expand Down
2 changes: 1 addition & 1 deletion readme.md
Expand Up @@ -149,7 +149,7 @@ Default: `false`

If set to `true` and `Content-Type` header is not set, it will be set to `application/x-www-form-urlencoded`.

`body` must be a plain object or array and will be stringified.
`body` must be a plain object. It will be converted to a query string using [`(new URLSearchParams(object)).toString()`](https://nodejs.org/api/url.html#url_constructor_new_urlsearchparams_obj).

###### json

Expand Down
4 changes: 2 additions & 2 deletions test/error.js
Expand Up @@ -59,12 +59,12 @@ test('options.body error message', async t => {

test('options.body json error message', async t => {
const err = await t.throws(got(s.url, {body: Buffer.from('test'), json: true}));
t.regex(err.message, /The `body` option must be a plain Object or Array when the `form` or `json` option is used/);
t.regex(err.message, /The `body` option must be a plain Object or Array when the `json` option is used/);
});

test('options.body form error message', async t => {
const err = await t.throws(got(s.url, {body: Buffer.from('test'), form: true}));
t.regex(err.message, /The `body` option must be a plain Object or Array when the `form` or `json` option is used/);
t.regex(err.message, /The `body` option must be a plain Object when the `form` option is used/);
});

test('default status message', async t => {
Expand Down
7 changes: 3 additions & 4 deletions test/post.js
Expand Up @@ -53,12 +53,11 @@ test('sends plain objects as forms', async t => {
t.is(body, 'such=wow');
});

test('sends arrays as forms', async t => {
const {body} = await got(s.url, {
test('does NOT support sending arrays as forms', async t => {
await t.throws(got(s.url, {
body: ['such', 'wow'],
form: true
});
t.is(body, '0=such&1=wow');
}), TypeError);
});

test('sends plain objects as JSON', async t => {
Expand Down

0 comments on commit dfe5b1c

Please sign in to comment.