got 11.1.0 → 11.1.4

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.
@@ -1,3 +1,4 @@
1
1
  import { RetryFunction } from './types';
2
- declare const calculateRetryDelay: RetryFunction;
2
+ declare type Returns<T extends (...args: any) => unknown, V> = (...args: Parameters<T>) => V;
3
+ declare const calculateRetryDelay: Returns<RetryFunction, number>;
3
4
  export default calculateRetryDelay;
@@ -39,6 +39,11 @@ class PromisableRequest extends core_1.default {
39
39
  is_1.assert.any([is_1.default.boolean, is_1.default.undefined], options.resolveBodyOnly);
40
40
  is_1.assert.any([is_1.default.boolean, is_1.default.undefined], options.methodRewriting);
41
41
  is_1.assert.any([is_1.default.boolean, is_1.default.undefined], options.isStream);
42
+ is_1.assert.any([is_1.default.string, is_1.default.undefined], options.responseType);
43
+ // `options.responseType`
44
+ if (options.responseType === undefined) {
45
+ options.responseType = 'text';
46
+ }
42
47
  // `options.retry`
43
48
  const { retry } = options;
44
49
  if (defaults) {
@@ -51,7 +51,7 @@ function asPromise(options) {
51
51
  _reject(error);
52
52
  };
53
53
  globalRequest = request;
54
- request.once('response', async (response) => {
54
+ const onResponse = async (response) => {
55
55
  response.retryCount = retryCount;
56
56
  if (response.request.aborted) {
57
57
  // Canceled while downloading - will throw a `CancelError` or `TimeoutError` error
@@ -126,8 +126,9 @@ function asPromise(options) {
126
126
  }
127
127
  globalResponse = response;
128
128
  resolve(options.resolveBodyOnly ? response.body : response);
129
- });
130
- request.once('error', (error) => {
129
+ };
130
+ request.once('response', onResponse);
131
+ request.once('error', async (error) => {
131
132
  if (promise.isCanceled) {
132
133
  return;
133
134
  }
@@ -135,10 +136,11 @@ function asPromise(options) {
135
136
  reject(error);
136
137
  return;
137
138
  }
139
+ request.off('response', onResponse);
138
140
  let backoff;
139
141
  retryCount++;
140
142
  try {
141
- backoff = options.retry.calculateDelay({
143
+ backoff = await options.retry.calculateDelay({
142
144
  attemptCount: retryCount,
143
145
  retryOptions: options.retry,
144
146
  error,
@@ -181,7 +183,8 @@ function asPromise(options) {
181
183
  // The retry has not been made
182
184
  retryCount--;
183
185
  if (error instanceof types_1.HTTPError) {
184
- // It will be handled by the `response` event
186
+ // The error will be handled by the `response` event
187
+ onResponse(request._response);
185
188
  return;
186
189
  }
187
190
  // Don't emit the `response` event
@@ -13,7 +13,7 @@ export interface RetryObject {
13
13
  error: TimeoutError | RequestError;
14
14
  computedValue: number;
15
15
  }
16
- export declare type RetryFunction = (retryObject: RetryObject) => number;
16
+ export declare type RetryFunction = (retryObject: RetryObject) => number | Promise<number>;
17
17
  export interface RequiredRetryOptions {
18
18
  limit: number;
19
19
  methods: Method[];
@@ -4,7 +4,7 @@ import { URL, URLSearchParams } from 'url';
4
4
  import { Socket } from 'net';
5
5
  import { SecureContextOptions } from 'tls';
6
6
  import http = require('http');
7
- import { ClientRequest, RequestOptions, IncomingMessage, ServerResponse, request as httpRequest } from 'http';
7
+ import { ClientRequest, RequestOptions, ServerResponse, request as httpRequest } from 'http';
8
8
  import https = require('https');
9
9
  import { Timings, IncomingMessageWithTimings } from '@szmarczak/http-timer';
10
10
  import CacheableLookup from 'cacheable-lookup';
@@ -29,6 +29,7 @@ declare const kStopReading: unique symbol;
29
29
  declare const kTriggerRead: unique symbol;
30
30
  declare const kBody: unique symbol;
31
31
  declare const kJobs: unique symbol;
32
+ declare const kOriginalResponse: unique symbol;
32
33
  export declare const kIsNormalizedAlready: unique symbol;
33
34
  export interface Agents {
34
35
  http?: http.Agent;
@@ -64,7 +65,7 @@ export interface Hooks {
64
65
  }
65
66
  export declare type HookEvent = 'init' | 'beforeRequest' | 'beforeRedirect' | 'beforeError';
66
67
  export declare const knownHookEvents: HookEvent[];
67
- declare type AcceptableResponse = IncomingMessage | ResponseLike;
68
+ declare type AcceptableResponse = IncomingMessageWithTimings | ResponseLike;
68
69
  declare type AcceptableRequestResult = AcceptableResponse | ClientRequest | Promise<AcceptableResponse | ClientRequest> | undefined;
69
70
  export declare type RequestFunction = (url: URL, options: RequestOptions, callback?: (response: AcceptableResponse) => void) => AcceptableRequestResult;
70
71
  export declare type Headers = Record<string, string | string[] | undefined>;
@@ -248,7 +249,8 @@ export default class Request extends Duplex implements RequestEvents<Request> {
248
249
  [kStartedReading]?: boolean;
249
250
  [kCancelTimeouts]?: () => void;
250
251
  [kResponseSize]?: number;
251
- [kResponse]?: IncomingMessage;
252
+ [kResponse]?: IncomingMessageWithTimings;
253
+ [kOriginalResponse]?: IncomingMessageWithTimings;
252
254
  [kRequest]?: ClientRequest;
253
255
  _noPipe?: boolean;
254
256
  _progressCallbacks: Array<() => void>;
@@ -261,7 +263,7 @@ export default class Request extends Duplex implements RequestEvents<Request> {
261
263
  _lockWrite(): void;
262
264
  _unlockWrite(): void;
263
265
  _finalizeBody(): Promise<void>;
264
- _onResponse(response: IncomingMessage): Promise<void>;
266
+ _onResponse(response: IncomingMessageWithTimings): Promise<void>;
265
267
  _onRequest(request: ClientRequest): void;
266
268
  _createCacheableRequest(url: URL, options: RequestOptions): Promise<ClientRequest | ResponseLike>;
267
269
  _makeRequest(): Promise<void>;
@@ -278,6 +280,7 @@ export default class Request extends Duplex implements RequestEvents<Request> {
278
280
  get uploadProgress(): Progress;
279
281
  get timings(): Timings | undefined;
280
282
  get isFromCache(): boolean | undefined;
283
+ get _response(): Response | undefined;
281
284
  pipe<T extends NodeJS.WritableStream>(destination: T, options?: {
282
285
  end?: boolean;
283
286
  }): T;
@@ -8,9 +8,9 @@ const http = require("http");
8
8
  const http_1 = require("http");
9
9
  const https = require("https");
10
10
  const http_timer_1 = require("@szmarczak/http-timer");
11
- const decompressResponse = require("decompress-response");
12
11
  const cacheable_lookup_1 = require("cacheable-lookup");
13
12
  const CacheableRequest = require("cacheable-request");
13
+ const decompressResponse = require("decompress-response");
14
14
  // @ts-ignore Missing types
15
15
  const http2wrapper = require("http2-wrapper");
16
16
  const lowercaseKeys = require("lowercase-keys");
@@ -38,6 +38,7 @@ const kStopReading = Symbol('stopReading');
38
38
  const kTriggerRead = Symbol('triggerRead');
39
39
  const kBody = Symbol('body');
40
40
  const kJobs = Symbol('jobs');
41
+ const kOriginalResponse = Symbol('originalResponse');
41
42
  exports.kIsNormalizedAlready = Symbol('isNormalizedAlready');
42
43
  const supportsBrotli = is_1.default.string(process.versions.brotli);
43
44
  exports.withoutBody = new Set(['GET', 'HEAD']);
@@ -193,7 +194,6 @@ class UnsupportedProtocolError extends RequestError {
193
194
  exports.UnsupportedProtocolError = UnsupportedProtocolError;
194
195
  const proxiedRequestEvents = [
195
196
  'socket',
196
- 'abort',
197
197
  'connect',
198
198
  'continue',
199
199
  'information',
@@ -264,7 +264,7 @@ class Request extends stream_1.Duplex {
264
264
  await this._finalizeBody();
265
265
  await this._makeRequest();
266
266
  if (this.destroyed) {
267
- (_a = this[kRequest]) === null || _a === void 0 ? void 0 : _a.abort();
267
+ (_a = this[kRequest]) === null || _a === void 0 ? void 0 : _a.destroy();
268
268
  return;
269
269
  }
270
270
  // Queued writes etc.
@@ -278,15 +278,16 @@ class Request extends stream_1.Duplex {
278
278
  this._beforeError(error);
279
279
  return;
280
280
  }
281
- this.destroy(error);
281
+ // This is a workaround for https://github.com/nodejs/node/issues/33335
282
+ if (!this.destroyed) {
283
+ this.destroy(error);
284
+ }
282
285
  }
283
286
  })(options);
284
287
  }
285
288
  static normalizeArguments(url, options, defaults) {
286
289
  var _a, _b, _c, _d;
287
290
  const rawOptions = options;
288
- const searchParameters = options === null || options === void 0 ? void 0 : options.searchParams;
289
- const hooks = options === null || options === void 0 ? void 0 : options.hooks;
290
291
  if (is_1.default.object(url) && !is_1.default.urlInstance(url)) {
291
292
  options = { ...defaults, ...url, ...options };
292
293
  }
@@ -298,28 +299,8 @@ class Request extends stream_1.Duplex {
298
299
  if (url) {
299
300
  options.url = url;
300
301
  }
301
- }
302
- // Prevent duplicating default search params & hooks
303
- if (searchParameters === undefined) {
304
- delete options.searchParams;
305
- }
306
- else {
307
- options.searchParams = searchParameters;
308
- }
309
- if (hooks === undefined) {
310
- delete options.hooks;
311
- }
312
- else {
313
- options.hooks = hooks;
314
- }
315
- // Setting options to `undefined` turns off its functionalities
316
- if (rawOptions && defaults) {
317
- for (const key in rawOptions) {
318
- // @ts-ignore Dear TypeScript, all object keys are strings (or symbols which are NOT enumerable).
319
- if (is_1.default.undefined(rawOptions[key]) && !is_1.default.undefined(defaults[key])) {
320
- // @ts-ignore See the note above
321
- options[key] = defaults[key];
322
- }
302
+ if (is_1.default.urlInstance(options.url)) {
303
+ options.url = new url_1.URL(options.url.toString());
323
304
  }
324
305
  }
325
306
  // TODO: Deprecate URL options in Got 12.
@@ -327,6 +308,9 @@ class Request extends stream_1.Duplex {
327
308
  if (options.cache === false) {
328
309
  options.cache = undefined;
329
310
  }
311
+ if (options.dnsCache === false) {
312
+ options.dnsCache = undefined;
313
+ }
330
314
  // Nice type assertions
331
315
  is_1.assert.any([is_1.default.string, is_1.default.undefined], options.method);
332
316
  is_1.assert.any([is_1.default.object, is_1.default.undefined], options.headers);
@@ -345,6 +329,7 @@ class Request extends stream_1.Duplex {
345
329
  is_1.assert.any([is_1.default.boolean, is_1.default.undefined], options.http2);
346
330
  is_1.assert.any([is_1.default.boolean, is_1.default.undefined], options.allowGetBody);
347
331
  is_1.assert.any([is_1.default.boolean, is_1.default.undefined], options.rejectUnauthorized);
332
+ is_1.assert.any([is_1.default.string, is_1.default.undefined], options.localAddress);
348
333
  // `options.method`
349
334
  if (is_1.default.string(options.method)) {
350
335
  options.method = options.method.toUpperCase();
@@ -353,10 +338,7 @@ class Request extends stream_1.Duplex {
353
338
  options.method = 'GET';
354
339
  }
355
340
  // `options.headers`
356
- if (is_1.default.undefined(options.headers)) {
357
- options.headers = {};
358
- }
359
- else if (options.headers === (defaults === null || defaults === void 0 ? void 0 : defaults.headers)) {
341
+ if (options.headers === (defaults === null || defaults === void 0 ? void 0 : defaults.headers)) {
360
342
  options.headers = { ...options.headers };
361
343
  }
362
344
  else {
@@ -371,18 +353,21 @@ class Request extends stream_1.Duplex {
371
353
  throw new TypeError('Parameter `auth` is deprecated. Use `username` / `password` instead.');
372
354
  }
373
355
  // `options.searchParams`
374
- if (options.searchParams) {
375
- if (!is_1.default.string(options.searchParams) && !(options.searchParams instanceof url_1.URLSearchParams)) {
376
- validateSearchParameters(options.searchParams);
377
- }
378
- options.searchParams = new url_1.URLSearchParams(options.searchParams);
379
- // `normalizeArguments()` is also used to merge options
380
- (_a = defaults === null || defaults === void 0 ? void 0 : defaults.searchParams) === null || _a === void 0 ? void 0 : _a.forEach((value, key) => {
381
- options.searchParams.append(key, value);
382
- });
383
- }
384
- else {
385
- options.searchParams = defaults === null || defaults === void 0 ? void 0 : defaults.searchParams;
356
+ if ('searchParams' in options) {
357
+ if (options.searchParams && options.searchParams !== (defaults === null || defaults === void 0 ? void 0 : defaults.searchParams)) {
358
+ if (!is_1.default.string(options.searchParams) && !(options.searchParams instanceof url_1.URLSearchParams)) {
359
+ validateSearchParameters(options.searchParams);
360
+ }
361
+ const searchParameters = new url_1.URLSearchParams(options.searchParams);
362
+ // `normalizeArguments()` is also used to merge options
363
+ (_a = defaults === null || defaults === void 0 ? void 0 : defaults.searchParams) === null || _a === void 0 ? void 0 : _a.forEach((value, key) => {
364
+ // Only use default if one isn't already defined
365
+ if (!searchParameters.has(key)) {
366
+ searchParameters.append(key, value);
367
+ }
368
+ });
369
+ options.searchParams = searchParameters;
370
+ }
386
371
  }
387
372
  // `options.username` & `options.password`
388
373
  options.username = (_b = options.username) !== null && _b !== void 0 ? _b : '';
@@ -430,19 +415,24 @@ class Request extends stream_1.Duplex {
430
415
  if (options.searchParams) {
431
416
  options.url.search = options.searchParams.toString();
432
417
  }
433
- // Trigger search params normalization
434
- if (options.url.search) {
435
- const triggerSearchParameters = '_GOT_INTERNAL_TRIGGER_NORMALIZATION';
436
- options.url.searchParams.append(triggerSearchParameters, '');
437
- options.url.searchParams.delete(triggerSearchParameters);
438
- }
439
418
  // Protocol check
440
419
  if (protocol !== 'http:' && protocol !== 'https:') {
441
420
  throw new UnsupportedProtocolError(options);
442
421
  }
443
- // Update `username` & `password`
444
- options.url.username = options.username;
445
- options.url.password = options.password;
422
+ // Update `username`
423
+ if (options.username === '') {
424
+ options.username = options.url.username;
425
+ }
426
+ else {
427
+ options.url.username = options.username;
428
+ }
429
+ // Update `password`
430
+ if (options.password === '') {
431
+ options.password = options.url.password;
432
+ }
433
+ else {
434
+ options.url.password = options.password;
435
+ }
446
436
  }
447
437
  // `options.cookieJar`
448
438
  const { cookieJar } = options;
@@ -471,7 +461,7 @@ class Request extends stream_1.Duplex {
471
461
  if (options.dnsCache === true) {
472
462
  options.dnsCache = new cacheable_lookup_1.default();
473
463
  }
474
- else if (!is_1.default.undefined(options.dnsCache) && options.dnsCache !== false && !(options.dnsCache instanceof cacheable_lookup_1.default)) {
464
+ else if (!is_1.default.undefined(options.dnsCache) && !options.dnsCache.lookup) {
475
465
  throw new TypeError(`Parameter \`dnsCache\` must be a CacheableLookup instance or a boolean, got ${is_1.default(options.dnsCache)}`);
476
466
  }
477
467
  // `options.timeout`
@@ -492,6 +482,7 @@ class Request extends stream_1.Duplex {
492
482
  options.context = {};
493
483
  }
494
484
  // `options.hooks`
485
+ const areHooksDefault = options.hooks === (defaults === null || defaults === void 0 ? void 0 : defaults.hooks);
495
486
  options.hooks = { ...options.hooks };
496
487
  for (const event of exports.knownHookEvents) {
497
488
  if (event in options.hooks) {
@@ -507,7 +498,7 @@ class Request extends stream_1.Duplex {
507
498
  options.hooks[event] = [];
508
499
  }
509
500
  }
510
- if (defaults) {
501
+ if (defaults && !areHooksDefault) {
511
502
  for (const event of exports.knownHookEvents) {
512
503
  const defaultHooks = defaults.hooks[event];
513
504
  if (defaultHooks.length !== 0) {
@@ -622,6 +613,7 @@ class Request extends stream_1.Duplex {
622
613
  async _onResponse(response) {
623
614
  const { options } = this;
624
615
  const { url } = options;
616
+ this[kOriginalResponse] = response;
625
617
  if (options.decompress) {
626
618
  response = decompressResponse(response);
627
619
  }
@@ -642,6 +634,9 @@ class Request extends stream_1.Duplex {
642
634
  this.emit('downloadProgress', this.downloadProgress);
643
635
  });
644
636
  response.once('error', (error) => {
637
+ // Force clean-up, because some packages don't do this.
638
+ // TODO: Fix decompress-response
639
+ response.destroy();
645
640
  this._beforeError(new ReadError(error, this));
646
641
  });
647
642
  response.once('aborted', () => {
@@ -699,13 +694,17 @@ class Request extends stream_1.Duplex {
699
694
  return;
700
695
  }
701
696
  try {
702
- // Handles invalid URLs. See https://github.com/sindresorhus/got/issues/604
697
+ // Do not remove. See https://github.com/sindresorhus/got/pull/214
703
698
  const redirectBuffer = Buffer.from(response.headers.location, 'binary').toString();
699
+ // Handles invalid URLs. See https://github.com/sindresorhus/got/issues/604
704
700
  const redirectUrl = new url_1.URL(redirectBuffer, url);
705
701
  const redirectString = redirectUrl.toString();
706
702
  decodeURI(redirectString);
707
703
  // Redirecting to a different site, clear sensitive data.
708
704
  if (redirectUrl.hostname !== url.hostname) {
705
+ if ('host' in options.headers) {
706
+ delete options.headers.host;
707
+ }
709
708
  if ('cookie' in options.headers) {
710
709
  delete options.headers.cookie;
711
710
  }
@@ -775,10 +774,13 @@ class Request extends stream_1.Duplex {
775
774
  const { timeout, url } = options;
776
775
  http_timer_1.default(request);
777
776
  this[kCancelTimeouts] = timed_out_1.default(request, timeout, url);
778
- request.once('response', response => {
777
+ const responseEventName = options.cache ? 'cacheableResponse' : 'response';
778
+ request.once(responseEventName, (response) => {
779
779
  this._onResponse(response);
780
780
  });
781
781
  request.once('error', (error) => {
782
+ // Force clean-up, because some packages (e.g. nock) don't do this.
783
+ request.destroy();
782
784
  if (error instanceof timed_out_1.TimeoutError) {
783
785
  error = new TimeoutError(error, this.timings, this);
784
786
  }
@@ -823,16 +825,19 @@ class Request extends stream_1.Duplex {
823
825
  // `http-cache-semantics` checks this
824
826
  delete options.url;
825
827
  // This is ugly
826
- const cacheRequest = cacheableStore.get(options.cache)(options, resolve);
827
- // Restore options
828
- options.url = url;
829
- cacheRequest.once('error', (error) => {
830
- if (error instanceof CacheableRequest.CacheError) {
831
- reject(new CacheError(error, this));
832
- return;
828
+ const cacheRequest = cacheableStore.get(options.cache)(options, response => {
829
+ const typedResponse = response;
830
+ const { req } = typedResponse;
831
+ // TODO: Fix `cacheable-response`
832
+ typedResponse._readableState.autoDestroy = false;
833
+ if (req) {
834
+ req.emit('cacheableResponse', typedResponse);
833
835
  }
834
- reject(error);
836
+ resolve(typedResponse);
835
837
  });
838
+ // Restore options
839
+ options.url = url;
840
+ cacheRequest.once('error', reject);
836
841
  cacheRequest.once('request', resolve);
837
842
  });
838
843
  }
@@ -884,6 +889,7 @@ class Request extends stream_1.Duplex {
884
889
  }
885
890
  }
886
891
  const isHttps = url.protocol === 'https:';
892
+ // Fallback function
887
893
  let fallbackFn;
888
894
  if (options.http2) {
889
895
  fallbackFn = http2wrapper.auto;
@@ -892,16 +898,18 @@ class Request extends stream_1.Duplex {
892
898
  fallbackFn = isHttps ? https.request : http.request;
893
899
  }
894
900
  const realFn = (_a = options.request) !== null && _a !== void 0 ? _a : fallbackFn;
895
- const fn = options.cache ? this._createCacheableRequest.bind(this) : realFn;
901
+ // Cache support
902
+ const fn = options.cache ? this._createCacheableRequest : realFn;
903
+ // Pass an agent directly when HTTP2 is disabled
896
904
  if (agent && !options.http2) {
897
905
  options.agent = agent[isHttps ? 'https' : 'http'];
898
906
  }
907
+ // Prepare plain HTTP request options
899
908
  options[kRequest] = realFn;
900
909
  delete options.request;
901
910
  delete options.timeout;
902
- let requestOrResponse;
903
911
  try {
904
- requestOrResponse = await fn(url, options);
912
+ let requestOrResponse = await fn(url, options);
905
913
  if (is_1.default.undefined(requestOrResponse)) {
906
914
  requestOrResponse = fallbackFn(url, options);
907
915
  }
@@ -926,8 +934,8 @@ class Request extends stream_1.Duplex {
926
934
  }
927
935
  }
928
936
  catch (error) {
929
- if (error instanceof RequestError) {
930
- throw error;
937
+ if (error instanceof CacheableRequest.CacheError) {
938
+ throw new CacheError(error, this);
931
939
  }
932
940
  throw new RequestError(error.message, error, this);
933
941
  }
@@ -955,7 +963,10 @@ class Request extends stream_1.Duplex {
955
963
  catch (error_) {
956
964
  error = new RequestError(error_.message, error_, this);
957
965
  }
958
- this.destroy(error);
966
+ // This is a workaround for https://github.com/nodejs/node/issues/33335
967
+ if (!this.destroyed) {
968
+ this.destroy(error);
969
+ }
959
970
  }
960
971
  _read() {
961
972
  this[kTriggerRead] = true;
@@ -1017,6 +1028,10 @@ class Request extends stream_1.Duplex {
1017
1028
  callback();
1018
1029
  return;
1019
1030
  }
1031
+ if (this[kRequest].destroyed) {
1032
+ callback();
1033
+ return;
1034
+ }
1020
1035
  this[kRequest].end((error) => {
1021
1036
  if (!error) {
1022
1037
  this[kBodySize] = this[kUploadedSize];
@@ -1039,9 +1054,8 @@ class Request extends stream_1.Duplex {
1039
1054
  this[kCancelTimeouts]();
1040
1055
  // TODO: Remove the next `if` when these get fixed:
1041
1056
  // - https://github.com/nodejs/node/issues/32851
1042
- // - https://github.com/nock/nock/issues/1981
1043
- if (!((_a = this[kResponse]) === null || _a === void 0 ? void 0 : _a.complete) && !this[kRequest].destroyed) {
1044
- this[kRequest].abort();
1057
+ if (!((_a = this[kResponse]) === null || _a === void 0 ? void 0 : _a.complete)) {
1058
+ this[kRequest].destroy();
1045
1059
  }
1046
1060
  }
1047
1061
  if (error !== null && !is_1.default.undefined(error) && !(error instanceof RequestError)) {
@@ -1054,8 +1068,8 @@ class Request extends stream_1.Duplex {
1054
1068
  return (_a = this[kRequest]) === null || _a === void 0 ? void 0 : _a.socket.remoteAddress;
1055
1069
  }
1056
1070
  get aborted() {
1057
- var _a;
1058
- return Boolean((_a = this[kRequest]) === null || _a === void 0 ? void 0 : _a.aborted);
1071
+ var _a, _b, _c;
1072
+ 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);
1059
1073
  }
1060
1074
  get socket() {
1061
1075
  var _a;
@@ -1102,6 +1116,9 @@ class Request extends stream_1.Duplex {
1102
1116
  get isFromCache() {
1103
1117
  return this[kIsFromCache];
1104
1118
  }
1119
+ get _response() {
1120
+ return this[kResponse];
1121
+ }
1105
1122
  pipe(destination, options) {
1106
1123
  if (this[kStartedReading]) {
1107
1124
  throw new Error('Failed to pipe. The response has been emitted already.');
@@ -48,7 +48,7 @@ exports.default = (request, delays, options) => {
48
48
  throw error;
49
49
  }
50
50
  });
51
- request.once('abort', cancelTimeouts);
51
+ request.once('close', cancelTimeouts);
52
52
  once(request, 'response', (response) => {
53
53
  once(response, 'end', cancelTimeouts);
54
54
  });
@@ -60,6 +60,7 @@ const create = (defaults) => {
60
60
  }
61
61
  return result;
62
62
  }));
63
+ // Got interface
63
64
  const got = ((url, options) => {
64
65
  var _a, _b;
65
66
  let iteration = 0;
@@ -89,8 +90,6 @@ const create = (defaults) => {
89
90
  if (initHookError) {
90
91
  throw new as_promise_1.RequestError(initHookError.message, initHookError, normalizedOptions);
91
92
  }
92
- // A bug.
93
- // eslint-disable-next-line @typescript-eslint/return-await
94
93
  return iterateHandlers(normalizedOptions);
95
94
  }
96
95
  catch (error) {
@@ -98,8 +97,6 @@ const create = (defaults) => {
98
97
  throw error;
99
98
  }
100
99
  else {
101
- // A bug.
102
- // eslint-disable-next-line @typescript-eslint/return-await
103
100
  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);
104
101
  }
105
102
  }
@@ -132,7 +129,8 @@ const create = (defaults) => {
132
129
  mutableDefaults: Boolean(isMutableDefaults)
133
130
  });
134
131
  };
135
- got.paginate = (async function* (url, options) {
132
+ // Pagination
133
+ const paginateEach = (async function* (url, options) {
136
134
  let normalizedOptions = normalizeArguments(url, options, defaults.options);
137
135
  normalizedOptions.resolveBodyOnly = false;
138
136
  const pagination = normalizedOptions.pagination;
@@ -168,12 +166,18 @@ const create = (defaults) => {
168
166
  if (optionsToMerge === false) {
169
167
  return;
170
168
  }
171
- if (optionsToMerge !== undefined) {
169
+ if (optionsToMerge === result.request.options) {
170
+ normalizedOptions = result.request.options;
171
+ }
172
+ else if (optionsToMerge !== undefined) {
172
173
  normalizedOptions = normalizeArguments(undefined, optionsToMerge, normalizedOptions);
173
174
  }
174
175
  numberOfRequests++;
175
176
  }
176
177
  });
178
+ got.paginate = ((url, options) => {
179
+ return paginateEach(url, options);
180
+ });
177
181
  got.paginate.all = (async (url, options) => {
178
182
  const results = [];
179
183
  for await (const item of got.paginate(url, options)) {
@@ -181,7 +185,11 @@ const create = (defaults) => {
181
185
  }
182
186
  return results;
183
187
  });
188
+ // For those who like very descriptive names
189
+ got.paginate.each = paginateEach;
190
+ // Stream API
184
191
  got.stream = ((url, options) => got(url, { ...options, isStream: true }));
192
+ // Shortcuts
185
193
  for (const method of aliases) {
186
194
  got[method] = ((url, options) => got(url, { ...options, method }));
187
195
  got.stream[method] = ((url, options) => {
@@ -4,7 +4,6 @@ function __export(m) {
4
4
  }
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const url_1 = require("url");
7
- const cacheable_lookup_1 = require("cacheable-lookup");
8
7
  const create_1 = require("./create");
9
8
  const defaults = {
10
9
  options: {
@@ -57,7 +56,7 @@ const defaults = {
57
56
  afterResponse: []
58
57
  },
59
58
  cache: undefined,
60
- dnsCache: new cacheable_lookup_1.default(),
59
+ dnsCache: undefined,
61
60
  decompress: true,
62
61
  throwHttpErrors: true,
63
62
  followRedirect: true,
@@ -25,7 +25,7 @@ export declare type OptionsOfTextResponseBody = Merge<Options, {
25
25
  export declare type OptionsOfJSONResponseBody = Merge<Options, {
26
26
  isStream?: false;
27
27
  resolveBodyOnly?: false;
28
- responseType: 'json';
28
+ responseType?: 'json';
29
29
  }>;
30
30
  export declare type OptionsOfBufferResponseBody = Merge<Options, {
31
31
  isStream?: false;
@@ -42,8 +42,10 @@ declare type ResponseBodyOnly = {
42
42
  export declare type OptionsWithPagination<T = unknown, R = unknown> = Merge<Options, PaginationOptions<T, R>>;
43
43
  export interface GotPaginate {
44
44
  <T, R = unknown>(url: string | URL, options?: OptionsWithPagination<T, R>): AsyncIterableIterator<T>;
45
- all<T, R = unknown>(url: string | URL, options?: OptionsWithPagination<T, R>): Promise<T[]>;
46
45
  <T, R = unknown>(options?: OptionsWithPagination<T, R>): AsyncIterableIterator<T>;
46
+ each<T, R = unknown>(url: string | URL, options?: OptionsWithPagination<T, R>): AsyncIterableIterator<T>;
47
+ each<T, R = unknown>(options?: OptionsWithPagination<T, R>): AsyncIterableIterator<T>;
48
+ all<T, R = unknown>(url: string | URL, options?: OptionsWithPagination<T, R>): Promise<T[]>;
47
49
  all<T, R = unknown>(options?: OptionsWithPagination<T, R>): Promise<T[]>;
48
50
  }
49
51
  export interface GotRequestFunction {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "got",
3
- "version": "11.1.0",
3
+ "version": "11.1.4",
4
4
  "description": "Human-friendly and powerful HTTP request library for Node.js",
5
5
  "license": "MIT",
6
6
  "repository": "sindresorhus/got",
@@ -43,15 +43,15 @@
43
43
  "ky"
44
44
  ],
45
45
  "dependencies": {
46
- "@sindresorhus/is": "^2.1.0",
47
- "@szmarczak/http-timer": "^4.0.0",
46
+ "@sindresorhus/is": "^2.1.1",
47
+ "@szmarczak/http-timer": "^4.0.5",
48
48
  "@types/cacheable-request": "^6.0.1",
49
49
  "@types/responselike": "^1.0.0",
50
- "cacheable-lookup": "^4.1.1",
50
+ "cacheable-lookup": "^5.0.3",
51
51
  "cacheable-request": "^7.0.1",
52
- "decompress-response": "^5.0.0",
53
- "get-stream": "^5.0.0",
54
- "http2-wrapper": "^1.0.0-beta.4.4",
52
+ "decompress-response": "^6.0.0",
53
+ "get-stream": "^5.1.0",
54
+ "http2-wrapper": "^1.0.0-beta.4.5",
55
55
  "lowercase-keys": "^2.0.0",
56
56
  "p-cancelable": "^2.0.0",
57
57
  "responselike": "^2.0.0"
@@ -59,10 +59,10 @@
59
59
  "devDependencies": {
60
60
  "@ava/typescript": "^1.1.1",
61
61
  "@sindresorhus/tsconfig": "^0.7.0",
62
+ "@sinonjs/fake-timers": "^6.0.1",
62
63
  "@types/benchmark": "^1.0.31",
63
64
  "@types/express": "^4.17.6",
64
- "@types/lolex": "^5.1.0",
65
- "@types/node": "13.1.2",
65
+ "@types/node": "^13.13.4",
66
66
  "@types/node-fetch": "^2.5.5",
67
67
  "@types/request": "^2.48.4",
68
68
  "@types/sinon": "^9.0.0",
@@ -76,7 +76,6 @@
76
76
  "delay": "^4.3.0",
77
77
  "express": "^4.17.1",
78
78
  "form-data": "^3.0.0",
79
- "lolex": "^6.0.0",
80
79
  "nock": "^12.0.0",
81
80
  "node-fetch": "^2.6.0",
82
81
  "np": "^6.0.0",
@@ -125,5 +124,6 @@
125
124
  "@typescript-eslint/method-signature-style": "off",
126
125
  "unicorn/no-fn-reference-in-iterator": "off"
127
126
  }
128
- }
127
+ },
128
+ "runkitExampleFilename": "./documentation/examples/runkit-example.js"
129
129
  }
package/readme.md CHANGED
@@ -139,6 +139,16 @@ Properties from `options` will override properties in the parsed `url`.
139
139
 
140
140
  If no protocol is specified, it will throw a `TypeError`.
141
141
 
142
+ **Note:** The query string is **not** parsed as search params. Example:
143
+
144
+ ```
145
+ got('https://example.com/?query=a b'); //=> https://example.com/?query=a%20b
146
+ got('https://example.com/', {searchParams: {query: 'a b'}}); //=> https://example.com/?query=a+b
147
+
148
+ // The query string is overridden by `searchParams`
149
+ got('https://example.com/?query=a b', {searchParams: {query: 'a b'}}); //=> https://example.com/?query=a+b
150
+ ```
151
+
142
152
  ##### options
143
153
 
144
154
  Type: `object`
@@ -402,7 +412,7 @@ This also accepts an `object` with the following fields to constrain the duratio
402
412
  Type: `number | object`\
403
413
  Default:
404
414
  - limit: `2`
405
- - calculateDelay: `({attemptCount, retryOptions, error, computedValue}) => computedValue`
415
+ - calculateDelay: `({attemptCount, retryOptions, error, computedValue}) => computedValue | Promise<computedValue>`
406
416
  - methods: `GET` `PUT` `HEAD` `DELETE` `OPTIONS` `TRACE`
407
417
  - statusCodes: [`408`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/408) [`413`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/413) [`429`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/429) [`500`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/500) [`502`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/502) [`503`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/503) [`504`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/504) [`521`](https://support.cloudflare.com/hc/en-us/articles/115003011431#521error) [`522`](https://support.cloudflare.com/hc/en-us/articles/115003011431#522error) [`524`](https://support.cloudflare.com/hc/en-us/articles/115003011431#524error)
408
418
  - maxRetryAfter: `undefined`
@@ -417,7 +427,7 @@ If [`Retry-After`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Ret
417
427
 
418
428
  Delays between retries counts with function `1000 * Math.pow(2, retry) + Math.random() * 100`, where `retry` is attempt number (starts from 1).
419
429
 
420
- 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 (`0` return value cancels retry).
430
+ 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).
421
431
 
422
432
  By default, it retries *only* on the specified methods, status codes, and on these network errors:
423
433
  - `ETIMEDOUT`: One of the [timeout](#timeout) limits were reached.
@@ -481,10 +491,13 @@ Default: `false`
481
491
 
482
492
  ###### dnsCache
483
493
 
484
- Type: `object | false`\
485
- Default: `new CacheableLookup()`
494
+ Type: `CacheableLookup | false`\
495
+ Default: `false`
496
+
497
+ An instance of [`CacheableLookup`](https://github.com/szmarczak/cacheable-lookup) used for making DNS lookups. Useful when making lots of requests to different *public* hostnames.
486
498
 
487
- An instance of [`CacheableLookup`](https://github.com/szmarczak/cacheable-lookup) used for making DNS lookups.
499
+ **Note:** This should stay disabled when making requests to internal hostnames such as `localhost`, `database.local` etc.\
500
+ `CacheableLookup` uses `dns.resolver4(..)` and `dns.resolver6(...)` under the hood and fall backs to `dns.lookup(...)` when the first two fail, which may lead to additional delay.
488
501
 
489
502
  ###### request
490
503
 
@@ -520,7 +533,7 @@ const got = require('got');
520
533
  Type: `boolean`\
521
534
  Default: `true`
522
535
 
523
- Determines if a `got.HTTPError` is thrown for error responses (non-2xx status codes).
536
+ Determines if a [`got.HTTPError`](#gothttperror) is thrown for unsuccessful responses.
524
537
 
525
538
  If this is disabled, requests that encounter an error status code will be resolved with the `response` instead of throwing. This may be useful if you are checking for resource availability and are expecting error responses.
526
539
 
@@ -721,7 +734,7 @@ The function takes three arguments:
721
734
  - `allItems` - An array of the emitted items.
722
735
  - `currentItems` - Items from the current response.
723
736
 
724
- It should return an object representing Got options pointing to the next page. If there are no more pages, `false` should be returned.
737
+ It should return an object representing Got options pointing to the next page. The options are merged automatically with the previous request, therefore the options returned `pagination.paginate(...)` must reflect changes only. If there are no more pages, `false` should be returned.
725
738
 
726
739
  For example, if you want to stop when the response contains less items than expected, you can use something like this:
727
740
 
@@ -806,6 +819,31 @@ Type: `string`
806
819
 
807
820
  The IP address used to send the request from.
808
821
 
822
+ ##### rejectUnauthorized
823
+
824
+ Type: `boolean`\
825
+ Default: `true`
826
+
827
+ If set to `false`, all invalid SSL certificates will be ignored and no error will be thrown.\
828
+ If set to `true`, it will throw an error whenever an invalid SSL certificate is detected.
829
+
830
+ We strongly recommend to have this set to `true` for security reasons.
831
+
832
+ ```js
833
+ const got = require('got');
834
+
835
+ (async () => {
836
+ // Correct:
837
+ await got('https://example.com', {rejectUnauthorized: true});
838
+
839
+ // You can disable it when developing an HTTPS app:
840
+ await got('https://localhost', {rejectUnauthorized: false});
841
+
842
+ // Never do this:
843
+ await got('https://example.com', {rejectUnauthorized: false});
844
+ })();
845
+ ```
846
+
809
847
  #### Response
810
848
 
811
849
  The response object will typically be a [Node.js HTTP response stream](https://nodejs.org/api/http.html#http_class_http_incomingmessage), however, if returned from the cache it will be a [response-like object](https://github.com/lukechilds/responselike) which behaves in the same way.
@@ -918,7 +956,7 @@ Returns a [duplex stream](https://nodejs.org/api/stream.html#stream_class_stream
918
956
 
919
957
  ```js
920
958
  got.stream('https://github.com')
921
- .on('request', request => setTimeout(() => request.abort(), 50));
959
+ .on('request', request => setTimeout(() => request.destroy(), 50));
922
960
  ```
923
961
 
924
962
  ##### .on('response', response)
@@ -1132,17 +1170,12 @@ const handler = (options, next) => {
1132
1170
  const instance = got.extend({handlers: [handler]});
1133
1171
  ```
1134
1172
 
1135
- #### got.extend(...instances)
1173
+ #### got.extend(...options, ...instances, ...)
1136
1174
 
1137
1175
  Merges many instances into a single one:
1138
- - options are merged using [`got.mergeOptions()`](#gotmergeoptionsparentoptions-newoptions) (+ hooks are merged too),
1176
+ - options are merged using [`got.mergeOptions()`](#gotmergeoptionsparentoptions-newoptions) (including hooks),
1139
1177
  - handlers are stored in an array (you can access them through `instance.defaults.handlers`).
1140
1178
 
1141
- #### got.extend(...options, ...instances, ...)
1142
-
1143
- It's possible to combine options and instances.\
1144
- It gives the same effect as `got.extend(...options).extend(...instances)`:
1145
-
1146
1179
  ```js
1147
1180
  const a = {headers: {cat: 'meow'}};
1148
1181
  const b = got.extend({
@@ -1159,7 +1192,7 @@ got.extend(a, b);
1159
1192
  //=> {headers: {cat: 'meow', cow: 'moo'}}
1160
1193
  ```
1161
1194
 
1162
- #### got.mergeOptions(parentOptions, newOptions)
1195
+ #### got.mergeOptions(parent, ...sources)
1163
1196
 
1164
1197
  Extends parent options. Avoid using [object spread](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals) as it doesn't work recursively:
1165
1198
 
@@ -1171,16 +1204,24 @@ const b = {headers: {cow: 'moo', wolf: ['auuu']}};
1171
1204
  got.mergeOptions(a, b) // => {headers: {cat: 'meow', cow: 'moo', wolf: ['auuu']}}
1172
1205
  ```
1173
1206
 
1207
+ **Note:** Only Got options are merged! Custom user options should be defined via [`options.context`](#context).
1208
+
1174
1209
  Options are deeply merged to a new object. The value of each key is determined as follows:
1175
1210
 
1176
- - If the new property is set to `undefined`, it keeps the old one.
1177
- - If both properties are an instances of `URLSearchParams`, a new URLSearchParams instance is created. The values are merged using [`urlSearchParams.append(key, value)`](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams/append).
1178
- - If the parent property is an instance of `URL` and the new value is a `string` or `URL`, a new URL instance is created: [`new URL(new, parent)`](https://developer.mozilla.org/en-US/docs/Web/API/URL/URL#Syntax).
1211
+ - If the new property is not defined, the old value is used.
1212
+ - If the new property is explicitly set to `undefined`:
1213
+ - If the parent property is a plain `object`, the parent value is deeply cloned.
1214
+ - Otherwise, `undefined` is used.
1215
+ - If the parent value is an instance of `URLSearchParams`:
1216
+ - If the new value is a `string`, an `object` or an instance of `URLSearchParams`, a new `URLSearchParams` instance is created. The values are merged using [`urlSearchParams.append(key, value)`](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams/append). The keys defined in the new value override the keys defined in the parent value.
1217
+ - Otherwise, the only available value is `undefined`.
1179
1218
  - If the new property is a plain `object`:
1180
1219
  - If the parent property is a plain `object` too, both values are merged recursively into a new `object`.
1181
1220
  - Otherwise, only the new value is deeply cloned.
1182
1221
  - If the new property is an `Array`, it overwrites the old one with a deep clone of the new property.
1183
1222
  - Properties that are not enumerable, such as `context`, `body`, `json`, and `form`, will not be merged.
1223
+ - Otherwise, the new value is assigned to the key.
1224
+
1184
1225
  ```js
1185
1226
  const a = {json: {cat: 'meow'}};
1186
1227
  const b = {json: {cow: 'moo'}};
@@ -1188,7 +1229,6 @@ const b = {json: {cow: 'moo'}};
1188
1229
  got.mergeOptions(a, b);
1189
1230
  //=> {json: {cow: 'moo'}}
1190
1231
  ```
1191
- - Otherwise, the new value is assigned to the key.
1192
1232
 
1193
1233
  #### got.defaults
1194
1234
 
@@ -1203,7 +1243,7 @@ The Got defaults used in that instance.
1203
1243
  Type: `Function[]`\
1204
1244
  Default: `[]`
1205
1245
 
1206
- An array of functions. You execute them directly by calling `got()`. They are some sort of "global hooks" - these functions are called first. The last handler (*it's hidden*) is either [`asPromise`](source/as-promise.ts) or [`asStream`](source/as-stream.ts), depending on the `options.isStream` property.
1246
+ An array of functions. You execute them directly by calling `got()`. They are some sort of "global hooks" - these functions are called first. The last handler (*it's hidden*) is either [`asPromise`](source/core/as-promise/index.ts) or [`asStream`](source/core/index.ts), depending on the `options.isStream` property.
1207
1247
 
1208
1248
  Each handler takes two arguments:
1209
1249
 
@@ -1297,7 +1337,7 @@ When server response code is 2xx, and parsing body fails. Includes a `response`
1297
1337
 
1298
1338
  #### got.HTTPError
1299
1339
 
1300
- When the server response code is not 2xx. Includes a `response` property.
1340
+ When the server response code is not 2xx nor 3xx if `options.followRedirect` is `true`, but always except for 304. Includes a `response` property.
1301
1341
 
1302
1342
  #### got.MaxRedirectsError
1303
1343