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.
- package/dist/source/as-promise/calculate-retry-delay.d.ts +2 -1
- package/dist/source/as-promise/core.js +5 -0
- package/dist/source/as-promise/index.js +8 -5
- package/dist/source/as-promise/types.d.ts +1 -1
- package/dist/source/core/index.d.ts +7 -4
- package/dist/source/core/index.js +93 -76
- package/dist/source/core/utils/timed-out.js +1 -1
- package/dist/source/create.js +14 -6
- package/dist/source/index.js +1 -2
- package/dist/source/types.d.ts +4 -2
- package/package.json +11 -11
- package/readme.md +62 -22
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import { RetryFunction } from './types';
|
|
2
|
-
declare
|
|
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
|
-
|
|
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('
|
|
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
|
-
//
|
|
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,
|
|
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 =
|
|
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]?:
|
|
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:
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
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 (
|
|
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
|
|
375
|
-
if (
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
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`
|
|
444
|
-
options.
|
|
445
|
-
|
|
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) &&
|
|
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
|
-
//
|
|
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
|
-
|
|
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,
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
1043
|
-
|
|
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
|
|
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.');
|
package/dist/source/create.js
CHANGED
|
@@ -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
|
-
|
|
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
|
|
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) => {
|
package/dist/source/index.js
CHANGED
|
@@ -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:
|
|
59
|
+
dnsCache: undefined,
|
|
61
60
|
decompress: true,
|
|
62
61
|
throwHttpErrors: true,
|
|
63
62
|
followRedirect: true,
|
package/dist/source/types.d.ts
CHANGED
|
@@ -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
|
|
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.
|
|
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.
|
|
47
|
-
"@szmarczak/http-timer": "^4.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": "^
|
|
50
|
+
"cacheable-lookup": "^5.0.3",
|
|
51
51
|
"cacheable-request": "^7.0.1",
|
|
52
|
-
"decompress-response": "^
|
|
53
|
-
"get-stream": "^5.
|
|
54
|
-
"http2-wrapper": "^1.0.0-beta.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/
|
|
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: `
|
|
485
|
-
Default: `
|
|
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
|
-
|
|
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
|
|
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.
|
|
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) (
|
|
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(
|
|
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
|
|
1177
|
-
- If
|
|
1178
|
-
- If the parent property is
|
|
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/
|
|
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
|
|