got 11.6.0 → 11.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -133,9 +133,10 @@ function asPromise(normalizedOptions) {
133
133
  reject(error);
134
134
  };
135
135
  request.once('error', onError);
136
+ const previousBody = request.options.body;
136
137
  request.once('retry', (newRetryCount, error) => {
137
- var _a;
138
- if (is_1.default.nodeStream((_a = error.request) === null || _a === void 0 ? void 0 : _a.options.body)) {
138
+ var _a, _b;
139
+ if (previousBody === ((_a = error.request) === null || _a === void 0 ? void 0 : _a.options.body) && is_1.default.nodeStream((_b = error.request) === null || _b === void 0 ? void 0 : _b.options.body)) {
139
140
  onError(error);
140
141
  return;
141
142
  }
@@ -11,7 +11,7 @@ const parseBody = (response, responseType, parseJson, encoding) => {
11
11
  return rawBody.length === 0 ? '' : parseJson(rawBody.toString());
12
12
  }
13
13
  if (responseType === 'buffer') {
14
- return Buffer.from(rawBody);
14
+ return rawBody;
15
15
  }
16
16
  throw new types_1.ParseError({
17
17
  message: `Unknown body type '${responseType}'`,
@@ -41,12 +41,8 @@ export interface Agents {
41
41
  }
42
42
  export declare const withoutBody: ReadonlySet<string>;
43
43
  export interface ToughCookieJar {
44
- getCookieString: ((currentUrl: string, options: {
45
- [key: string]: unknown;
46
- }, cb: (err: Error | null, cookies: string) => void) => void) & ((url: string, callback: (error: Error | null, cookieHeader: string) => void) => void);
47
- setCookie: ((cookieOrString: unknown, currentUrl: string, options: {
48
- [key: string]: unknown;
49
- }, cb: (err: Error | null, cookie: unknown) => void) => void) & ((rawCookie: string, url: string, callback: (error: Error | null, result: unknown) => void) => void);
44
+ getCookieString: ((currentUrl: string, options: Record<string, unknown>, cb: (err: Error | null, cookies: string) => void) => void) & ((url: string, callback: (error: Error | null, cookieHeader: string) => void) => void);
45
+ setCookie: ((cookieOrString: unknown, currentUrl: string, options: Record<string, unknown>, cb: (err: Error | null, cookie: unknown) => void) => void) & ((rawCookie: string, url: string, callback: (error: Error | null, result: unknown) => void) => void);
50
46
  }
51
47
  export interface PromiseCookieJar {
52
48
  getCookieString: (url: string) => Promise<string>;
@@ -352,9 +348,7 @@ interface PlainOptions extends URLOptions {
352
348
 
353
349
  __Note #2__: This option is not enumerable and will not be merged with the instance defaults.
354
350
  */
355
- form?: {
356
- [key: string]: any;
357
- };
351
+ form?: Record<string, any>;
358
352
  /**
359
353
  JSON body. If the `Content-Type` header is not set, it will be set to `application/json`.
360
354
 
@@ -362,9 +356,7 @@ interface PlainOptions extends URLOptions {
362
356
 
363
357
  __Note #2__: This option is not enumerable and will not be merged with the instance defaults.
364
358
  */
365
- json?: {
366
- [key: string]: any;
367
- };
359
+ json?: Record<string, any>;
368
360
  /**
369
361
  The URL to request, as a string, a [`https.request` options object](https://nodejs.org/api/https.html#https_https_request_options_callback), or a [WHATWG `URL`](https://nodejs.org/api/url.html#url_class_url).
370
362
 
@@ -415,9 +407,7 @@ interface PlainOptions extends URLOptions {
415
407
  //=> 'key=a&key=b'
416
408
  ```
417
409
  */
418
- searchParams?: string | {
419
- [key: string]: string | number | boolean | null | undefined;
420
- } | URLSearchParams;
410
+ searchParams?: string | Record<string, string | number | boolean | null | undefined> | URLSearchParams;
421
411
  /**
422
412
  An instance of [`CacheableLookup`](https://github.com/szmarczak/cacheable-lookup) used for making DNS lookups.
423
413
  Useful when making lots of requests to different *public* hostnames.
@@ -738,6 +728,7 @@ export interface HTTPSOptions {
738
728
  The passphrase to decrypt the `options.https.key` (if different keys have different passphrases refer to `options.https.key` documentation).
739
729
  */
740
730
  passphrase?: SecureContextOptions['passphrase'];
731
+ pfx?: SecureContextOptions['pfx'];
741
732
  }
742
733
  interface NormalizedPlainOptions extends PlainOptions {
743
734
  method: Method;
@@ -295,18 +295,28 @@ class Request extends stream_1.Duplex {
295
295
  if (json || body || form) {
296
296
  this._lockWrite();
297
297
  }
298
- (async (nonNormalizedOptions) => {
299
- var _a;
298
+ if (exports.kIsNormalizedAlready in options) {
299
+ this.options = options;
300
+ }
301
+ else {
300
302
  try {
301
- if (nonNormalizedOptions.body instanceof fs_1.ReadStream) {
302
- await waitForOpenFile(nonNormalizedOptions.body);
303
- }
304
- if (exports.kIsNormalizedAlready in nonNormalizedOptions) {
305
- this.options = nonNormalizedOptions;
303
+ // @ts-expect-error Common TypeScript bug saying that `this.constructor` is not accessible
304
+ this.options = this.constructor.normalizeArguments(url, options, defaults);
305
+ }
306
+ catch (error) {
307
+ // TODO: Move this to `_destroy()`
308
+ if (is_1.default.nodeStream(options.body)) {
309
+ options.body.destroy();
306
310
  }
307
- else {
308
- // @ts-expect-error Common TypeScript bug saying that `this.constructor` is not accessible
309
- this.options = this.constructor.normalizeArguments(url, nonNormalizedOptions, defaults);
311
+ this.destroy(error);
312
+ return;
313
+ }
314
+ }
315
+ (async () => {
316
+ var _a;
317
+ try {
318
+ if (this.options.body instanceof fs_1.ReadStream) {
319
+ await waitForOpenFile(this.options.body);
310
320
  }
311
321
  const { url: normalizedURL } = this.options;
312
322
  if (!normalizedURL) {
@@ -338,10 +348,10 @@ class Request extends stream_1.Duplex {
338
348
  this.destroy(error);
339
349
  }
340
350
  }
341
- })(options);
351
+ })();
342
352
  }
343
353
  static normalizeArguments(url, options, defaults) {
344
- var _a, _b, _c, _d;
354
+ var _a, _b, _c, _d, _e;
345
355
  const rawOptions = options;
346
356
  if (is_1.default.object(url) && !is_1.default.urlInstance(url)) {
347
357
  options = { ...defaults, ...url, ...options };
@@ -394,6 +404,7 @@ class Request extends stream_1.Duplex {
394
404
  is_1.assert.any([is_1.default.string, is_1.default.object, is_1.default.array, is_1.default.undefined], options.https.key);
395
405
  is_1.assert.any([is_1.default.string, is_1.default.object, is_1.default.array, is_1.default.undefined], options.https.certificate);
396
406
  is_1.assert.any([is_1.default.string, is_1.default.undefined], options.https.passphrase);
407
+ is_1.assert.any([is_1.default.string, is_1.default.buffer, is_1.default.array, is_1.default.undefined], options.https.pfx);
397
408
  }
398
409
  is_1.assert.any([is_1.default.object, is_1.default.undefined], options.cacheOptions);
399
410
  // `options.method`
@@ -453,15 +464,15 @@ class Request extends stream_1.Duplex {
453
464
  options.username = (_b = options.username) !== null && _b !== void 0 ? _b : '';
454
465
  options.password = (_c = options.password) !== null && _c !== void 0 ? _c : '';
455
466
  // `options.prefixUrl` & `options.url`
456
- if (options.prefixUrl) {
467
+ if (is_1.default.undefined(options.prefixUrl)) {
468
+ options.prefixUrl = (_d = defaults === null || defaults === void 0 ? void 0 : defaults.prefixUrl) !== null && _d !== void 0 ? _d : '';
469
+ }
470
+ else {
457
471
  options.prefixUrl = options.prefixUrl.toString();
458
472
  if (options.prefixUrl !== '' && !options.prefixUrl.endsWith('/')) {
459
473
  options.prefixUrl += '/';
460
474
  }
461
475
  }
462
- else {
463
- options.prefixUrl = '';
464
- }
465
476
  if (is_1.default.string(options.url)) {
466
477
  if (options.url.startsWith('/')) {
467
478
  throw new Error('`input` must not start with a slash when using `prefixUrl`');
@@ -472,6 +483,9 @@ class Request extends stream_1.Duplex {
472
483
  options.url = options_to_url_1.default(options.prefixUrl, options);
473
484
  }
474
485
  if (options.url) {
486
+ if ('port' in options) {
487
+ delete options.port;
488
+ }
475
489
  // Make it possible to change `options.prefixUrl`
476
490
  let { prefixUrl } = options;
477
491
  Object.defineProperty(options, 'prefixUrl', {
@@ -614,7 +628,7 @@ class Request extends stream_1.Duplex {
614
628
  if (defaults && !areHooksDefault) {
615
629
  for (const event of exports.knownHookEvents) {
616
630
  const defaultHooks = defaults.hooks[event];
617
- if (defaultHooks.length !== 0) {
631
+ if (defaultHooks.length > 0) {
618
632
  // See https://github.com/microsoft/TypeScript/issues/31445#issuecomment-576929044
619
633
  options.hooks[event] = [
620
634
  ...defaults.hooks[event],
@@ -649,6 +663,9 @@ class Request extends stream_1.Duplex {
649
663
  if ('passphrase' in options) {
650
664
  deprecation_warning_1.default('"options.passphrase" was never documented, please use "options.https.passphrase"');
651
665
  }
666
+ if ('pfx' in options) {
667
+ deprecation_warning_1.default('"options.pfx" was never documented, please use "options.https.pfx"');
668
+ }
652
669
  // Other options
653
670
  if ('followRedirects' in options) {
654
671
  throw new TypeError('The `followRedirects` option does not exist. Use `followRedirect` instead.');
@@ -660,7 +677,7 @@ class Request extends stream_1.Duplex {
660
677
  }
661
678
  }
662
679
  }
663
- options.maxRedirects = (_d = options.maxRedirects) !== null && _d !== void 0 ? _d : 0;
680
+ options.maxRedirects = (_e = options.maxRedirects) !== null && _e !== void 0 ? _e : 0;
664
681
  // Set non-enumerable properties
665
682
  exports.setNonEnumerableProperties([defaults, rawOptions], options);
666
683
  return normalize_arguments_1.default(options, defaults);
@@ -826,6 +843,8 @@ class Request extends stream_1.Duplex {
826
843
  if ('form' in options) {
827
844
  delete options.form;
828
845
  }
846
+ this[kBody] = undefined;
847
+ delete options.headers['content-length'];
829
848
  }
830
849
  if (this.redirects.length >= options.maxRedirects) {
831
850
  this._beforeError(new MaxRedirectsError(this));
@@ -839,7 +858,7 @@ class Request extends stream_1.Duplex {
839
858
  const redirectString = redirectUrl.toString();
840
859
  decodeURI(redirectString);
841
860
  // Redirecting to a different site, clear sensitive data.
842
- if (redirectUrl.hostname !== url.hostname) {
861
+ if (redirectUrl.hostname !== url.hostname || redirectUrl.port !== url.port) {
843
862
  if ('host' in options.headers) {
844
863
  delete options.headers.host;
845
864
  }
@@ -850,13 +869,14 @@ class Request extends stream_1.Duplex {
850
869
  delete options.headers.authorization;
851
870
  }
852
871
  if (options.username || options.password) {
853
- // TODO: Fix this ignore.
854
- // @ts-expect-error
855
- delete options.username;
856
- // @ts-expect-error
857
- delete options.password;
872
+ options.username = '';
873
+ options.password = '';
858
874
  }
859
875
  }
876
+ else {
877
+ redirectUrl.username = options.username;
878
+ redirectUrl.password = options.password;
879
+ }
860
880
  this.redirects.push(redirectString);
861
881
  options.url = redirectUrl;
862
882
  for (const hook of options.hooks.beforeRedirect) {
@@ -930,12 +950,7 @@ class Request extends stream_1.Duplex {
930
950
  request.destroy();
931
951
  // Node.js <= 12.18.2 mistakenly emits the response `end` first.
932
952
  (_a = request.res) === null || _a === void 0 ? void 0 : _a.removeAllListeners('end');
933
- if (error instanceof timed_out_1.TimeoutError) {
934
- error = new TimeoutError(error, this.timings, this);
935
- }
936
- else {
937
- error = new RequestError(error.message, error, this);
938
- }
953
+ error = error instanceof timed_out_1.TimeoutError ? new TimeoutError(error, this.timings, this) : new RequestError(error.message, error, this);
939
954
  this._beforeError(error);
940
955
  });
941
956
  this[kUnproxyEvents] = proxy_events_1.default(request, this, proxiedRequestEvents);
@@ -1023,6 +1038,9 @@ class Request extends stream_1.Duplex {
1023
1038
  break;
1024
1039
  }
1025
1040
  }
1041
+ if (options.body && this[kBody] !== options.body) {
1042
+ this[kBody] = options.body;
1043
+ }
1026
1044
  const { agent, request, timeout, url } = options;
1027
1045
  if (options.dnsCache && !('lookup' in options)) {
1028
1046
  options.lookup = options.dnsCache.lookup;
@@ -1095,6 +1113,9 @@ class Request extends stream_1.Duplex {
1095
1113
  if (options.https.passphrase) {
1096
1114
  requestOptions.passphrase = options.https.passphrase;
1097
1115
  }
1116
+ if (options.https.pfx) {
1117
+ requestOptions.pfx = options.https.pfx;
1118
+ }
1098
1119
  }
1099
1120
  try {
1100
1121
  let requestOrResponse = await fn(url, requestOptions);
@@ -1126,6 +1147,9 @@ class Request extends stream_1.Duplex {
1126
1147
  if (options.https.passphrase) {
1127
1148
  delete requestOptions.passphrase;
1128
1149
  }
1150
+ if (options.https.pfx) {
1151
+ delete requestOptions.pfx;
1152
+ }
1129
1153
  }
1130
1154
  if (isClientRequest(requestOrResponse)) {
1131
1155
  this._onRequest(requestOrResponse);
@@ -1179,9 +1203,9 @@ class Request extends stream_1.Duplex {
1179
1203
  response.setEncoding(this._readableState.encoding);
1180
1204
  try {
1181
1205
  response.rawBody = await get_buffer_1.default(response);
1206
+ response.body = response.rawBody.toString();
1182
1207
  }
1183
1208
  catch (_a) { }
1184
- response.body = response.rawBody.toString();
1185
1209
  }
1186
1210
  if (this.listenerCount('retry') !== 0) {
1187
1211
  let backoff;
@@ -1277,6 +1301,10 @@ class Request extends stream_1.Duplex {
1277
1301
  }
1278
1302
  }
1279
1303
  _writeRequest(chunk, encoding, callback) {
1304
+ if (this[kRequest].destroyed) {
1305
+ // Probably the `ClientRequest` instance will throw
1306
+ return;
1307
+ }
1280
1308
  this._progressCallbacks.push(() => {
1281
1309
  this[kUploadedSize] += Buffer.byteLength(chunk, encoding);
1282
1310
  const progress = this.uploadProgress;
@@ -1286,7 +1314,7 @@ class Request extends stream_1.Duplex {
1286
1314
  });
1287
1315
  // TODO: What happens if it's from cache? Then this[kRequest] won't be defined.
1288
1316
  this[kRequest].write(chunk, encoding, (error) => {
1289
- if (!error && this._progressCallbacks.length !== 0) {
1317
+ if (!error && this._progressCallbacks.length > 0) {
1290
1318
  this._progressCallbacks.shift()();
1291
1319
  }
1292
1320
  callback(error);
@@ -1350,7 +1378,7 @@ class Request extends stream_1.Duplex {
1350
1378
  */
1351
1379
  get ip() {
1352
1380
  var _a;
1353
- return (_a = this[kRequest]) === null || _a === void 0 ? void 0 : _a.socket.remoteAddress;
1381
+ return (_a = this.socket) === null || _a === void 0 ? void 0 : _a.remoteAddress;
1354
1382
  }
1355
1383
  /**
1356
1384
  Indicates whether the request has been aborted or not.
@@ -1360,8 +1388,8 @@ class Request extends stream_1.Duplex {
1360
1388
  return ((_b = (_a = this[kRequest]) === null || _a === void 0 ? void 0 : _a.destroyed) !== null && _b !== void 0 ? _b : this.destroyed) && !((_c = this[kOriginalResponse]) === null || _c === void 0 ? void 0 : _c.complete);
1361
1389
  }
1362
1390
  get socket() {
1363
- var _a;
1364
- return (_a = this[kRequest]) === null || _a === void 0 ? void 0 : _a.socket;
1391
+ var _a, _b;
1392
+ return (_b = (_a = this[kRequest]) === null || _a === void 0 ? void 0 : _a.socket) !== null && _b !== void 0 ? _b : undefined;
1365
1393
  }
1366
1394
  /**
1367
1395
  Progress event for downloading (receiving a response).
@@ -23,6 +23,9 @@ exports.default = async (body, headers) => {
23
23
  }
24
24
  if (body instanceof fs_1.ReadStream) {
25
25
  const { size } = await statAsync(body.path);
26
+ if (size === 0) {
27
+ return undefined;
28
+ }
26
29
  return size;
27
30
  }
28
31
  return undefined;
@@ -14,7 +14,7 @@ exports.default = (url) => {
14
14
  href: url.href,
15
15
  path: `${url.pathname || ''}${url.search || ''}`
16
16
  };
17
- if (is_1.default.string(url.port) && url.port.length !== 0) {
17
+ if (is_1.default.string(url.port) && url.port.length > 0) {
18
18
  options.port = Number(url.port);
19
19
  }
20
20
  if (url.username || url.password) {
@@ -82,7 +82,7 @@ const create = (defaults) => {
82
82
  return result;
83
83
  }));
84
84
  // Got interface
85
- const got = ((url, options, _defaults) => {
85
+ const got = ((url, options = {}, _defaults) => {
86
86
  var _a, _b;
87
87
  let iteration = 0;
88
88
  const iterateHandlers = (newOptions) => {
@@ -103,7 +103,7 @@ const create = (defaults) => {
103
103
  let initHookError;
104
104
  try {
105
105
  callInitHooks(defaults.options.hooks.init, options);
106
- callInitHooks((_a = options === null || options === void 0 ? void 0 : options.hooks) === null || _a === void 0 ? void 0 : _a.init, options);
106
+ callInitHooks((_a = options.hooks) === null || _a === void 0 ? void 0 : _a.init, options);
107
107
  }
108
108
  catch (error) {
109
109
  initHookError = error;
@@ -117,11 +117,11 @@ const create = (defaults) => {
117
117
  return iterateHandlers(normalizedOptions);
118
118
  }
119
119
  catch (error) {
120
- if (options === null || options === void 0 ? void 0 : options.isStream) {
120
+ if (options.isStream) {
121
121
  throw error;
122
122
  }
123
123
  else {
124
- return create_rejection_1.default(error, defaults.options.hooks.beforeError, (_b = options === null || options === void 0 ? void 0 : options.hooks) === null || _b === void 0 ? void 0 : _b.beforeError);
124
+ return create_rejection_1.default(error, defaults.options.hooks.beforeError, (_b = options.hooks) === null || _b === void 0 ? void 0 : _b.beforeError);
125
125
  }
126
126
  }
127
127
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "got",
3
- "version": "11.6.0",
3
+ "version": "11.8.0",
4
4
  "description": "Human-friendly and powerful HTTP request library for Node.js",
5
5
  "license": "MIT",
6
6
  "repository": "sindresorhus/got",
@@ -43,7 +43,7 @@
43
43
  "ky"
44
44
  ],
45
45
  "dependencies": {
46
- "@sindresorhus/is": "^3.1.1",
46
+ "@sindresorhus/is": "^4.0.0",
47
47
  "@szmarczak/http-timer": "^4.0.5",
48
48
  "@types/cacheable-request": "^6.0.1",
49
49
  "@types/responselike": "^1.0.0",
@@ -61,7 +61,7 @@
61
61
  "@sinonjs/fake-timers": "^6.0.1",
62
62
  "@types/benchmark": "^1.0.33",
63
63
  "@types/express": "^4.17.7",
64
- "@types/node": "^14.6.0",
64
+ "@types/node": "^14.14.0",
65
65
  "@types/node-fetch": "^2.5.7",
66
66
  "@types/pem": "^1.9.5",
67
67
  "@types/pify": "^3.0.2",
@@ -87,11 +87,11 @@
87
87
  "pify": "^5.0.0",
88
88
  "sinon": "^9.0.3",
89
89
  "slow-stream": "0.0.4",
90
- "tempy": "^0.6.0",
90
+ "tempy": "^1.0.0",
91
91
  "to-readable-stream": "^2.1.0",
92
92
  "tough-cookie": "^4.0.0",
93
- "typescript": "^4.0.2",
94
- "xo": "^0.33.0"
93
+ "typescript": "4.0.3",
94
+ "xo": "^0.34.1"
95
95
  },
96
96
  "types": "dist/source",
97
97
  "sideEffects": false,
@@ -123,7 +123,7 @@
123
123
  "node/prefer-global/url": "off",
124
124
  "node/prefer-global/url-search-params": "off",
125
125
  "import/no-anonymous-default-export": "off",
126
- "@typescript-eslint/no-invalid-void-type": "off"
126
+ "@typescript-eslint/no-implicit-any-catch": "off"
127
127
  }
128
128
  },
129
129
  "runkitExampleFilename": "./documentation/examples/runkit-example.js"
package/readme.md CHANGED
@@ -5,8 +5,9 @@
5
5
  <br>
6
6
  <br>
7
7
  <br>
8
- <p align="center">Huge thanks to <a href="https://moxy.studio"><img src="https://sindresorhus.com/assets/thanks/moxy-logo.svg" width="150"></a> for sponsoring Sindre Sorhus!
8
+ <p align="center">Huge thanks to <a href="https://moxy.studio"><img src="https://sindresorhus.com/assets/thanks/moxy-logo.svg" valign="middle" width="150"></a> for sponsoring Sindre Sorhus!
9
9
  </p>
10
+ <p align="center"><sup>(they love Got too!)</sup></p>
10
11
  <br>
11
12
  <br>
12
13
  </div>
@@ -48,6 +49,7 @@ For browser usage, we recommend [Ky](https://github.com/sindresorhus/ky) by the
48
49
  - [Plugins](documentation/lets-make-a-plugin.md)
49
50
  - [Used by 4K+ packages and 1.8M+ repos](https://github.com/sindresorhus/got/network/dependents)
50
51
  - [Actively maintained](https://github.com/sindresorhus/got/graphs/contributors)
52
+ - [Trusted by many companies](#widely-used)
51
53
 
52
54
  ## Install
53
55
 
@@ -105,16 +107,16 @@ const got = require('got');
105
107
  const pipeline = promisify(stream.pipeline);
106
108
 
107
109
  (async () => {
108
- await pipeline(
109
- got.stream('https://sindresorhus.com'),
110
- fs.createWriteStream('index.html')
111
- );
112
-
113
- // For POST, PUT, and PATCH methods `got.stream` returns a `stream.Writable`
114
- await pipeline(
115
- fs.createReadStream('index.html'),
116
- got.stream.post('https://sindresorhus.com')
117
- );
110
+ await pipeline(
111
+ got.stream('https://sindresorhus.com'),
112
+ fs.createWriteStream('index.html')
113
+ );
114
+
115
+ // For POST, PUT, PATCH, and DELETE methods, `got.stream` returns a `stream.Writable`.
116
+ await pipeline(
117
+ fs.createReadStream('index.html'),
118
+ got.stream.post('https://sindresorhus.com')
119
+ );
118
120
  })();
119
121
  ```
120
122
 
@@ -144,7 +146,7 @@ If no protocol is specified, it will throw a `TypeError`.
144
146
 
145
147
  **Note:** The query string is **not** parsed as search params. Example:
146
148
 
147
- ```
149
+ ```js
148
150
  got('https://example.com/?query=a b'); //=> https://example.com/?query=a%20b
149
151
  got('https://example.com/', {searchParams: {query: 'a b'}}); //=> https://example.com/?query=a+b
150
152
 
@@ -304,7 +306,7 @@ Example:
304
306
  const bufferPromise = responsePromise.buffer();
305
307
  const jsonPromise = responsePromise.json();
306
308
 
307
- const [response, buffer, json] = Promise.all([responsePromise, bufferPromise, jsonPromise]);
309
+ const [response, buffer, json] = await Promise.all([responsePromise, bufferPromise, jsonPromise]);
308
310
  // `response` is an instance of Got Response
309
311
  // `buffer` is an instance of Buffer
310
312
  // `json` is an object
@@ -319,6 +321,8 @@ const body = await got(url).json();
319
321
  const body = await got(url, {responseType: 'json', resolveBodyOnly: true});
320
322
  ```
321
323
 
324
+ **Note:** `buffer` will return the raw body buffer. Modifying it will also alter the result of `promise.text()` and `promise.json()`. Before overwritting the buffer, please copy it first via `Buffer.from(buffer)`. See https://github.com/nodejs/node/issues/27080
325
+
322
326
  ###### parseJson
323
327
 
324
328
  Type: `(text: string) => unknown`\
@@ -517,6 +521,8 @@ Delays between retries counts with function `1000 * Math.pow(2, retry - 1) + Mat
517
521
 
518
522
  The `calculateDelay` property is a `function` that receives an object with `attemptCount`, `retryOptions`, `error` and `computedValue` properties for current retry count, the retry options, error and default computed value. The function must return a delay in milliseconds (or a Promise resolving with it) (`0` return value cancels retry).
519
523
 
524
+ **Note:** The `calculateDelay` function is responsible for the entire cache mechanism, including the `limit` property. To support it, you need to check whether `computedValue` is different than `0`.
525
+
520
526
  By default, it retries *only* on the specified methods, status codes, and on these network errors:
521
527
  - `ETIMEDOUT`: One of the [timeout](#timeout) limits were reached.
522
528
  - `ECONNRESET`: Connection was forcibly closed by a peer.
@@ -649,6 +655,15 @@ await got('https://api6.ipify.org', {
649
655
  });
650
656
  ```
651
657
 
658
+ ###### lookup
659
+
660
+ Type: `Function`\
661
+ Default: [`dns.lookup`](https://nodejs.org/api/dns.html#dns_dns_lookup_hostname_options_callback)
662
+
663
+ Custom DNS resolution logic.
664
+
665
+ The function signature is the same as [`dns.lookup`](https://nodejs.org/api/dns.html#dns_dns_lookup_hostname_options_callback).
666
+
652
667
  ###### request
653
668
 
654
669
  Type: `Function`\
@@ -724,7 +739,7 @@ Called with plain [request options](#options), right before their normalization.
724
739
  See the [Request migration guide](documentation/migration-guides.md#breaking-changes) for an example.
725
740
 
726
741
  **Note #1:** This hook must be synchronous!\
727
- **Note #2:** Errors in this hook will be converted into an instances of [`RequestError`](#got.requesterror).\
742
+ **Note #2:** Errors in this hook will be converted into an instances of [`RequestError`](#gotrequesterror).\
728
743
  **Note #3:** The options object may not have a `url` property. To modify it, use a `beforeRequest` hook instead.
729
744
 
730
745
  ###### hooks.beforeRequest
@@ -734,6 +749,24 @@ Default: `[]`
734
749
 
735
750
  Called with [normalized](source/core/index.ts) [request options](#options). Got will make no further changes to the request before it is sent. This is especially useful in conjunction with [`got.extend()`](#instances) when you want to create an API client that, for example, uses HMAC-signing.
736
751
 
752
+ **Note:** Changing `options.json` or `options.form` has no effect on the request, you should change `options.body` instead. If needed, update the `options.headers` accordingly. Example:
753
+
754
+ ```js
755
+ const got = require('got');
756
+
757
+ got.post({
758
+ json: {payload: 'old'},
759
+ hooks: {
760
+ beforeRequest: [
761
+ options => {
762
+ options.body = JSON.stringify({payload: 'new'});
763
+ options.headers['content-length'] = options.body.length.toString();
764
+ }
765
+ ]
766
+ }
767
+ });
768
+ ```
769
+
737
770
  **Tip:** You can override the `request` function by returning a [`ClientRequest`-like](https://nodejs.org/api/http.html#http_class_http_clientrequest) instance or a [`IncomingMessage`-like](https://nodejs.org/api/http.html#http_class_http_incomingmessage) instance. This is very useful when creating a custom cache mechanism.
738
771
 
739
772
  ###### hooks.beforeRedirect
@@ -849,12 +882,12 @@ got('https://api.github.com/some-endpoint', {
849
882
  beforeError: [
850
883
  error => {
851
884
  const {response} = error;
852
- if (response && response.body) {
885
+ if (response && response.body) {
853
886
  error.name = 'GitHubError';
854
887
  error.message = `${response.body.message} (${response.statusCode})`;
855
888
  }
856
889
 
857
- return error;
890
+ return error;
858
891
  }
859
892
  ]
860
893
  }
@@ -1018,7 +1051,24 @@ Type: `string`
1018
1051
 
1019
1052
  The passphrase to decrypt the `options.https.key` (if different keys have different passphrases refer to `options.https.key` documentation).
1020
1053
 
1021
- ##### Examples for `https.key`, `https.certificate` and `https.passphrase`
1054
+ ##### https.pfx
1055
+
1056
+ Type: `string | Buffer | Array<string | Buffer | object>`
1057
+
1058
+ [PFX or PKCS12](https://en.wikipedia.org/wiki/PKCS_12) encoded private key and certificate chain. Using `options.https.pfx` is an alternative to providing `options.https.key` and `options.https.certificate` individually. A PFX is usually encrypted, and if it is, `options.https.passphrase` will be used to decrypt it.
1059
+
1060
+ Multiple PFX's can be be provided as an array of unencrypted buffers or an array of objects like:
1061
+
1062
+ ```ts
1063
+ {
1064
+ buffer: string | Buffer,
1065
+ passphrase?: string
1066
+ }
1067
+ ```
1068
+
1069
+ This object form can only occur in an array. If the provided buffers are encrypted, `object.passphrase` can be used to decrypt them. If `object.passphrase` is not provided, `options.https.passphrase` will be used for decryption.
1070
+
1071
+ ##### Examples for `https.key`, `https.certificate`, `https.passphrase`, and `https.pfx`
1022
1072
 
1023
1073
  ```js
1024
1074
  // Single key with certificate
@@ -1065,6 +1115,45 @@ got('https://example.com', {
1065
1115
  ]
1066
1116
  }
1067
1117
  });
1118
+
1119
+ // Single encrypted PFX with passphrase
1120
+ got('https://example.com', {
1121
+ https: {
1122
+ pfx: fs.readFileSync('./fake.pfx'),
1123
+ passphrase: 'passphrase'
1124
+ }
1125
+ });
1126
+
1127
+ // Multiple encrypted PFX's with different passphrases
1128
+ got('https://example.com', {
1129
+ https: {
1130
+ pfx: [
1131
+ {
1132
+ buffer: fs.readFileSync('./key1.pfx'),
1133
+ passphrase: 'passphrase1'
1134
+ },
1135
+ {
1136
+ buffer: fs.readFileSync('./key2.pfx'),
1137
+ passphrase: 'passphrase2'
1138
+ }
1139
+ ]
1140
+ }
1141
+ });
1142
+
1143
+ // Multiple encrypted PFX's with single passphrase
1144
+ got('https://example.com', {
1145
+ https: {
1146
+ passphrase: 'passphrase',
1147
+ pfx: [
1148
+ {
1149
+ buffer: fs.readFileSync('./key1.pfx')
1150
+ },
1151
+ {
1152
+ buffer: fs.readFileSync('./key2.pfx')
1153
+ }
1154
+ ]
1155
+ }
1156
+ });
1068
1157
  ```
1069
1158
 
1070
1159
  ##### https.rejectUnauthorized
@@ -1318,7 +1407,7 @@ The same as `response.socket`.
1318
1407
 
1319
1408
  ##### .on('error', error)
1320
1409
 
1321
- The emitted `error` is an instance of [`RequestError`](#got.requesterror).
1410
+ The emitted `error` is an instance of [`RequestError`](#gotrequesterror).
1322
1411
 
1323
1412
  #### Pagination
1324
1413
 
@@ -2192,12 +2281,12 @@ The Electron `net` module is not consistent with the Node.js `http` module. See
2192
2281
  [ab]: https://badgen.net/travis/axios/axios?label
2193
2282
  [sb]: https://badgen.net/travis/visionmedia/superagent?label
2194
2283
 
2195
- [g5]: https://travis-ci.org/sindresorhus/got
2196
- [k5]: https://travis-ci.org/sindresorhus/ky
2197
- [r5]: https://travis-ci.org/request/request
2198
- [n5]: https://travis-ci.org/bitinn/node-fetch
2199
- [a5]: https://travis-ci.org/axios/axios
2200
- [s5]: https://travis-ci.org/visionmedia/superagent
2284
+ [g5]: https://travis-ci.com/github/sindresorhus/got
2285
+ [k5]: https://travis-ci.com/github/sindresorhus/ky
2286
+ [r5]: https://travis-ci.org/github/request/request
2287
+ [n5]: https://travis-ci.org/github/bitinn/node-fetch
2288
+ [a5]: https://travis-ci.org/github/axios/axios
2289
+ [s5]: https://travis-ci.org/github/visionmedia/superagent
2201
2290
 
2202
2291
  <!-- BUGS -->
2203
2292
  [gbg]: https://badgen.net/github/label-issues/sindresorhus/got/bug/open?label
@@ -2304,9 +2393,9 @@ The Electron `net` module is not consistent with the Node.js `http` module. See
2304
2393
 
2305
2394
  ## Maintainers
2306
2395
 
2307
- [![Sindre Sorhus](https://github.com/sindresorhus.png?size=100)](https://sindresorhus.com) | [![Szymon Marczak](https://github.com/szmarczak.png?size=100)](https://github.com/szmarczak)
2308
- ---|---
2309
- [Sindre Sorhus](https://sindresorhus.com) | [Szymon Marczak](https://github.com/szmarczak)
2396
+ [![Sindre Sorhus](https://github.com/sindresorhus.png?size=100)](https://sindresorhus.com) | [![Szymon Marczak](https://github.com/szmarczak.png?size=100)](https://github.com/szmarczak) | [![Giovanni Minotti](https://github.com/Giotino.png?size=100)](https://github.com/Giotino)
2397
+ ---|---|---
2398
+ [Sindre Sorhus](https://sindresorhus.com) | [Szymon Marczak](https://github.com/szmarczak) | [Giovanni Minotti](https://github.com/Giotino)
2310
2399
 
2311
2400
  ###### Former
2312
2401
 
@@ -2315,6 +2404,71 @@ The Electron `net` module is not consistent with the Node.js `http` module. See
2315
2404
  - [Brandon Smith](https://github.com/brandon93s)
2316
2405
  - [Luke Childs](https://github.com/lukechilds)
2317
2406
 
2407
+ <a name="widely-used"></a>
2408
+ ## These amazing companies are using Got
2409
+
2410
+ <a href="https://segment.com"><img width="90" valign="middle" src="https://user-images.githubusercontent.com/697676/47693700-ddb62500-dbb7-11e8-8332-716a91010c2d.png"></a>
2411
+ &nbsp;&nbsp;&nbsp;&nbsp;
2412
+ <a href="https://antora.org"><img width="100" valign="middle" src="https://user-images.githubusercontent.com/79351/47706840-d874cc80-dbef-11e8-87c6-5f0c60cbf5dc.png"></a>
2413
+ &nbsp;&nbsp;&nbsp;&nbsp;
2414
+ <a href="https://getvoip.com"><img width="150" valign="middle" src="https://user-images.githubusercontent.com/10832620/47869404-429e9480-dddd-11e8-8a7a-ca43d7f06020.png"></a>
2415
+ &nbsp;&nbsp;&nbsp;&nbsp;
2416
+ <a href="https://github.com/exoframejs/exoframe"><img width="150" valign="middle" src="https://user-images.githubusercontent.com/365944/47791460-11a95b80-dd1a-11e8-9070-e8f2a215e03a.png"></a>
2417
+ &nbsp;&nbsp;&nbsp;&nbsp;
2418
+ <a href="http://karaokes.moe"><img width="140" valign="middle" src="https://camo.githubusercontent.com/6860e5fa4684c14d8e1aa65df0aba4e6808ea1a9/687474703a2f2f6b6172616f6b65732e6d6f652f6173736574732f696d616765732f696e6465782e706e67"></a>
2419
+ &nbsp;&nbsp;&nbsp;&nbsp;
2420
+ <a href="https://github.com/renovatebot/renovate"><img width="150" valign="middle" src="https://camo.githubusercontent.com/206d470ac709b9a702a97b0c08d6f389a086793d/68747470733a2f2f72656e6f76617465626f742e636f6d2f696d616765732f6c6f676f2e737667"></a>
2421
+ &nbsp;&nbsp;&nbsp;&nbsp;
2422
+ <a href="https://resist.bot"><img width="150" valign="middle" src="https://user-images.githubusercontent.com/3322287/51992724-28736180-2473-11e9-9764-599cfda4b012.png"></a>
2423
+ &nbsp;&nbsp;&nbsp;&nbsp;
2424
+ <a href="https://www.naturalcycles.com"><img width="150" valign="middle" src="https://user-images.githubusercontent.com/170270/92244143-d0a8a200-eec2-11ea-9fc0-1c07f90b2113.png"></a>
2425
+ &nbsp;&nbsp;&nbsp;&nbsp;
2426
+ <a href="https://microlink.io"><img width="150" valign="middle" src="https://user-images.githubusercontent.com/36894700/91992974-1cc5dc00-ed35-11ea-9d04-f58b42ce6a5e.png"></a>
2427
+ &nbsp;&nbsp;&nbsp;&nbsp;
2428
+ <a href="https://radity.com"><img width="150" valign="middle" src="https://user-images.githubusercontent.com/29518613/91814036-97fb9500-ec44-11ea-8c6c-d198cc23ca29.png"></a>
2429
+
2430
+ <br>
2431
+
2432
+ > Segment is a happy user of Got! Got powers the main backend API that our app talks to. It's used by our in-house RPC client that we use to communicate with all microservices.
2433
+ >
2434
+ > — <a href="https://github.com/vadimdemedes">Vadim Demedes</a>
2435
+
2436
+ > Antora, a static site generator for creating documentation sites, uses Got to download the UI bundle. In Antora, the UI bundle (aka theme) is maintained as a separate project. That project exports the UI as a zip file we call the UI bundle. The main site generator downloads that UI from a URL using Got and streams it to vinyl-zip to extract the files. Those files go on to be used to create the HTML pages and supporting assets.
2437
+ >
2438
+ > — <a href="https://github.com/mojavelinux">Dan Allen</a>
2439
+
2440
+ > GetVoIP is happily using Got in production. One of the unique capabilities of Got is the ability to handle Unix sockets which enables us to build a full control interfaces for our docker stack.
2441
+ >
2442
+ > — <a href="https://github.com/danielkalen">Daniel Kalen</a>
2443
+
2444
+ > We're using Got inside of Exoframe to handle all the communication between CLI and server. Exoframe is a self-hosted tool that allows simple one-command deployments using Docker.
2445
+ >
2446
+ > — <a href="https://github.com/yamalight">Tim Ermilov</a>
2447
+
2448
+ > Karaoke Mugen uses Got to fetch content updates from its online server.
2449
+ >
2450
+ > — <a href="https://github.com/AxelTerizaki">Axel Terizaki</a>
2451
+
2452
+ > Renovate uses Got, gh-got and gl-got to send millions of queries per day to GitHub, GitLab, npmjs, PyPi, Packagist, Docker Hub, Terraform, CircleCI, and more.
2453
+ >
2454
+ > — <a href="https://github.com/rarkins">Rhys Arkins</a>
2455
+
2456
+ > Resistbot uses Got to communicate from the API frontend where all correspondence ingresses to the officials lookup database in back.
2457
+ >
2458
+ > — <a href="https://github.com/chris-erickson">Chris Erickson</a>
2459
+
2460
+ > Natural Cycles is using Got to communicate with all kinds of 3rd-party REST APIs (over 9000!).
2461
+ >
2462
+ > — <a href="https://github.com/kirillgroshkov">Kirill Groshkov</a>
2463
+
2464
+ > Microlink is a cloud browser as an API service that uses Got widely as the main HTTP client, serving ~22M requests a month, every time a network call needs to be performed.
2465
+ >
2466
+ > — <a href="https://github.com/Kikobeats">Kiko Beats</a>
2467
+
2468
+ > We’re using Got at Radity. Thanks for such an amazing work!
2469
+ >
2470
+ > — <a href="https://github.com/MirzayevFarid">Mirzayev Farid</a>
2471
+
2318
2472
  ## For enterprise
2319
2473
 
2320
2474
  Available as part of the Tidelift Subscription.