From dfe5b1cfd762d4ccf4bf53ef2c1c0b31500baa30 Mon Sep 17 00:00:00 2001 From: Sindre Sorhus Date: Thu, 5 Jul 2018 23:15:57 +0700 Subject: [PATCH] Drop support for `body` being an Array when `form: true` `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. --- index.js | 16 +++++++++------- readme.md | 2 +- test/error.js | 4 ++-- test/post.js | 7 +++---- 4 files changed, 15 insertions(+), 14 deletions(-) diff --git a/index.js b/index.js index 1765b4298..192ec5a87 100644 --- a/index.js +++ b/index.js @@ -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'); @@ -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); } diff --git a/readme.md b/readme.md index c190f8607..69ebc0b68 100644 --- a/readme.md +++ b/readme.md @@ -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 diff --git a/test/error.js b/test/error.js index d76072343..ddb6bb40a 100644 --- a/test/error.js +++ b/test/error.js @@ -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 => { diff --git a/test/post.js b/test/post.js index ac6028c1e..679f57a2b 100644 --- a/test/post.js +++ b/test/post.js @@ -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 => {