From 6cc3d9f3027f28ce4dcbe8605d104e65f7e66787 Mon Sep 17 00:00:00 2001 From: Szymon Marczak <36894700+szmarczak@users.noreply.github.com> Date: Sun, 24 Nov 2019 03:44:16 +0100 Subject: [PATCH] Use `responseType` instead of `options.encoding` to get a Buffer (#940) Co-authored-by: Sindre Sorhus --- readme.md | 20 +++++++++++++------- source/as-promise.ts | 4 +--- source/get-response.ts | 5 ++++- source/normalize-arguments.ts | 5 +++++ source/utils/types.ts | 2 +- test/arguments.ts | 6 ++++++ test/http.ts | 11 ++++++----- test/progress.ts | 4 ++-- 8 files changed, 38 insertions(+), 19 deletions(-) diff --git a/readme.md b/readme.md index 02808b7de..bd3028c0a 100644 --- a/readme.md +++ b/readme.md @@ -248,17 +248,21 @@ Default: `'default'` Parsing method used to retrieve the body from the response. -- `'default'` - if `options.encoding` is `null`, the body will be a Buffer. Otherwise it will be a string unless it's overwritten in a `afterResponse` hook, -- `'text'` - will always give a string, no matter what's the `options.encoding` or if the body is a custom object, -- `'json'` - will always give an object, unless it's invalid JSON - then it will throw. -- `'buffer'` - will always give a Buffer, no matter what's the `options.encoding`. It will throw if the body is a custom object. +- `'default'` - Will give a string unless the body is overwritten in a `afterResponse` hook or if `options.decompress` is set to false - Will give a Buffer if the response is compresssed. +- `'text'` - Will give a string no matter what. +- `'json'` - Will give an object, unless the body is invalid JSON, then it will throw. +- `'buffer'` - Will give a Buffer, ignoring `options.encoding`. It will throw if the body is a custom object. -The promise has `.json()` and `.buffer()` and `.text()` functions which set this option automatically. +The promise has `.json()` and `.buffer()` and `.text()` methods which set this option automatically. Example: ```js +// This const body = await got(url).json(); + +// is the same as this +const body = await got(url, {responseType: 'json'}); ``` ###### resolveBodyOnly @@ -297,10 +301,12 @@ Ignore invalid cookies instead of throwing an error. Only useful when the `cooki ###### encoding -Type: `string | null`
+Type: `string`
Default: `'utf8'` -[Encoding](https://nodejs.org/api/buffer.html#buffer_buffers_and_character_encodings) to be used on `setEncoding` of the response data. If `null`, the body is returned as a [`Buffer`](https://nodejs.org/api/buffer.html) (binary data). +[Encoding](https://nodejs.org/api/buffer.html#buffer_buffers_and_character_encodings) to be used on `setEncoding` of the response data. + +To get a [`Buffer`](https://nodejs.org/api/buffer.html), you need to set [`responseType`](#responseType) to `buffer` instead. ###### form diff --git a/source/as-promise.ts b/source/as-promise.ts index df4d9a122..97fa9b5ba 100644 --- a/source/as-promise.ts +++ b/source/as-promise.ts @@ -53,10 +53,8 @@ export default function asPromise(options: NormalizedOptions) { emitter.on('response', async (response: Response) => { proxy.emit('response', response); - const streamAsPromise = is.null_(options.encoding) ? getStream.buffer(response) : getStream(response, {encoding: options.encoding}); - try { - response.body = await streamAsPromise; + response.body = await getStream(response, {encoding: options.encoding}); } catch (error) { emitError(new ReadError(error, options)); return; diff --git a/source/get-response.ts b/source/get-response.ts index ee4561537..d17fdeac9 100644 --- a/source/get-response.ts +++ b/source/get-response.ts @@ -21,7 +21,10 @@ export default async (response: IncomingMessage, options: NormalizedOptions, emi ) as Response; if (!options.decompress && ['gzip', 'deflate', 'br'].includes(response.headers['content-encoding'] ?? '')) { - options.encoding = null; + options.responseType = 'default'; + + // @ts-ignore Internal use. + options.encoding = 'buffer'; } emitter.emit('response', newResponse); diff --git a/source/normalize-arguments.ts b/source/normalize-arguments.ts index 4b99a945c..74ad8accb 100644 --- a/source/normalize-arguments.ts +++ b/source/normalize-arguments.ts @@ -164,6 +164,11 @@ export const preNormalizeArguments = (options: Options, defaults?: NormalizedOpt options.cookieJar = {setCookie, getCookieString}; } + // `options.encoding` + if (is.null_(options.encoding)) { + throw new TypeError('To get a Buffer, set `options.responseType` to `buffer` instead'); + } + return options as NormalizedOptions; }; diff --git a/source/utils/types.ts b/source/utils/types.ts index 571ab45d2..b279ffeed 100644 --- a/source/utils/types.ts +++ b/source/utils/types.ts @@ -131,7 +131,7 @@ export interface Options extends URLOptions { hooks?: Partial; decompress?: boolean; isStream?: boolean; - encoding?: BufferEncoding | null; + encoding?: BufferEncoding; method?: Method; retry?: number | RetryOptions; throwHttpErrors?: boolean; diff --git a/test/arguments.ts b/test/arguments.ts index df3ea31e7..ac36b5571 100644 --- a/test/arguments.ts +++ b/test/arguments.ts @@ -336,3 +336,9 @@ test('`context` option is accessible when extending instances', t => { t.is(instance.defaults.options.context, context); t.false({}.propertyIsEnumerable.call(instance.defaults.options, 'context')); }); + +test('throws if `options.encoding` is `null`', async t => { + await t.throwsAsync(got('https://example.com', { + encoding: null + }), 'To get a Buffer, set `options.responseType` to `buffer` instead'); +}); diff --git a/test/http.ts b/test/http.ts index f13cd6e7a..076ad894b 100644 --- a/test/http.ts +++ b/test/http.ts @@ -1,4 +1,3 @@ -import is from '@sindresorhus/is'; import test from 'ava'; import got from '../source'; import withServer from './helpers/with-server'; @@ -72,13 +71,15 @@ test('invalid protocol throws', async t => { }); }); -test('gives buffer if `options.encoding` is null', withServer, async (t, server, got) => { +test('custom `options.encoding`', withServer, async (t, server, got) => { + const string = 'ok'; + server.get('/', (_request, response) => { - response.end('ok'); + response.end(string); }); - const data = (await got({encoding: null})).body; - t.true(is.buffer(data)); + const data = (await got({encoding: 'base64'})).body; + t.is(data, Buffer.from(string).toString('base64')); }); test('`searchParams` option', withServer, async (t, server, got) => { diff --git a/test/progress.ts b/test/progress.ts index c08b7e74d..2b9ed68fc 100644 --- a/test/progress.ts +++ b/test/progress.ts @@ -71,7 +71,7 @@ test('download progress', withServer, async (t, server, got) => { const events = []; - const {body} = await got({encoding: null}) + const {body} = await got({responseType: 'buffer'}) .on('downloadProgress', event => events.push(event)); checkEvents(t, events, body.length); @@ -92,7 +92,7 @@ test('download progress - stream', withServer, async (t, server, got) => { const events = []; - const stream = got.stream({encoding: null}) + const stream = got.stream({responseType: 'buffer'}) .on('downloadProgress', event => events.push(event)); await getStream(stream);