Skip to content

Commit

Permalink
Use responseType instead of options.encoding to get a Buffer (#940)
Browse files Browse the repository at this point in the history
Co-authored-by: Sindre Sorhus <sindresorhus@gmail.com>
  • Loading branch information
szmarczak and sindresorhus committed Nov 24, 2019
1 parent 3acdb69 commit 6cc3d9f
Show file tree
Hide file tree
Showing 8 changed files with 38 additions and 19 deletions.
20 changes: 13 additions & 7 deletions readme.md
Expand Up @@ -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
Expand Down Expand Up @@ -297,10 +301,12 @@ Ignore invalid cookies instead of throwing an error. Only useful when the `cooki

###### encoding

Type: `string | null`<br>
Type: `string`<br>
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

Expand Down
4 changes: 1 addition & 3 deletions source/as-promise.ts
Expand Up @@ -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;
Expand Down
5 changes: 4 additions & 1 deletion source/get-response.ts
Expand Up @@ -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);
Expand Down
5 changes: 5 additions & 0 deletions source/normalize-arguments.ts
Expand Up @@ -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;
};

Expand Down
2 changes: 1 addition & 1 deletion source/utils/types.ts
Expand Up @@ -131,7 +131,7 @@ export interface Options extends URLOptions {
hooks?: Partial<Hooks>;
decompress?: boolean;
isStream?: boolean;
encoding?: BufferEncoding | null;
encoding?: BufferEncoding;
method?: Method;
retry?: number | RetryOptions;
throwHttpErrors?: boolean;
Expand Down
6 changes: 6 additions & 0 deletions test/arguments.ts
Expand Up @@ -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');
});
11 changes: 6 additions & 5 deletions 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';
Expand Down Expand Up @@ -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) => {
Expand Down
4 changes: 2 additions & 2 deletions test/progress.ts
Expand Up @@ -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);
Expand All @@ -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);
Expand Down

0 comments on commit 6cc3d9f

Please sign in to comment.