got 14.6.6 → 15.0.1
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/index.d.ts +2 -2
- package/dist/source/as-promise/index.js +105 -85
- package/dist/source/as-promise/types.d.ts +10 -23
- package/dist/source/as-promise/types.js +1 -17
- package/dist/source/core/calculate-retry-delay.js +1 -4
- package/dist/source/core/diagnostics-channel.js +12 -21
- package/dist/source/core/errors.d.ts +2 -1
- package/dist/source/core/errors.js +10 -13
- package/dist/source/core/index.d.ts +19 -7
- package/dist/source/core/index.js +748 -327
- package/dist/source/core/options.d.ts +117 -116
- package/dist/source/core/options.js +620 -309
- package/dist/source/core/response.d.ts +5 -3
- package/dist/source/core/response.js +26 -3
- package/dist/source/core/timed-out.d.ts +1 -1
- package/dist/source/core/timed-out.js +4 -4
- package/dist/source/core/utils/defer-to-connect.js +5 -17
- package/dist/source/core/utils/get-body-size.d.ts +1 -1
- package/dist/source/core/utils/get-body-size.js +3 -20
- package/dist/source/core/utils/is-unix-socket-url.d.ts +1 -1
- package/dist/source/core/utils/is-unix-socket-url.js +3 -4
- package/dist/source/core/utils/proxy-events.d.ts +1 -1
- package/dist/source/core/utils/proxy-events.js +3 -3
- package/dist/source/core/utils/strip-url-auth.d.ts +1 -0
- package/dist/source/core/utils/strip-url-auth.js +9 -0
- package/dist/source/core/utils/timer.js +5 -7
- package/dist/source/core/utils/unhandle.js +1 -2
- package/dist/source/create.js +83 -27
- package/dist/source/index.d.ts +2 -3
- package/dist/source/index.js +0 -4
- package/dist/source/types.d.ts +39 -70
- package/package.json +34 -38
- package/readme.md +2 -5
- package/dist/source/core/utils/is-form-data.d.ts +0 -7
- package/dist/source/core/utils/is-form-data.js +0 -4
- package/dist/source/core/utils/url-to-options.d.ts +0 -14
- package/dist/source/core/utils/url-to-options.js +0 -22
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import process from 'node:process';
|
|
2
|
-
import { promisify, inspect } from 'node:util';
|
|
2
|
+
import { promisify, inspect, isDeepStrictEqual, } from 'node:util';
|
|
3
3
|
import { checkServerIdentity } from 'node:tls';
|
|
4
4
|
// DO NOT use destructuring for `https.request` and `http.request` as it's not compatible with `nock`.
|
|
5
5
|
import https from 'node:https';
|
|
@@ -8,8 +8,8 @@ import is, { assert } from '@sindresorhus/is';
|
|
|
8
8
|
import lowercaseKeys from 'lowercase-keys';
|
|
9
9
|
import CacheableLookup from 'cacheable-lookup';
|
|
10
10
|
import http2wrapper from 'http2-wrapper';
|
|
11
|
-
import { isFormData } from 'form-data-encoder';
|
|
12
11
|
import parseLinkHeader from './parse-link-header.js';
|
|
12
|
+
import { getUnixSocketPath } from './utils/is-unix-socket-url.js';
|
|
13
13
|
const [major, minor] = process.versions.node.split('.').map(Number);
|
|
14
14
|
/**
|
|
15
15
|
Generic helper that wraps any assertion function to add context to error messages.
|
|
@@ -43,9 +43,68 @@ function assertPlainObject(optionName, value) {
|
|
|
43
43
|
assert.plainObject(value);
|
|
44
44
|
});
|
|
45
45
|
}
|
|
46
|
+
export function isSameOrigin(previousUrl, nextUrl) {
|
|
47
|
+
return previousUrl.origin === nextUrl.origin
|
|
48
|
+
&& getUnixSocketPath(previousUrl) === getUnixSocketPath(nextUrl);
|
|
49
|
+
}
|
|
50
|
+
export const crossOriginStripHeaders = ['host', 'cookie', 'cookie2', 'authorization', 'proxy-authorization'];
|
|
51
|
+
const bodyHeaderNames = ['content-length', 'content-encoding', 'content-language', 'content-location', 'content-type', 'transfer-encoding'];
|
|
52
|
+
function usesUnixSocket(url) {
|
|
53
|
+
return url.protocol === 'unix:' || getUnixSocketPath(url) !== undefined;
|
|
54
|
+
}
|
|
55
|
+
function hasCredentialInUrl(url, credential) {
|
|
56
|
+
if (url instanceof URL) {
|
|
57
|
+
return url[credential] !== '';
|
|
58
|
+
}
|
|
59
|
+
if (!is.string(url)) {
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
try {
|
|
63
|
+
return new URL(url)[credential] !== '';
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
export const hasExplicitCredentialInUrlChange = (changedState, url, credential) => (changedState.has(credential)
|
|
70
|
+
|| (changedState.has('url') && url?.[credential] !== ''));
|
|
71
|
+
const hasProtocolSlashes = (value) => /^[a-z][\d+\-.a-z]*:\/\//iv.test(value);
|
|
72
|
+
const hasHttpProtocolWithoutSlashes = (value) => /^https?:(?!\/\/)/iv.test(value);
|
|
73
|
+
export function applyUrlOverride(options, url, { username, password } = {}) {
|
|
74
|
+
if (is.string(url) && options.url) {
|
|
75
|
+
url = new URL(url, options.url).toString();
|
|
76
|
+
}
|
|
77
|
+
options.prefixUrl = '';
|
|
78
|
+
options.url = url;
|
|
79
|
+
if (username !== undefined) {
|
|
80
|
+
options.username = username;
|
|
81
|
+
}
|
|
82
|
+
if (password !== undefined) {
|
|
83
|
+
options.password = password;
|
|
84
|
+
}
|
|
85
|
+
return options.url;
|
|
86
|
+
}
|
|
87
|
+
function assertValidHeaderName(name) {
|
|
88
|
+
if (name.startsWith(':')) {
|
|
89
|
+
throw new TypeError(`HTTP/2 pseudo-headers are not supported in \`options.headers\`: ${name}`);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
Safely assign own properties from source to target, skipping `__proto__` to prevent prototype pollution from JSON.parse'd input.
|
|
94
|
+
*/
|
|
95
|
+
function safeObjectAssign(target, source) {
|
|
96
|
+
for (const key of Object.keys(source)) {
|
|
97
|
+
if (key === '__proto__') {
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
target[key] = source[key];
|
|
101
|
+
}
|
|
102
|
+
}
|
|
46
103
|
function validateSearchParameters(searchParameters) {
|
|
47
|
-
|
|
48
|
-
|
|
104
|
+
for (const key of Object.keys(searchParameters)) {
|
|
105
|
+
if (key === '__proto__') {
|
|
106
|
+
continue;
|
|
107
|
+
}
|
|
49
108
|
const value = searchParameters[key];
|
|
50
109
|
assertAny(`searchParams.${key}`, [is.string, is.number, is.boolean, is.null, is.undefined], value);
|
|
51
110
|
}
|
|
@@ -138,7 +197,7 @@ const defaultInternals = {
|
|
|
138
197
|
password: '',
|
|
139
198
|
http2: false,
|
|
140
199
|
allowGetBody: false,
|
|
141
|
-
copyPipedHeaders:
|
|
200
|
+
copyPipedHeaders: false,
|
|
142
201
|
headers: {
|
|
143
202
|
'user-agent': 'got (https://github.com/sindresorhus/got)',
|
|
144
203
|
},
|
|
@@ -182,8 +241,7 @@ const defaultInternals = {
|
|
|
182
241
|
calculateDelay: ({ computedValue }) => computedValue,
|
|
183
242
|
backoffLimit: Number.POSITIVE_INFINITY,
|
|
184
243
|
noise: 100,
|
|
185
|
-
|
|
186
|
-
enforceRetryRules: false,
|
|
244
|
+
enforceRetryRules: true,
|
|
187
245
|
},
|
|
188
246
|
localAddress: undefined,
|
|
189
247
|
method: 'GET',
|
|
@@ -235,8 +293,9 @@ const defaultInternals = {
|
|
|
235
293
|
const parsed = parseLinkHeader(rawLinkHeader);
|
|
236
294
|
const next = parsed.find(entry => entry.parameters.rel === 'next' || entry.parameters.rel === '"next"');
|
|
237
295
|
if (next) {
|
|
296
|
+
const baseUrl = response.request.options.url ?? response.url;
|
|
238
297
|
return {
|
|
239
|
-
url: new URL(next.reference,
|
|
298
|
+
url: new URL(next.reference, baseUrl),
|
|
240
299
|
};
|
|
241
300
|
}
|
|
242
301
|
return false;
|
|
@@ -252,7 +311,7 @@ const defaultInternals = {
|
|
|
252
311
|
maxHeaderSize: undefined,
|
|
253
312
|
signal: undefined,
|
|
254
313
|
enableUnixSockets: false,
|
|
255
|
-
strictContentLength:
|
|
314
|
+
strictContentLength: true,
|
|
256
315
|
};
|
|
257
316
|
const cloneInternals = (internals) => {
|
|
258
317
|
const { hooks, retry } = internals;
|
|
@@ -285,27 +344,24 @@ const cloneInternals = (internals) => {
|
|
|
285
344
|
return result;
|
|
286
345
|
};
|
|
287
346
|
const cloneRaw = (raw) => {
|
|
288
|
-
const { hooks, retry } = raw;
|
|
289
347
|
const result = { ...raw };
|
|
290
|
-
if (is.object(raw.context)) {
|
|
348
|
+
if (Object.hasOwn(raw, 'context') && is.object(raw.context)) {
|
|
291
349
|
result.context = { ...raw.context };
|
|
292
350
|
}
|
|
293
|
-
if (is.object(raw.cacheOptions)) {
|
|
351
|
+
if (Object.hasOwn(raw, 'cacheOptions') && is.object(raw.cacheOptions)) {
|
|
294
352
|
result.cacheOptions = { ...raw.cacheOptions };
|
|
295
353
|
}
|
|
296
|
-
if (is.object(raw.https)) {
|
|
354
|
+
if (Object.hasOwn(raw, 'https') && is.object(raw.https)) {
|
|
297
355
|
result.https = { ...raw.https };
|
|
298
356
|
}
|
|
299
|
-
if (is.object(raw.
|
|
300
|
-
result.cacheOptions = { ...result.cacheOptions };
|
|
301
|
-
}
|
|
302
|
-
if (is.object(raw.agent)) {
|
|
357
|
+
if (Object.hasOwn(raw, 'agent') && is.object(raw.agent)) {
|
|
303
358
|
result.agent = { ...raw.agent };
|
|
304
359
|
}
|
|
305
|
-
if (is.object(raw.headers)) {
|
|
360
|
+
if (Object.hasOwn(raw, 'headers') && is.object(raw.headers)) {
|
|
306
361
|
result.headers = { ...raw.headers };
|
|
307
362
|
}
|
|
308
|
-
if (is.object(retry)) {
|
|
363
|
+
if (Object.hasOwn(raw, 'retry') && is.object(raw.retry)) {
|
|
364
|
+
const { retry } = raw;
|
|
309
365
|
result.retry = { ...retry };
|
|
310
366
|
if (is.array(retry.errorCodes)) {
|
|
311
367
|
result.retry.errorCodes = [...retry.errorCodes];
|
|
@@ -317,10 +373,11 @@ const cloneRaw = (raw) => {
|
|
|
317
373
|
result.retry.statusCodes = [...retry.statusCodes];
|
|
318
374
|
}
|
|
319
375
|
}
|
|
320
|
-
if (is.object(raw.timeout)) {
|
|
376
|
+
if (Object.hasOwn(raw, 'timeout') && is.object(raw.timeout)) {
|
|
321
377
|
result.timeout = { ...raw.timeout };
|
|
322
378
|
}
|
|
323
|
-
if (is.object(hooks)) {
|
|
379
|
+
if (Object.hasOwn(raw, 'hooks') && is.object(raw.hooks)) {
|
|
380
|
+
const { hooks } = raw;
|
|
324
381
|
result.hooks = {
|
|
325
382
|
...hooks,
|
|
326
383
|
};
|
|
@@ -346,7 +403,7 @@ const cloneRaw = (raw) => {
|
|
|
346
403
|
result.hooks.afterResponse = [...hooks.afterResponse];
|
|
347
404
|
}
|
|
348
405
|
}
|
|
349
|
-
if (raw.searchParams) {
|
|
406
|
+
if (Object.hasOwn(raw, 'searchParams') && raw.searchParams) {
|
|
350
407
|
if (is.string(raw.searchParams)) {
|
|
351
408
|
result.searchParams = raw.searchParams;
|
|
352
409
|
}
|
|
@@ -357,17 +414,34 @@ const cloneRaw = (raw) => {
|
|
|
357
414
|
result.searchParams = { ...raw.searchParams };
|
|
358
415
|
}
|
|
359
416
|
}
|
|
360
|
-
if (is.object(raw.pagination)) {
|
|
417
|
+
if (Object.hasOwn(raw, 'pagination') && is.object(raw.pagination)) {
|
|
361
418
|
result.pagination = { ...raw.pagination };
|
|
362
419
|
}
|
|
363
420
|
return result;
|
|
364
421
|
};
|
|
365
422
|
const getHttp2TimeoutOption = (internals) => {
|
|
366
423
|
const delays = [internals.timeout.socket, internals.timeout.connect, internals.timeout.lookup, internals.timeout.request, internals.timeout.secureConnect].filter(delay => typeof delay === 'number');
|
|
367
|
-
|
|
368
|
-
|
|
424
|
+
return delays.length > 0 ? Math.min(...delays) : undefined;
|
|
425
|
+
};
|
|
426
|
+
const trackStateMutation = (trackedStateMutations, name) => {
|
|
427
|
+
trackedStateMutations?.add(name);
|
|
428
|
+
};
|
|
429
|
+
const addExplicitHeader = (explicitHeaders, name) => {
|
|
430
|
+
explicitHeaders.add(name);
|
|
431
|
+
};
|
|
432
|
+
const markHeaderAsExplicit = (explicitHeaders, trackedStateMutations, name) => {
|
|
433
|
+
addExplicitHeader(explicitHeaders, name);
|
|
434
|
+
trackStateMutation(trackedStateMutations, name);
|
|
435
|
+
};
|
|
436
|
+
const trackReplacedHeaderMutations = (trackedStateMutations, previousHeaders, nextHeaders) => {
|
|
437
|
+
if (!trackedStateMutations) {
|
|
438
|
+
return;
|
|
439
|
+
}
|
|
440
|
+
for (const header of new Set([...Object.keys(previousHeaders), ...Object.keys(nextHeaders)])) {
|
|
441
|
+
if (previousHeaders[header] !== nextHeaders[header]) {
|
|
442
|
+
trackStateMutation(trackedStateMutations, header);
|
|
443
|
+
}
|
|
369
444
|
}
|
|
370
|
-
return undefined;
|
|
371
445
|
};
|
|
372
446
|
const init = (options, withOptions, self) => {
|
|
373
447
|
const initHooks = options.hooks?.init;
|
|
@@ -377,11 +451,15 @@ const init = (options, withOptions, self) => {
|
|
|
377
451
|
}
|
|
378
452
|
}
|
|
379
453
|
};
|
|
454
|
+
// Keys never merged: got.extend() internals, url (passed as first arg), control flags, security
|
|
455
|
+
const nonMergeableKeys = new Set(['mutableDefaults', 'handlers', 'url', 'preserveHooks', 'isStream', '__proto__']);
|
|
380
456
|
export default class Options {
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
457
|
+
#internals;
|
|
458
|
+
#headersProxy;
|
|
459
|
+
#merging = false;
|
|
460
|
+
#init;
|
|
461
|
+
#explicitHeaders;
|
|
462
|
+
#trackedStateMutations;
|
|
385
463
|
constructor(input, options, defaults) {
|
|
386
464
|
assertAny('input', [is.string, is.urlInstance, is.object, is.undefined], input);
|
|
387
465
|
assertAny('options', [is.object, is.undefined], options);
|
|
@@ -389,8 +467,17 @@ export default class Options {
|
|
|
389
467
|
if (input instanceof Options || options instanceof Options) {
|
|
390
468
|
throw new TypeError('The defaults must be passed as the third argument');
|
|
391
469
|
}
|
|
392
|
-
|
|
393
|
-
|
|
470
|
+
if (defaults) {
|
|
471
|
+
this.#internals = cloneInternals(defaults.#internals);
|
|
472
|
+
this.#init = [...defaults.#init];
|
|
473
|
+
this.#explicitHeaders = new Set(defaults.#explicitHeaders);
|
|
474
|
+
}
|
|
475
|
+
else {
|
|
476
|
+
this.#internals = cloneInternals(defaultInternals);
|
|
477
|
+
this.#init = [];
|
|
478
|
+
this.#explicitHeaders = new Set();
|
|
479
|
+
}
|
|
480
|
+
this.#headersProxy = this.#createHeadersProxy();
|
|
394
481
|
// This rule allows `finally` to be considered more important.
|
|
395
482
|
// Meaning no matter the error thrown in the `try` block,
|
|
396
483
|
// if `finally` throws then the `finally` error will be thrown.
|
|
@@ -399,7 +486,7 @@ export default class Options {
|
|
|
399
486
|
// would get merged. Instead we set the `searchParams` first, then
|
|
400
487
|
// `url.searchParams` is overwritten as expected.
|
|
401
488
|
//
|
|
402
|
-
/* eslint-disable no-unsafe-finally */
|
|
489
|
+
/* eslint-disable no-unsafe-finally -- `finally` is used intentionally here to ensure `url` is always set last, overwriting any merged searchParams */
|
|
403
490
|
try {
|
|
404
491
|
if (is.plainObject(input)) {
|
|
405
492
|
try {
|
|
@@ -440,9 +527,9 @@ export default class Options {
|
|
|
440
527
|
return;
|
|
441
528
|
}
|
|
442
529
|
if (options instanceof Options) {
|
|
443
|
-
// Create a copy of the
|
|
530
|
+
// Create a copy of the #init array to avoid infinite loop
|
|
444
531
|
// when merging an Options instance with itself
|
|
445
|
-
const initArray = [...options
|
|
532
|
+
const initArray = [...options.#init];
|
|
446
533
|
for (const init of initArray) {
|
|
447
534
|
this.merge(init);
|
|
448
535
|
}
|
|
@@ -451,24 +538,11 @@ export default class Options {
|
|
|
451
538
|
options = cloneRaw(options);
|
|
452
539
|
init(this, options, this);
|
|
453
540
|
init(options, options, this);
|
|
454
|
-
this
|
|
455
|
-
// Always merge `isStream` first
|
|
456
|
-
if ('isStream' in options) {
|
|
457
|
-
this.isStream = options.isStream;
|
|
458
|
-
}
|
|
541
|
+
this.#merging = true;
|
|
459
542
|
try {
|
|
460
543
|
let push = false;
|
|
461
|
-
for (const key
|
|
462
|
-
|
|
463
|
-
if (key === 'mutableDefaults' || key === 'handlers') {
|
|
464
|
-
continue;
|
|
465
|
-
}
|
|
466
|
-
// Never merge `url`
|
|
467
|
-
if (key === 'url') {
|
|
468
|
-
continue;
|
|
469
|
-
}
|
|
470
|
-
// Never merge `preserveHooks` - it's a control flag, not a persistent option
|
|
471
|
-
if (key === 'preserveHooks') {
|
|
544
|
+
for (const key of Object.keys(options)) {
|
|
545
|
+
if (nonMergeableKeys.has(key)) {
|
|
472
546
|
continue;
|
|
473
547
|
}
|
|
474
548
|
if (!(key in this)) {
|
|
@@ -484,11 +558,11 @@ export default class Options {
|
|
|
484
558
|
push = true;
|
|
485
559
|
}
|
|
486
560
|
if (push) {
|
|
487
|
-
this.
|
|
561
|
+
this.#init.push(options);
|
|
488
562
|
}
|
|
489
563
|
}
|
|
490
564
|
finally {
|
|
491
|
-
this
|
|
565
|
+
this.#merging = false;
|
|
492
566
|
}
|
|
493
567
|
}
|
|
494
568
|
/**
|
|
@@ -498,11 +572,11 @@ export default class Options {
|
|
|
498
572
|
@default http.request | https.request
|
|
499
573
|
*/
|
|
500
574
|
get request() {
|
|
501
|
-
return this.
|
|
575
|
+
return this.#internals.request;
|
|
502
576
|
}
|
|
503
577
|
set request(value) {
|
|
504
578
|
assertAny('request', [is.function, is.undefined], value);
|
|
505
|
-
this.
|
|
579
|
+
this.#internals.request = value;
|
|
506
580
|
}
|
|
507
581
|
/**
|
|
508
582
|
An object representing `http`, `https` and `http2` keys for [`http.Agent`](https://nodejs.org/api/http.html#http_class_http_agent), [`https.Agent`](https://nodejs.org/api/https.html#https_class_https_agent) and [`http2wrapper.Agent`](https://github.com/szmarczak/http2-wrapper#new-http2agentoptions) instance.
|
|
@@ -527,47 +601,49 @@ export default class Options {
|
|
|
527
601
|
```
|
|
528
602
|
*/
|
|
529
603
|
get agent() {
|
|
530
|
-
return this.
|
|
604
|
+
return this.#internals.agent;
|
|
531
605
|
}
|
|
532
606
|
set agent(value) {
|
|
533
607
|
assertPlainObject('agent', value);
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
608
|
+
for (const key of Object.keys(value)) {
|
|
609
|
+
if (key === '__proto__') {
|
|
610
|
+
continue;
|
|
611
|
+
}
|
|
612
|
+
if (!(key in this.#internals.agent)) {
|
|
537
613
|
throw new TypeError(`Unexpected agent option: ${key}`);
|
|
538
614
|
}
|
|
539
615
|
// @ts-expect-error - No idea why `value[key]` doesn't work here.
|
|
540
616
|
assertAny(`agent.${key}`, [is.object, is.undefined, (v) => v === false], value[key]);
|
|
541
617
|
}
|
|
542
|
-
if (this
|
|
543
|
-
|
|
618
|
+
if (this.#merging) {
|
|
619
|
+
safeObjectAssign(this.#internals.agent, value);
|
|
544
620
|
}
|
|
545
621
|
else {
|
|
546
|
-
this.
|
|
622
|
+
this.#internals.agent = { ...value };
|
|
547
623
|
}
|
|
548
624
|
}
|
|
549
625
|
get h2session() {
|
|
550
|
-
return this.
|
|
626
|
+
return this.#internals.h2session;
|
|
551
627
|
}
|
|
552
628
|
set h2session(value) {
|
|
553
|
-
this.
|
|
629
|
+
this.#internals.h2session = value;
|
|
554
630
|
}
|
|
555
631
|
/**
|
|
556
632
|
Decompress the response automatically.
|
|
557
633
|
|
|
558
634
|
This will set the `accept-encoding` header to `gzip, deflate, br` unless you set it yourself.
|
|
559
635
|
|
|
560
|
-
If this is disabled, a compressed response is returned as a `
|
|
636
|
+
If this is disabled, a compressed response is returned as a `Uint8Array`.
|
|
561
637
|
This may be useful if you want to handle decompression yourself or stream the raw compressed data.
|
|
562
638
|
|
|
563
639
|
@default true
|
|
564
640
|
*/
|
|
565
641
|
get decompress() {
|
|
566
|
-
return this.
|
|
642
|
+
return this.#internals.decompress;
|
|
567
643
|
}
|
|
568
644
|
set decompress(value) {
|
|
569
645
|
assert.boolean(value);
|
|
570
|
-
this.
|
|
646
|
+
this.#internals.decompress = value;
|
|
571
647
|
}
|
|
572
648
|
/**
|
|
573
649
|
Milliseconds to wait for the server to end the response before aborting the request with `got.TimeoutError` error (a.k.a. `request` property).
|
|
@@ -587,23 +663,25 @@ export default class Options {
|
|
|
587
663
|
get timeout() {
|
|
588
664
|
// We always return `Delays` here.
|
|
589
665
|
// It has to be `Delays | number`, otherwise TypeScript will error because the getter and the setter have incompatible types.
|
|
590
|
-
return this.
|
|
666
|
+
return this.#internals.timeout;
|
|
591
667
|
}
|
|
592
668
|
set timeout(value) {
|
|
593
669
|
assertPlainObject('timeout', value);
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
670
|
+
for (const key of Object.keys(value)) {
|
|
671
|
+
if (key === '__proto__') {
|
|
672
|
+
continue;
|
|
673
|
+
}
|
|
674
|
+
if (!(key in this.#internals.timeout)) {
|
|
597
675
|
throw new Error(`Unexpected timeout option: ${key}`);
|
|
598
676
|
}
|
|
599
677
|
// @ts-expect-error - No idea why `value[key]` doesn't work here.
|
|
600
678
|
assertAny(`timeout.${key}`, [is.number, is.undefined], value[key]);
|
|
601
679
|
}
|
|
602
|
-
if (this
|
|
603
|
-
|
|
680
|
+
if (this.#merging) {
|
|
681
|
+
safeObjectAssign(this.#internals.timeout, value);
|
|
604
682
|
}
|
|
605
683
|
else {
|
|
606
|
-
this.
|
|
684
|
+
this.#internals.timeout = { ...value };
|
|
607
685
|
}
|
|
608
686
|
}
|
|
609
687
|
/**
|
|
@@ -648,23 +726,23 @@ export default class Options {
|
|
|
648
726
|
get prefixUrl() {
|
|
649
727
|
// We always return `string` here.
|
|
650
728
|
// It has to be `string | URL`, otherwise TypeScript will error because the getter and the setter have incompatible types.
|
|
651
|
-
return this.
|
|
729
|
+
return this.#internals.prefixUrl;
|
|
652
730
|
}
|
|
653
731
|
set prefixUrl(value) {
|
|
654
732
|
assertAny('prefixUrl', [is.string, is.urlInstance], value);
|
|
655
733
|
if (value === '') {
|
|
656
|
-
this.
|
|
734
|
+
this.#internals.prefixUrl = '';
|
|
657
735
|
return;
|
|
658
736
|
}
|
|
659
737
|
value = value.toString();
|
|
660
738
|
if (!value.endsWith('/')) {
|
|
661
739
|
value += '/';
|
|
662
740
|
}
|
|
663
|
-
if (this.
|
|
664
|
-
const { href } = this.
|
|
665
|
-
this.
|
|
741
|
+
if (this.#internals.prefixUrl && this.#internals.url) {
|
|
742
|
+
const { href } = this.#internals.url;
|
|
743
|
+
this.#internals.url.href = value + href.slice(this.#internals.prefixUrl.length);
|
|
666
744
|
}
|
|
667
|
-
this.
|
|
745
|
+
this.#internals.prefixUrl = value;
|
|
668
746
|
}
|
|
669
747
|
/**
|
|
670
748
|
__Note #1__: The `body` option cannot be used with the `json` or `form` option.
|
|
@@ -675,7 +753,7 @@ export default class Options {
|
|
|
675
753
|
|
|
676
754
|
__Note #4__: This option is not enumerable and will not be merged with the instance defaults.
|
|
677
755
|
|
|
678
|
-
The `content-length` header will be automatically set if `body` is a `string` / `
|
|
756
|
+
The `content-length` header will be automatically set if `body` is a `string` / `Uint8Array` / typed array, and `content-length` and `transfer-encoding` are not manually set in `options.headers`.
|
|
679
757
|
|
|
680
758
|
Since Got 12, the `content-length` is not automatically set when `body` is a `fs.createReadStream`.
|
|
681
759
|
|
|
@@ -697,18 +775,19 @@ export default class Options {
|
|
|
697
775
|
```
|
|
698
776
|
*/
|
|
699
777
|
get body() {
|
|
700
|
-
return this.
|
|
778
|
+
return this.#internals.body;
|
|
701
779
|
}
|
|
702
780
|
set body(value) {
|
|
703
|
-
assertAny('body', [is.string, is.buffer, is.nodeStream, is.generator, is.asyncGenerator, is.iterable, is.asyncIterable,
|
|
781
|
+
assertAny('body', [is.string, is.buffer, is.nodeStream, is.generator, is.asyncGenerator, is.iterable, is.asyncIterable, is.typedArray, is.undefined], value);
|
|
704
782
|
if (is.nodeStream(value)) {
|
|
705
783
|
assert.truthy(value.readable);
|
|
706
784
|
}
|
|
707
785
|
if (value !== undefined) {
|
|
708
|
-
assert.undefined(this.
|
|
709
|
-
assert.undefined(this.
|
|
786
|
+
assert.undefined(this.#internals.form);
|
|
787
|
+
assert.undefined(this.#internals.json);
|
|
710
788
|
}
|
|
711
|
-
this.
|
|
789
|
+
this.#internals.body = value;
|
|
790
|
+
trackStateMutation(this.#trackedStateMutations, 'body');
|
|
712
791
|
}
|
|
713
792
|
/**
|
|
714
793
|
The form body is converted to a query string using [`(new URLSearchParams(object)).toString()`](https://nodejs.org/api/url.html#url_constructor_new_urlsearchparams_obj).
|
|
@@ -720,15 +799,16 @@ export default class Options {
|
|
|
720
799
|
__Note #2__: This option is not enumerable and will not be merged with the instance defaults.
|
|
721
800
|
*/
|
|
722
801
|
get form() {
|
|
723
|
-
return this.
|
|
802
|
+
return this.#internals.form;
|
|
724
803
|
}
|
|
725
804
|
set form(value) {
|
|
726
805
|
assertAny('form', [is.plainObject, is.undefined], value);
|
|
727
806
|
if (value !== undefined) {
|
|
728
|
-
assert.undefined(this.
|
|
729
|
-
assert.undefined(this.
|
|
807
|
+
assert.undefined(this.#internals.body);
|
|
808
|
+
assert.undefined(this.#internals.json);
|
|
730
809
|
}
|
|
731
|
-
this.
|
|
810
|
+
this.#internals.form = value;
|
|
811
|
+
trackStateMutation(this.#trackedStateMutations, 'form');
|
|
732
812
|
}
|
|
733
813
|
/**
|
|
734
814
|
JSON request body. If the `content-type` header is not set, it will be set to `application/json`.
|
|
@@ -740,14 +820,15 @@ export default class Options {
|
|
|
740
820
|
__Note #2__: This option is not enumerable and will not be merged with the instance defaults.
|
|
741
821
|
*/
|
|
742
822
|
get json() {
|
|
743
|
-
return this.
|
|
823
|
+
return this.#internals.json;
|
|
744
824
|
}
|
|
745
825
|
set json(value) {
|
|
746
826
|
if (value !== undefined) {
|
|
747
|
-
assert.undefined(this.
|
|
748
|
-
assert.undefined(this.
|
|
827
|
+
assert.undefined(this.#internals.body);
|
|
828
|
+
assert.undefined(this.#internals.form);
|
|
749
829
|
}
|
|
750
|
-
this.
|
|
830
|
+
this.#internals.json = value;
|
|
831
|
+
trackStateMutation(this.#trackedStateMutations, 'json');
|
|
751
832
|
}
|
|
752
833
|
/**
|
|
753
834
|
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).
|
|
@@ -768,24 +849,34 @@ export default class Options {
|
|
|
768
849
|
```
|
|
769
850
|
*/
|
|
770
851
|
get url() {
|
|
771
|
-
return this.
|
|
852
|
+
return this.#internals.url;
|
|
772
853
|
}
|
|
773
854
|
set url(value) {
|
|
774
855
|
assertAny('url', [is.string, is.urlInstance, is.undefined], value);
|
|
775
856
|
if (value === undefined) {
|
|
776
|
-
this.
|
|
857
|
+
this.#internals.url = undefined;
|
|
858
|
+
trackStateMutation(this.#trackedStateMutations, 'url');
|
|
777
859
|
return;
|
|
778
860
|
}
|
|
779
861
|
if (is.string(value) && value.startsWith('/')) {
|
|
780
862
|
throw new Error('`url` must not start with a slash');
|
|
781
863
|
}
|
|
782
|
-
// Detect if URL is already absolute (has a protocol/scheme)
|
|
783
864
|
const valueString = value.toString();
|
|
784
|
-
|
|
865
|
+
if (is.string(value)
|
|
866
|
+
&& !this.prefixUrl
|
|
867
|
+
&& hasHttpProtocolWithoutSlashes(valueString)) {
|
|
868
|
+
throw new Error('`url` protocol must be followed by `//`');
|
|
869
|
+
}
|
|
870
|
+
// Detect if URL is already absolute (has a protocol/scheme)
|
|
871
|
+
const isAbsolute = is.urlInstance(value) || hasProtocolSlashes(valueString);
|
|
785
872
|
// Only concatenate prefixUrl if the URL is relative
|
|
786
873
|
const urlString = isAbsolute ? valueString : `${this.prefixUrl}${valueString}`;
|
|
787
874
|
const url = new URL(urlString);
|
|
788
|
-
this.
|
|
875
|
+
this.#internals.url = url;
|
|
876
|
+
trackStateMutation(this.#trackedStateMutations, 'url');
|
|
877
|
+
if (usesUnixSocket(url) && !this.#internals.enableUnixSockets) {
|
|
878
|
+
throw new Error('Using UNIX domain sockets but option `enableUnixSockets` is not enabled');
|
|
879
|
+
}
|
|
789
880
|
if (url.protocol === 'unix:') {
|
|
790
881
|
url.href = `http://unix${url.pathname}${url.search}`;
|
|
791
882
|
}
|
|
@@ -794,37 +885,18 @@ export default class Options {
|
|
|
794
885
|
error.code = 'ERR_UNSUPPORTED_PROTOCOL';
|
|
795
886
|
throw error;
|
|
796
887
|
}
|
|
797
|
-
if (this.
|
|
798
|
-
url.username = this.
|
|
799
|
-
this.
|
|
888
|
+
if (this.#internals.username) {
|
|
889
|
+
url.username = this.#internals.username;
|
|
890
|
+
this.#internals.username = '';
|
|
800
891
|
}
|
|
801
|
-
if (this.
|
|
802
|
-
url.password = this.
|
|
803
|
-
this.
|
|
892
|
+
if (this.#internals.password) {
|
|
893
|
+
url.password = this.#internals.password;
|
|
894
|
+
this.#internals.password = '';
|
|
804
895
|
}
|
|
805
|
-
if (this.
|
|
806
|
-
url.search = this.
|
|
807
|
-
this.
|
|
808
|
-
}
|
|
809
|
-
if (url.hostname === 'unix') {
|
|
810
|
-
if (!this._internals.enableUnixSockets) {
|
|
811
|
-
throw new Error('Using UNIX domain sockets but option `enableUnixSockets` is not enabled');
|
|
812
|
-
}
|
|
813
|
-
const matches = /(?<socketPath>.+?):(?<path>.+)/.exec(`${url.pathname}${url.search}`);
|
|
814
|
-
if (matches?.groups) {
|
|
815
|
-
const { socketPath, path } = matches.groups;
|
|
816
|
-
this._unixOptions = {
|
|
817
|
-
socketPath,
|
|
818
|
-
path,
|
|
819
|
-
host: '',
|
|
820
|
-
};
|
|
821
|
-
}
|
|
822
|
-
else {
|
|
823
|
-
this._unixOptions = undefined;
|
|
824
|
-
}
|
|
825
|
-
return;
|
|
896
|
+
if (this.#internals.searchParams) {
|
|
897
|
+
url.search = this.#internals.searchParams.toString();
|
|
898
|
+
this.#internals.searchParams = undefined;
|
|
826
899
|
}
|
|
827
|
-
this._unixOptions = undefined;
|
|
828
900
|
}
|
|
829
901
|
/**
|
|
830
902
|
Cookie support. You don't have to care about parsing or how to store them.
|
|
@@ -832,28 +904,26 @@ export default class Options {
|
|
|
832
904
|
__Note__: If you provide this option, `options.headers.cookie` will be overridden.
|
|
833
905
|
*/
|
|
834
906
|
get cookieJar() {
|
|
835
|
-
return this.
|
|
907
|
+
return this.#internals.cookieJar;
|
|
836
908
|
}
|
|
837
909
|
set cookieJar(value) {
|
|
838
910
|
assertAny('cookieJar', [is.object, is.undefined], value);
|
|
839
911
|
if (value === undefined) {
|
|
840
|
-
this.
|
|
912
|
+
this.#internals.cookieJar = undefined;
|
|
841
913
|
return;
|
|
842
914
|
}
|
|
843
|
-
|
|
915
|
+
const { setCookie, getCookieString } = value;
|
|
844
916
|
assert.function(setCookie);
|
|
845
917
|
assert.function(getCookieString);
|
|
846
918
|
/* istanbul ignore next: Horrible `tough-cookie` v3 check */
|
|
847
919
|
if (setCookie.length === 4 && getCookieString.length === 0) {
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
setCookie,
|
|
852
|
-
getCookieString: getCookieString,
|
|
920
|
+
this.#internals.cookieJar = {
|
|
921
|
+
setCookie: promisify(setCookie.bind(value)),
|
|
922
|
+
getCookieString: promisify(getCookieString.bind(value)),
|
|
853
923
|
};
|
|
854
924
|
}
|
|
855
925
|
else {
|
|
856
|
-
this.
|
|
926
|
+
this.#internals.cookieJar = value;
|
|
857
927
|
}
|
|
858
928
|
}
|
|
859
929
|
/**
|
|
@@ -875,11 +945,11 @@ export default class Options {
|
|
|
875
945
|
```
|
|
876
946
|
*/
|
|
877
947
|
get signal() {
|
|
878
|
-
return this.
|
|
948
|
+
return this.#internals.signal;
|
|
879
949
|
}
|
|
880
950
|
set signal(value) {
|
|
881
|
-
|
|
882
|
-
this.
|
|
951
|
+
assertAny('signal', [is.object, is.undefined], value);
|
|
952
|
+
this.#internals.signal = value;
|
|
883
953
|
}
|
|
884
954
|
/**
|
|
885
955
|
Ignore invalid cookies instead of throwing an error.
|
|
@@ -888,11 +958,11 @@ export default class Options {
|
|
|
888
958
|
@default false
|
|
889
959
|
*/
|
|
890
960
|
get ignoreInvalidCookies() {
|
|
891
|
-
return this.
|
|
961
|
+
return this.#internals.ignoreInvalidCookies;
|
|
892
962
|
}
|
|
893
963
|
set ignoreInvalidCookies(value) {
|
|
894
964
|
assert.boolean(value);
|
|
895
|
-
this.
|
|
965
|
+
this.#internals.ignoreInvalidCookies = value;
|
|
896
966
|
}
|
|
897
967
|
/**
|
|
898
968
|
Query string that will be added to the request URL.
|
|
@@ -913,19 +983,17 @@ export default class Options {
|
|
|
913
983
|
```
|
|
914
984
|
*/
|
|
915
985
|
get searchParams() {
|
|
916
|
-
if (this.
|
|
917
|
-
return this.
|
|
986
|
+
if (this.#internals.url) {
|
|
987
|
+
return this.#internals.url.searchParams;
|
|
918
988
|
}
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
}
|
|
922
|
-
return this._internals.searchParams;
|
|
989
|
+
this.#internals.searchParams ??= new URLSearchParams();
|
|
990
|
+
return this.#internals.searchParams;
|
|
923
991
|
}
|
|
924
992
|
set searchParams(value) {
|
|
925
993
|
assertAny('searchParams', [is.string, is.object, is.undefined], value);
|
|
926
|
-
const url = this.
|
|
994
|
+
const url = this.#internals.url;
|
|
927
995
|
if (value === undefined) {
|
|
928
|
-
this.
|
|
996
|
+
this.#internals.searchParams = undefined;
|
|
929
997
|
if (url) {
|
|
930
998
|
url.search = '';
|
|
931
999
|
}
|
|
@@ -942,8 +1010,10 @@ export default class Options {
|
|
|
942
1010
|
else {
|
|
943
1011
|
validateSearchParameters(value);
|
|
944
1012
|
updated = new URLSearchParams();
|
|
945
|
-
|
|
946
|
-
|
|
1013
|
+
for (const key of Object.keys(value)) {
|
|
1014
|
+
if (key === '__proto__') {
|
|
1015
|
+
continue;
|
|
1016
|
+
}
|
|
947
1017
|
const entry = value[key];
|
|
948
1018
|
if (entry === null) {
|
|
949
1019
|
updated.append(key, '');
|
|
@@ -956,7 +1026,7 @@ export default class Options {
|
|
|
956
1026
|
}
|
|
957
1027
|
}
|
|
958
1028
|
}
|
|
959
|
-
if (this
|
|
1029
|
+
if (this.#merging) {
|
|
960
1030
|
// These keys will be replaced
|
|
961
1031
|
for (const key of updated.keys()) {
|
|
962
1032
|
searchParameters.delete(key);
|
|
@@ -969,7 +1039,7 @@ export default class Options {
|
|
|
969
1039
|
url.search = searchParameters.toString();
|
|
970
1040
|
}
|
|
971
1041
|
else {
|
|
972
|
-
this.
|
|
1042
|
+
this.#internals.searchParams = searchParameters;
|
|
973
1043
|
}
|
|
974
1044
|
}
|
|
975
1045
|
get searchParameters() {
|
|
@@ -979,11 +1049,11 @@ export default class Options {
|
|
|
979
1049
|
throw new Error('The `searchParameters` option does not exist. Use `searchParams` instead.');
|
|
980
1050
|
}
|
|
981
1051
|
get dnsLookup() {
|
|
982
|
-
return this.
|
|
1052
|
+
return this.#internals.dnsLookup;
|
|
983
1053
|
}
|
|
984
1054
|
set dnsLookup(value) {
|
|
985
1055
|
assertAny('dnsLookup', [is.function, is.undefined], value);
|
|
986
|
-
this.
|
|
1056
|
+
this.#internals.dnsLookup = value;
|
|
987
1057
|
}
|
|
988
1058
|
/**
|
|
989
1059
|
An instance of [`CacheableLookup`](https://github.com/szmarczak/cacheable-lookup) used for making DNS lookups.
|
|
@@ -996,18 +1066,18 @@ export default class Options {
|
|
|
996
1066
|
@default false
|
|
997
1067
|
*/
|
|
998
1068
|
get dnsCache() {
|
|
999
|
-
return this.
|
|
1069
|
+
return this.#internals.dnsCache;
|
|
1000
1070
|
}
|
|
1001
1071
|
set dnsCache(value) {
|
|
1002
1072
|
assertAny('dnsCache', [is.object, is.boolean, is.undefined], value);
|
|
1003
1073
|
if (value === true) {
|
|
1004
|
-
this.
|
|
1074
|
+
this.#internals.dnsCache = getGlobalDnsCache();
|
|
1005
1075
|
}
|
|
1006
1076
|
else if (value === false) {
|
|
1007
|
-
this.
|
|
1077
|
+
this.#internals.dnsCache = undefined;
|
|
1008
1078
|
}
|
|
1009
1079
|
else {
|
|
1010
|
-
this.
|
|
1080
|
+
this.#internals.dnsCache = value;
|
|
1011
1081
|
}
|
|
1012
1082
|
}
|
|
1013
1083
|
/**
|
|
@@ -1042,15 +1112,15 @@ export default class Options {
|
|
|
1042
1112
|
```
|
|
1043
1113
|
*/
|
|
1044
1114
|
get context() {
|
|
1045
|
-
return this.
|
|
1115
|
+
return this.#internals.context;
|
|
1046
1116
|
}
|
|
1047
1117
|
set context(value) {
|
|
1048
1118
|
assert.object(value);
|
|
1049
|
-
if (this
|
|
1050
|
-
|
|
1119
|
+
if (this.#merging) {
|
|
1120
|
+
safeObjectAssign(this.#internals.context, value);
|
|
1051
1121
|
}
|
|
1052
1122
|
else {
|
|
1053
|
-
this.
|
|
1123
|
+
this.#internals.context = { ...value };
|
|
1054
1124
|
}
|
|
1055
1125
|
}
|
|
1056
1126
|
/**
|
|
@@ -1058,13 +1128,15 @@ export default class Options {
|
|
|
1058
1128
|
Hook functions may be async and are run serially.
|
|
1059
1129
|
*/
|
|
1060
1130
|
get hooks() {
|
|
1061
|
-
return this.
|
|
1131
|
+
return this.#internals.hooks;
|
|
1062
1132
|
}
|
|
1063
1133
|
set hooks(value) {
|
|
1064
1134
|
assert.object(value);
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1135
|
+
for (const knownHookEvent of Object.keys(value)) {
|
|
1136
|
+
if (knownHookEvent === '__proto__') {
|
|
1137
|
+
continue;
|
|
1138
|
+
}
|
|
1139
|
+
if (!(knownHookEvent in this.#internals.hooks)) {
|
|
1068
1140
|
throw new Error(`Unexpected hook event: ${knownHookEvent}`);
|
|
1069
1141
|
}
|
|
1070
1142
|
const typedKnownHookEvent = knownHookEvent;
|
|
@@ -1075,10 +1147,10 @@ export default class Options {
|
|
|
1075
1147
|
assert.function(hook);
|
|
1076
1148
|
}
|
|
1077
1149
|
}
|
|
1078
|
-
if (this
|
|
1150
|
+
if (this.#merging) {
|
|
1079
1151
|
if (hooks) {
|
|
1080
1152
|
// @ts-expect-error FIXME
|
|
1081
|
-
this.
|
|
1153
|
+
this.#internals.hooks[typedKnownHookEvent].push(...hooks);
|
|
1082
1154
|
}
|
|
1083
1155
|
}
|
|
1084
1156
|
else {
|
|
@@ -1086,7 +1158,7 @@ export default class Options {
|
|
|
1086
1158
|
throw new Error(`Missing hook event: ${knownHookEvent}`);
|
|
1087
1159
|
}
|
|
1088
1160
|
// @ts-expect-error FIXME
|
|
1089
|
-
this.
|
|
1161
|
+
this.#internals.hooks[knownHookEvent] = [...hooks];
|
|
1090
1162
|
}
|
|
1091
1163
|
}
|
|
1092
1164
|
}
|
|
@@ -1097,15 +1169,16 @@ export default class Options {
|
|
|
1097
1169
|
|
|
1098
1170
|
Note that if a `303` is sent by the server in response to any request type (`POST`, `DELETE`, etc.), Got will automatically request the resource pointed to in the location header via `GET`.
|
|
1099
1171
|
This is in accordance with [the spec](https://tools.ietf.org/html/rfc7231#section-6.4.4). You can optionally turn on this behavior also for other redirect codes - see `methodRewriting`.
|
|
1172
|
+
On cross-origin redirects, Got strips `host`, `cookie`, `cookie2`, `authorization`, and `proxy-authorization`. When a redirect rewrites the request to `GET`, Got also strips request body headers. Use `hooks.beforeRedirect` for app-specific sensitive headers.
|
|
1100
1173
|
|
|
1101
1174
|
@default true
|
|
1102
1175
|
*/
|
|
1103
1176
|
get followRedirect() {
|
|
1104
|
-
return this.
|
|
1177
|
+
return this.#internals.followRedirect;
|
|
1105
1178
|
}
|
|
1106
1179
|
set followRedirect(value) {
|
|
1107
1180
|
assertAny('followRedirect', [is.boolean, is.function], value);
|
|
1108
|
-
this.
|
|
1181
|
+
this.#internals.followRedirect = value;
|
|
1109
1182
|
}
|
|
1110
1183
|
get followRedirects() {
|
|
1111
1184
|
throw new TypeError('The `followRedirects` option does not exist. Use `followRedirect` instead.');
|
|
@@ -1119,11 +1192,11 @@ export default class Options {
|
|
|
1119
1192
|
@default 10
|
|
1120
1193
|
*/
|
|
1121
1194
|
get maxRedirects() {
|
|
1122
|
-
return this.
|
|
1195
|
+
return this.#internals.maxRedirects;
|
|
1123
1196
|
}
|
|
1124
1197
|
set maxRedirects(value) {
|
|
1125
1198
|
assert.number(value);
|
|
1126
|
-
this.
|
|
1199
|
+
this.#internals.maxRedirects = value;
|
|
1127
1200
|
}
|
|
1128
1201
|
/**
|
|
1129
1202
|
A cache adapter instance for storing cached response data.
|
|
@@ -1131,18 +1204,18 @@ export default class Options {
|
|
|
1131
1204
|
@default false
|
|
1132
1205
|
*/
|
|
1133
1206
|
get cache() {
|
|
1134
|
-
return this.
|
|
1207
|
+
return this.#internals.cache;
|
|
1135
1208
|
}
|
|
1136
1209
|
set cache(value) {
|
|
1137
1210
|
assertAny('cache', [is.object, is.string, is.boolean, is.undefined], value);
|
|
1138
1211
|
if (value === true) {
|
|
1139
|
-
this.
|
|
1212
|
+
this.#internals.cache = globalCache;
|
|
1140
1213
|
}
|
|
1141
1214
|
else if (value === false) {
|
|
1142
|
-
this.
|
|
1215
|
+
this.#internals.cache = undefined;
|
|
1143
1216
|
}
|
|
1144
1217
|
else {
|
|
1145
|
-
this.
|
|
1218
|
+
this.#internals.cache = wrapQuickLruIfNeeded(value);
|
|
1146
1219
|
}
|
|
1147
1220
|
}
|
|
1148
1221
|
/**
|
|
@@ -1154,43 +1227,45 @@ export default class Options {
|
|
|
1154
1227
|
@default true
|
|
1155
1228
|
*/
|
|
1156
1229
|
get throwHttpErrors() {
|
|
1157
|
-
return this.
|
|
1230
|
+
return this.#internals.throwHttpErrors;
|
|
1158
1231
|
}
|
|
1159
1232
|
set throwHttpErrors(value) {
|
|
1160
1233
|
assert.boolean(value);
|
|
1161
|
-
this.
|
|
1234
|
+
this.#internals.throwHttpErrors = value;
|
|
1162
1235
|
}
|
|
1163
1236
|
get username() {
|
|
1164
|
-
const url = this.
|
|
1165
|
-
const value = url ? url.username : this.
|
|
1237
|
+
const url = this.#internals.url;
|
|
1238
|
+
const value = url ? url.username : this.#internals.username;
|
|
1166
1239
|
return decodeURIComponent(value);
|
|
1167
1240
|
}
|
|
1168
1241
|
set username(value) {
|
|
1169
1242
|
assert.string(value);
|
|
1170
|
-
const url = this.
|
|
1243
|
+
const url = this.#internals.url;
|
|
1171
1244
|
const fixedValue = encodeURIComponent(value);
|
|
1172
1245
|
if (url) {
|
|
1173
1246
|
url.username = fixedValue;
|
|
1174
1247
|
}
|
|
1175
1248
|
else {
|
|
1176
|
-
this.
|
|
1249
|
+
this.#internals.username = fixedValue;
|
|
1177
1250
|
}
|
|
1251
|
+
trackStateMutation(this.#trackedStateMutations, 'username');
|
|
1178
1252
|
}
|
|
1179
1253
|
get password() {
|
|
1180
|
-
const url = this.
|
|
1181
|
-
const value = url ? url.password : this.
|
|
1254
|
+
const url = this.#internals.url;
|
|
1255
|
+
const value = url ? url.password : this.#internals.password;
|
|
1182
1256
|
return decodeURIComponent(value);
|
|
1183
1257
|
}
|
|
1184
1258
|
set password(value) {
|
|
1185
1259
|
assert.string(value);
|
|
1186
|
-
const url = this.
|
|
1260
|
+
const url = this.#internals.url;
|
|
1187
1261
|
const fixedValue = encodeURIComponent(value);
|
|
1188
1262
|
if (url) {
|
|
1189
1263
|
url.password = fixedValue;
|
|
1190
1264
|
}
|
|
1191
1265
|
else {
|
|
1192
|
-
this.
|
|
1266
|
+
this.#internals.password = fixedValue;
|
|
1193
1267
|
}
|
|
1268
|
+
trackStateMutation(this.#trackedStateMutations, 'password');
|
|
1194
1269
|
}
|
|
1195
1270
|
/**
|
|
1196
1271
|
If set to `true`, Got will additionally accept HTTP2 requests.
|
|
@@ -1214,11 +1289,11 @@ export default class Options {
|
|
|
1214
1289
|
```
|
|
1215
1290
|
*/
|
|
1216
1291
|
get http2() {
|
|
1217
|
-
return this.
|
|
1292
|
+
return this.#internals.http2;
|
|
1218
1293
|
}
|
|
1219
1294
|
set http2(value) {
|
|
1220
1295
|
assert.boolean(value);
|
|
1221
|
-
this.
|
|
1296
|
+
this.#internals.http2 = value;
|
|
1222
1297
|
}
|
|
1223
1298
|
/**
|
|
1224
1299
|
Set this to `true` to allow sending body for the `GET` method.
|
|
@@ -1230,36 +1305,35 @@ export default class Options {
|
|
|
1230
1305
|
@default false
|
|
1231
1306
|
*/
|
|
1232
1307
|
get allowGetBody() {
|
|
1233
|
-
return this.
|
|
1308
|
+
return this.#internals.allowGetBody;
|
|
1234
1309
|
}
|
|
1235
1310
|
set allowGetBody(value) {
|
|
1236
1311
|
assert.boolean(value);
|
|
1237
|
-
this.
|
|
1312
|
+
this.#internals.allowGetBody = value;
|
|
1238
1313
|
}
|
|
1239
1314
|
/**
|
|
1240
1315
|
Automatically copy headers from piped streams.
|
|
1241
1316
|
|
|
1242
1317
|
When piping a request into a Got stream (e.g., `request.pipe(got.stream(url))`), this controls whether headers from the source stream are automatically merged into the Got request headers.
|
|
1243
1318
|
|
|
1244
|
-
Note:
|
|
1319
|
+
Note: Explicitly set headers take precedence over piped headers. Piped headers are only copied when a header is not already explicitly set.
|
|
1245
1320
|
|
|
1246
|
-
Useful for proxy scenarios, but you may want to
|
|
1321
|
+
Useful for proxy scenarios when explicitly enabled, but you may still want to filter out headers like `Host`, `Connection`, `Authorization`, etc.
|
|
1247
1322
|
|
|
1248
|
-
@default
|
|
1323
|
+
@default false
|
|
1249
1324
|
|
|
1250
1325
|
@example
|
|
1251
1326
|
```
|
|
1252
1327
|
import got from 'got';
|
|
1253
1328
|
import {pipeline} from 'node:stream/promises';
|
|
1254
1329
|
|
|
1255
|
-
//
|
|
1330
|
+
// Opt in to automatic header copying for proxy scenarios
|
|
1256
1331
|
server.get('/proxy', async (request, response) => {
|
|
1257
1332
|
const gotStream = got.stream('https://example.com', {
|
|
1258
|
-
copyPipedHeaders:
|
|
1333
|
+
copyPipedHeaders: true,
|
|
1334
|
+
// Explicit headers win over piped headers
|
|
1259
1335
|
headers: {
|
|
1260
|
-
|
|
1261
|
-
'accept': request.headers['accept'],
|
|
1262
|
-
// Explicitly NOT copying host, connection, authorization, etc.
|
|
1336
|
+
host: 'example.com',
|
|
1263
1337
|
}
|
|
1264
1338
|
});
|
|
1265
1339
|
|
|
@@ -1270,27 +1344,114 @@ export default class Options {
|
|
|
1270
1344
|
@example
|
|
1271
1345
|
```
|
|
1272
1346
|
import got from 'got';
|
|
1347
|
+
import {pipeline} from 'node:stream/promises';
|
|
1273
1348
|
|
|
1274
|
-
//
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1349
|
+
// Keep it disabled and manually copy only safe headers
|
|
1350
|
+
server.get('/proxy', async (request, response) => {
|
|
1351
|
+
const gotStream = got.stream('https://example.com', {
|
|
1352
|
+
headers: {
|
|
1353
|
+
'user-agent': request.headers['user-agent'],
|
|
1354
|
+
'accept': request.headers['accept'],
|
|
1355
|
+
// Explicitly NOT copying host, connection, authorization, etc.
|
|
1356
|
+
}
|
|
1357
|
+
});
|
|
1358
|
+
|
|
1359
|
+
await pipeline(request, gotStream, response);
|
|
1285
1360
|
});
|
|
1286
1361
|
```
|
|
1287
1362
|
*/
|
|
1288
1363
|
get copyPipedHeaders() {
|
|
1289
|
-
return this.
|
|
1364
|
+
return this.#internals.copyPipedHeaders;
|
|
1290
1365
|
}
|
|
1291
1366
|
set copyPipedHeaders(value) {
|
|
1292
1367
|
assert.boolean(value);
|
|
1293
|
-
this.
|
|
1368
|
+
this.#internals.copyPipedHeaders = value;
|
|
1369
|
+
}
|
|
1370
|
+
isHeaderExplicitlySet(name) {
|
|
1371
|
+
return this.#explicitHeaders.has(name.toLowerCase());
|
|
1372
|
+
}
|
|
1373
|
+
shouldCopyPipedHeader(name) {
|
|
1374
|
+
return !this.isHeaderExplicitlySet(name);
|
|
1375
|
+
}
|
|
1376
|
+
setPipedHeader(name, value) {
|
|
1377
|
+
assertValidHeaderName(name);
|
|
1378
|
+
this.#internals.headers[name.toLowerCase()] = value;
|
|
1379
|
+
}
|
|
1380
|
+
getInternalHeaders() {
|
|
1381
|
+
return this.#internals.headers;
|
|
1382
|
+
}
|
|
1383
|
+
setInternalHeader(name, value) {
|
|
1384
|
+
assertValidHeaderName(name);
|
|
1385
|
+
this.#internals.headers[name.toLowerCase()] = value;
|
|
1386
|
+
}
|
|
1387
|
+
deleteInternalHeader(name) {
|
|
1388
|
+
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
|
|
1389
|
+
delete this.#internals.headers[name.toLowerCase()];
|
|
1390
|
+
}
|
|
1391
|
+
async trackStateMutations(operation) {
|
|
1392
|
+
const changedState = new Set();
|
|
1393
|
+
this.#trackedStateMutations = changedState;
|
|
1394
|
+
try {
|
|
1395
|
+
return await operation(changedState);
|
|
1396
|
+
}
|
|
1397
|
+
finally {
|
|
1398
|
+
this.#trackedStateMutations = undefined;
|
|
1399
|
+
}
|
|
1400
|
+
}
|
|
1401
|
+
clearBody() {
|
|
1402
|
+
this.body = undefined;
|
|
1403
|
+
this.json = undefined;
|
|
1404
|
+
this.form = undefined;
|
|
1405
|
+
for (const header of bodyHeaderNames) {
|
|
1406
|
+
this.deleteInternalHeader(header);
|
|
1407
|
+
}
|
|
1408
|
+
}
|
|
1409
|
+
stripUnchangedCrossOriginState(previousState, changedState, { clearBody = true } = {}) {
|
|
1410
|
+
const headers = this.getInternalHeaders();
|
|
1411
|
+
const url = this.#internals.url;
|
|
1412
|
+
for (const header of crossOriginStripHeaders) {
|
|
1413
|
+
if (!changedState.has(header) && headers[header] === previousState.headers[header]) {
|
|
1414
|
+
this.deleteInternalHeader(header);
|
|
1415
|
+
}
|
|
1416
|
+
}
|
|
1417
|
+
if (!hasExplicitCredentialInUrlChange(changedState, url, 'username')) {
|
|
1418
|
+
this.username = '';
|
|
1419
|
+
}
|
|
1420
|
+
if (!hasExplicitCredentialInUrlChange(changedState, url, 'password')) {
|
|
1421
|
+
this.password = '';
|
|
1422
|
+
}
|
|
1423
|
+
if (clearBody && !changedState.has('body') && !changedState.has('json') && !changedState.has('form') && isBodyUnchanged(this, previousState)) {
|
|
1424
|
+
this.clearBody();
|
|
1425
|
+
}
|
|
1426
|
+
}
|
|
1427
|
+
/**
|
|
1428
|
+
Strip sensitive headers and credentials when navigating to a different origin.
|
|
1429
|
+
Headers and credentials explicitly provided in `userOptions` are preserved.
|
|
1430
|
+
*/
|
|
1431
|
+
stripSensitiveHeaders(previousUrl, nextUrl, userOptions) {
|
|
1432
|
+
if (isSameOrigin(previousUrl, nextUrl)) {
|
|
1433
|
+
return;
|
|
1434
|
+
}
|
|
1435
|
+
const headers = lowercaseKeys(userOptions.headers ?? {});
|
|
1436
|
+
for (const header of crossOriginStripHeaders) {
|
|
1437
|
+
if (headers[header] === undefined) {
|
|
1438
|
+
this.deleteInternalHeader(header);
|
|
1439
|
+
}
|
|
1440
|
+
}
|
|
1441
|
+
const explicitUsername = Object.hasOwn(userOptions, 'username') ? userOptions.username : undefined;
|
|
1442
|
+
const explicitPassword = Object.hasOwn(userOptions, 'password') ? userOptions.password : undefined;
|
|
1443
|
+
const hasExplicitUsername = explicitUsername !== undefined
|
|
1444
|
+
|| hasCredentialInUrl(userOptions.url, 'username')
|
|
1445
|
+
|| isCrossOriginCredentialChanged(previousUrl, nextUrl, 'username');
|
|
1446
|
+
const hasExplicitPassword = explicitPassword !== undefined
|
|
1447
|
+
|| hasCredentialInUrl(userOptions.url, 'password')
|
|
1448
|
+
|| isCrossOriginCredentialChanged(previousUrl, nextUrl, 'password');
|
|
1449
|
+
if (!hasExplicitUsername && this.username) {
|
|
1450
|
+
this.username = '';
|
|
1451
|
+
}
|
|
1452
|
+
if (!hasExplicitPassword && this.password) {
|
|
1453
|
+
this.password = '';
|
|
1454
|
+
}
|
|
1294
1455
|
}
|
|
1295
1456
|
/**
|
|
1296
1457
|
Request headers.
|
|
@@ -1300,33 +1461,49 @@ export default class Options {
|
|
|
1300
1461
|
@default {}
|
|
1301
1462
|
*/
|
|
1302
1463
|
get headers() {
|
|
1303
|
-
return this
|
|
1464
|
+
return this.#headersProxy;
|
|
1304
1465
|
}
|
|
1305
1466
|
set headers(value) {
|
|
1306
1467
|
assertPlainObject('headers', value);
|
|
1307
|
-
|
|
1308
|
-
|
|
1468
|
+
const normalizedHeaders = lowercaseKeys(value);
|
|
1469
|
+
for (const header of Object.keys(normalizedHeaders)) {
|
|
1470
|
+
assertValidHeaderName(header);
|
|
1471
|
+
}
|
|
1472
|
+
if (this.#merging) {
|
|
1473
|
+
safeObjectAssign(this.#internals.headers, normalizedHeaders);
|
|
1309
1474
|
}
|
|
1310
1475
|
else {
|
|
1311
|
-
this.
|
|
1476
|
+
const previousHeaders = this.#internals.headers;
|
|
1477
|
+
this.#internals.headers = normalizedHeaders;
|
|
1478
|
+
this.#headersProxy = this.#createHeadersProxy();
|
|
1479
|
+
this.#explicitHeaders.clear();
|
|
1480
|
+
trackReplacedHeaderMutations(this.#trackedStateMutations, previousHeaders, normalizedHeaders);
|
|
1481
|
+
}
|
|
1482
|
+
for (const header of Object.keys(normalizedHeaders)) {
|
|
1483
|
+
if (this.#merging) {
|
|
1484
|
+
markHeaderAsExplicit(this.#explicitHeaders, this.#trackedStateMutations, header);
|
|
1485
|
+
}
|
|
1486
|
+
else {
|
|
1487
|
+
addExplicitHeader(this.#explicitHeaders, header);
|
|
1488
|
+
}
|
|
1312
1489
|
}
|
|
1313
1490
|
}
|
|
1314
1491
|
/**
|
|
1315
1492
|
Specifies if the HTTP request method should be [rewritten as `GET`](https://tools.ietf.org/html/rfc7231#section-6.4) on redirects.
|
|
1316
1493
|
|
|
1317
|
-
As the [specification](https://tools.ietf.org/html/rfc7231#section-6.4) prefers to rewrite the HTTP method only on `303` responses, this is Got's default behavior.
|
|
1318
|
-
Setting `methodRewriting` to `true` will also rewrite `301` and `302` responses, as allowed by the spec. This is the behavior followed by `curl` and browsers.
|
|
1494
|
+
As the [specification](https://tools.ietf.org/html/rfc7231#section-6.4) prefers to rewrite the HTTP method only on `303` responses, this is Got's default behavior. Cross-origin `301` and `302` redirects also rewrite `POST` requests to `GET` by default to avoid forwarding request bodies to another origin.
|
|
1495
|
+
Setting `methodRewriting` to `true` will also rewrite same-origin `301` and `302` responses, as allowed by the spec. This is the behavior followed by `curl` and browsers.
|
|
1319
1496
|
|
|
1320
1497
|
__Note__: Got never performs method rewriting on `307` and `308` responses, as this is [explicitly prohibited by the specification](https://www.rfc-editor.org/rfc/rfc7231#section-6.4.7).
|
|
1321
1498
|
|
|
1322
1499
|
@default false
|
|
1323
1500
|
*/
|
|
1324
1501
|
get methodRewriting() {
|
|
1325
|
-
return this.
|
|
1502
|
+
return this.#internals.methodRewriting;
|
|
1326
1503
|
}
|
|
1327
1504
|
set methodRewriting(value) {
|
|
1328
1505
|
assert.boolean(value);
|
|
1329
|
-
this.
|
|
1506
|
+
this.#internals.methodRewriting = value;
|
|
1330
1507
|
}
|
|
1331
1508
|
/**
|
|
1332
1509
|
Indicates which DNS record family to use.
|
|
@@ -1339,13 +1516,13 @@ export default class Options {
|
|
|
1339
1516
|
@default undefined
|
|
1340
1517
|
*/
|
|
1341
1518
|
get dnsLookupIpVersion() {
|
|
1342
|
-
return this.
|
|
1519
|
+
return this.#internals.dnsLookupIpVersion;
|
|
1343
1520
|
}
|
|
1344
1521
|
set dnsLookupIpVersion(value) {
|
|
1345
1522
|
if (value !== undefined && value !== 4 && value !== 6) {
|
|
1346
1523
|
throw new TypeError(`Invalid DNS lookup IP version: ${value}`);
|
|
1347
1524
|
}
|
|
1348
|
-
this.
|
|
1525
|
+
this.#internals.dnsLookupIpVersion = value;
|
|
1349
1526
|
}
|
|
1350
1527
|
/**
|
|
1351
1528
|
A function used to parse JSON responses.
|
|
@@ -1363,11 +1540,11 @@ export default class Options {
|
|
|
1363
1540
|
```
|
|
1364
1541
|
*/
|
|
1365
1542
|
get parseJson() {
|
|
1366
|
-
return this.
|
|
1543
|
+
return this.#internals.parseJson;
|
|
1367
1544
|
}
|
|
1368
1545
|
set parseJson(value) {
|
|
1369
1546
|
assert.function(value);
|
|
1370
|
-
this.
|
|
1547
|
+
this.#internals.parseJson = value;
|
|
1371
1548
|
}
|
|
1372
1549
|
/**
|
|
1373
1550
|
A function used to stringify the body of JSON requests.
|
|
@@ -1411,11 +1588,11 @@ export default class Options {
|
|
|
1411
1588
|
```
|
|
1412
1589
|
*/
|
|
1413
1590
|
get stringifyJson() {
|
|
1414
|
-
return this.
|
|
1591
|
+
return this.#internals.stringifyJson;
|
|
1415
1592
|
}
|
|
1416
1593
|
set stringifyJson(value) {
|
|
1417
1594
|
assert.function(value);
|
|
1418
|
-
this.
|
|
1595
|
+
this.#internals.stringifyJson = value;
|
|
1419
1596
|
}
|
|
1420
1597
|
/**
|
|
1421
1598
|
An object representing `limit`, `calculateDelay`, `methods`, `statusCodes`, `maxRetryAfter` and `errorCodes` fields for maximum retry count, retry handler, allowed methods, allowed status codes, maximum [`Retry-After`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After) time and allowed error codes.
|
|
@@ -1425,9 +1602,9 @@ export default class Options {
|
|
|
1425
1602
|
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.
|
|
1426
1603
|
The function must return a delay in milliseconds (or a Promise resolving with it) (`0` return value cancels retry).
|
|
1427
1604
|
|
|
1428
|
-
The `enforceRetryRules` property is a `boolean` that, when set to `true
|
|
1605
|
+
The `enforceRetryRules` property is a `boolean` that, when set to `true` (default), enforces the `limit`, `methods`, `statusCodes`, and `errorCodes` options before calling `calculateDelay`. Your `calculateDelay` function is only invoked when a retry is allowed based on these criteria. When `false`, `calculateDelay` receives the computed value but can override all retry logic.
|
|
1429
1606
|
|
|
1430
|
-
__Note:__ When `enforceRetryRules` is `false`, you must check `computedValue` in your `calculateDelay` function to respect
|
|
1607
|
+
__Note:__ When `enforceRetryRules` is `false`, you must check `computedValue` in your `calculateDelay` function to respect retry rules. When `true` (default), the retry rules are enforced automatically.
|
|
1431
1608
|
|
|
1432
1609
|
By default, it retries *only* on the specified methods, status codes, and on these network errors:
|
|
1433
1610
|
|
|
@@ -1444,7 +1621,7 @@ export default class Options {
|
|
|
1444
1621
|
__Note__: If [`Retry-After`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After) header is greater than `maxRetryAfter`, it will cancel the request.
|
|
1445
1622
|
*/
|
|
1446
1623
|
get retry() {
|
|
1447
|
-
return this.
|
|
1624
|
+
return this.#internals.retry;
|
|
1448
1625
|
}
|
|
1449
1626
|
set retry(value) {
|
|
1450
1627
|
assertPlainObject('retry', value);
|
|
@@ -1459,18 +1636,21 @@ export default class Options {
|
|
|
1459
1636
|
if (value.noise && Math.abs(value.noise) > 100) {
|
|
1460
1637
|
throw new Error(`The maximum acceptable retry noise is +/- 100ms, got ${value.noise}`);
|
|
1461
1638
|
}
|
|
1462
|
-
for (const key
|
|
1463
|
-
if (
|
|
1639
|
+
for (const key of Object.keys(value)) {
|
|
1640
|
+
if (key === '__proto__') {
|
|
1641
|
+
continue;
|
|
1642
|
+
}
|
|
1643
|
+
if (!(key in this.#internals.retry)) {
|
|
1464
1644
|
throw new Error(`Unexpected retry option: ${key}`);
|
|
1465
1645
|
}
|
|
1466
1646
|
}
|
|
1467
|
-
if (this
|
|
1468
|
-
|
|
1647
|
+
if (this.#merging) {
|
|
1648
|
+
safeObjectAssign(this.#internals.retry, value);
|
|
1469
1649
|
}
|
|
1470
1650
|
else {
|
|
1471
|
-
this.
|
|
1651
|
+
this.#internals.retry = { ...value };
|
|
1472
1652
|
}
|
|
1473
|
-
const { retry } = this
|
|
1653
|
+
const { retry } = this.#internals;
|
|
1474
1654
|
retry.methods = [...new Set(retry.methods.map(method => method.toUpperCase()))];
|
|
1475
1655
|
retry.statusCodes = [...new Set(retry.statusCodes)];
|
|
1476
1656
|
retry.errorCodes = [...new Set(retry.errorCodes)];
|
|
@@ -1481,11 +1661,11 @@ export default class Options {
|
|
|
1481
1661
|
The IP address used to send the request from.
|
|
1482
1662
|
*/
|
|
1483
1663
|
get localAddress() {
|
|
1484
|
-
return this.
|
|
1664
|
+
return this.#internals.localAddress;
|
|
1485
1665
|
}
|
|
1486
1666
|
set localAddress(value) {
|
|
1487
1667
|
assertAny('localAddress', [is.string, is.undefined], value);
|
|
1488
|
-
this.
|
|
1668
|
+
this.#internals.localAddress = value;
|
|
1489
1669
|
}
|
|
1490
1670
|
/**
|
|
1491
1671
|
The HTTP method used to make the request.
|
|
@@ -1493,18 +1673,18 @@ export default class Options {
|
|
|
1493
1673
|
@default 'GET'
|
|
1494
1674
|
*/
|
|
1495
1675
|
get method() {
|
|
1496
|
-
return this.
|
|
1676
|
+
return this.#internals.method;
|
|
1497
1677
|
}
|
|
1498
1678
|
set method(value) {
|
|
1499
1679
|
assert.string(value);
|
|
1500
|
-
this.
|
|
1680
|
+
this.#internals.method = value.toUpperCase();
|
|
1501
1681
|
}
|
|
1502
1682
|
get createConnection() {
|
|
1503
|
-
return this.
|
|
1683
|
+
return this.#internals.createConnection;
|
|
1504
1684
|
}
|
|
1505
1685
|
set createConnection(value) {
|
|
1506
1686
|
assertAny('createConnection', [is.function, is.undefined], value);
|
|
1507
|
-
this.
|
|
1687
|
+
this.#internals.createConnection = value;
|
|
1508
1688
|
}
|
|
1509
1689
|
/**
|
|
1510
1690
|
From `http-cache-semantics`
|
|
@@ -1512,7 +1692,7 @@ export default class Options {
|
|
|
1512
1692
|
@default {}
|
|
1513
1693
|
*/
|
|
1514
1694
|
get cacheOptions() {
|
|
1515
|
-
return this.
|
|
1695
|
+
return this.#internals.cacheOptions;
|
|
1516
1696
|
}
|
|
1517
1697
|
set cacheOptions(value) {
|
|
1518
1698
|
assertPlainObject('cacheOptions', value);
|
|
@@ -1520,23 +1700,26 @@ export default class Options {
|
|
|
1520
1700
|
assertAny('cacheOptions.cacheHeuristic', [is.number, is.undefined], value.cacheHeuristic);
|
|
1521
1701
|
assertAny('cacheOptions.immutableMinTimeToLive', [is.number, is.undefined], value.immutableMinTimeToLive);
|
|
1522
1702
|
assertAny('cacheOptions.ignoreCargoCult', [is.boolean, is.undefined], value.ignoreCargoCult);
|
|
1523
|
-
for (const key
|
|
1524
|
-
if (
|
|
1703
|
+
for (const key of Object.keys(value)) {
|
|
1704
|
+
if (key === '__proto__') {
|
|
1705
|
+
continue;
|
|
1706
|
+
}
|
|
1707
|
+
if (!(key in this.#internals.cacheOptions)) {
|
|
1525
1708
|
throw new Error(`Cache option \`${key}\` does not exist`);
|
|
1526
1709
|
}
|
|
1527
1710
|
}
|
|
1528
|
-
if (this
|
|
1529
|
-
|
|
1711
|
+
if (this.#merging) {
|
|
1712
|
+
safeObjectAssign(this.#internals.cacheOptions, value);
|
|
1530
1713
|
}
|
|
1531
1714
|
else {
|
|
1532
|
-
this.
|
|
1715
|
+
this.#internals.cacheOptions = { ...value };
|
|
1533
1716
|
}
|
|
1534
1717
|
}
|
|
1535
1718
|
/**
|
|
1536
1719
|
Options for the advanced HTTPS API.
|
|
1537
1720
|
*/
|
|
1538
1721
|
get https() {
|
|
1539
|
-
return this.
|
|
1722
|
+
return this.#internals.https;
|
|
1540
1723
|
}
|
|
1541
1724
|
set https(value) {
|
|
1542
1725
|
assertPlainObject('https', value);
|
|
@@ -1559,22 +1742,25 @@ export default class Options {
|
|
|
1559
1742
|
assertAny('https.ecdhCurve', [is.string, is.undefined], value.ecdhCurve);
|
|
1560
1743
|
assertAny('https.certificateRevocationLists', [is.string, is.buffer, is.array, is.undefined], value.certificateRevocationLists);
|
|
1561
1744
|
assertAny('https.secureOptions', [is.number, is.undefined], value.secureOptions);
|
|
1562
|
-
for (const key
|
|
1563
|
-
if (
|
|
1745
|
+
for (const key of Object.keys(value)) {
|
|
1746
|
+
if (key === '__proto__') {
|
|
1747
|
+
continue;
|
|
1748
|
+
}
|
|
1749
|
+
if (!(key in this.#internals.https)) {
|
|
1564
1750
|
throw new Error(`HTTPS option \`${key}\` does not exist`);
|
|
1565
1751
|
}
|
|
1566
1752
|
}
|
|
1567
|
-
if (this
|
|
1568
|
-
|
|
1753
|
+
if (this.#merging) {
|
|
1754
|
+
safeObjectAssign(this.#internals.https, value);
|
|
1569
1755
|
}
|
|
1570
1756
|
else {
|
|
1571
|
-
this.
|
|
1757
|
+
this.#internals.https = { ...value };
|
|
1572
1758
|
}
|
|
1573
1759
|
}
|
|
1574
1760
|
/**
|
|
1575
1761
|
[Encoding](https://nodejs.org/api/buffer.html#buffer_buffers_and_character_encodings) to be used on `setEncoding` of the response data.
|
|
1576
1762
|
|
|
1577
|
-
To get a [`
|
|
1763
|
+
To get a [`Uint8Array`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array), you need to set `responseType` to `buffer` instead.
|
|
1578
1764
|
Don't set this option to `null`.
|
|
1579
1765
|
|
|
1580
1766
|
__Note__: This doesn't affect streams! Instead, you need to do `got.stream(...).setEncoding(encoding)`.
|
|
@@ -1582,14 +1768,14 @@ export default class Options {
|
|
|
1582
1768
|
@default 'utf-8'
|
|
1583
1769
|
*/
|
|
1584
1770
|
get encoding() {
|
|
1585
|
-
return this.
|
|
1771
|
+
return this.#internals.encoding;
|
|
1586
1772
|
}
|
|
1587
1773
|
set encoding(value) {
|
|
1588
1774
|
if (value === null) {
|
|
1589
|
-
throw new TypeError('To get a
|
|
1775
|
+
throw new TypeError('To get a Uint8Array, set `options.responseType` to `buffer` instead');
|
|
1590
1776
|
}
|
|
1591
1777
|
assertAny('encoding', [is.string, is.undefined], value);
|
|
1592
|
-
this.
|
|
1778
|
+
this.#internals.encoding = value;
|
|
1593
1779
|
}
|
|
1594
1780
|
/**
|
|
1595
1781
|
When set to `true` the promise will return the Response body instead of the Response object.
|
|
@@ -1597,24 +1783,25 @@ export default class Options {
|
|
|
1597
1783
|
@default false
|
|
1598
1784
|
*/
|
|
1599
1785
|
get resolveBodyOnly() {
|
|
1600
|
-
return this.
|
|
1786
|
+
return this.#internals.resolveBodyOnly;
|
|
1601
1787
|
}
|
|
1602
1788
|
set resolveBodyOnly(value) {
|
|
1603
1789
|
assert.boolean(value);
|
|
1604
|
-
this.
|
|
1790
|
+
this.#internals.resolveBodyOnly = value;
|
|
1605
1791
|
}
|
|
1606
1792
|
/**
|
|
1607
1793
|
Returns a `Stream` instead of a `Promise`.
|
|
1608
|
-
|
|
1794
|
+
Set internally by `got.stream()`.
|
|
1609
1795
|
|
|
1610
1796
|
@default false
|
|
1797
|
+
@internal
|
|
1611
1798
|
*/
|
|
1612
1799
|
get isStream() {
|
|
1613
|
-
return this.
|
|
1800
|
+
return this.#internals.isStream;
|
|
1614
1801
|
}
|
|
1615
1802
|
set isStream(value) {
|
|
1616
1803
|
assert.boolean(value);
|
|
1617
|
-
this.
|
|
1804
|
+
this.#internals.isStream = value;
|
|
1618
1805
|
}
|
|
1619
1806
|
/**
|
|
1620
1807
|
The parsing method.
|
|
@@ -1633,7 +1820,7 @@ export default class Options {
|
|
|
1633
1820
|
|
|
1634
1821
|
const [response, buffer, json] = Promise.all([responsePromise, bufferPromise, jsonPromise]);
|
|
1635
1822
|
// `response` is an instance of Got Response
|
|
1636
|
-
// `buffer` is an instance of
|
|
1823
|
+
// `buffer` is an instance of Uint8Array
|
|
1637
1824
|
// `json` is an object
|
|
1638
1825
|
```
|
|
1639
1826
|
|
|
@@ -1647,28 +1834,28 @@ export default class Options {
|
|
|
1647
1834
|
```
|
|
1648
1835
|
*/
|
|
1649
1836
|
get responseType() {
|
|
1650
|
-
return this.
|
|
1837
|
+
return this.#internals.responseType;
|
|
1651
1838
|
}
|
|
1652
1839
|
set responseType(value) {
|
|
1653
1840
|
if (value === undefined) {
|
|
1654
|
-
this.
|
|
1841
|
+
this.#internals.responseType = 'text';
|
|
1655
1842
|
return;
|
|
1656
1843
|
}
|
|
1657
1844
|
if (value !== 'text' && value !== 'buffer' && value !== 'json') {
|
|
1658
1845
|
throw new Error(`Invalid \`responseType\` option: ${value}`);
|
|
1659
1846
|
}
|
|
1660
|
-
this.
|
|
1847
|
+
this.#internals.responseType = value;
|
|
1661
1848
|
}
|
|
1662
1849
|
get pagination() {
|
|
1663
|
-
return this.
|
|
1850
|
+
return this.#internals.pagination;
|
|
1664
1851
|
}
|
|
1665
1852
|
set pagination(value) {
|
|
1666
1853
|
assert.object(value);
|
|
1667
|
-
if (this
|
|
1668
|
-
|
|
1854
|
+
if (this.#merging) {
|
|
1855
|
+
safeObjectAssign(this.#internals.pagination, value);
|
|
1669
1856
|
}
|
|
1670
1857
|
else {
|
|
1671
|
-
this.
|
|
1858
|
+
this.#internals.pagination = value;
|
|
1672
1859
|
}
|
|
1673
1860
|
}
|
|
1674
1861
|
get auth() {
|
|
@@ -1678,25 +1865,25 @@ export default class Options {
|
|
|
1678
1865
|
throw new Error('Parameter `auth` is deprecated. Use `username` / `password` instead.');
|
|
1679
1866
|
}
|
|
1680
1867
|
get setHost() {
|
|
1681
|
-
return this.
|
|
1868
|
+
return this.#internals.setHost;
|
|
1682
1869
|
}
|
|
1683
1870
|
set setHost(value) {
|
|
1684
1871
|
assert.boolean(value);
|
|
1685
|
-
this.
|
|
1872
|
+
this.#internals.setHost = value;
|
|
1686
1873
|
}
|
|
1687
1874
|
get maxHeaderSize() {
|
|
1688
|
-
return this.
|
|
1875
|
+
return this.#internals.maxHeaderSize;
|
|
1689
1876
|
}
|
|
1690
1877
|
set maxHeaderSize(value) {
|
|
1691
1878
|
assertAny('maxHeaderSize', [is.number, is.undefined], value);
|
|
1692
|
-
this.
|
|
1879
|
+
this.#internals.maxHeaderSize = value;
|
|
1693
1880
|
}
|
|
1694
1881
|
get enableUnixSockets() {
|
|
1695
|
-
return this.
|
|
1882
|
+
return this.#internals.enableUnixSockets;
|
|
1696
1883
|
}
|
|
1697
1884
|
set enableUnixSockets(value) {
|
|
1698
1885
|
assert.boolean(value);
|
|
1699
|
-
this.
|
|
1886
|
+
this.#internals.enableUnixSockets = value;
|
|
1700
1887
|
}
|
|
1701
1888
|
/**
|
|
1702
1889
|
Throw an error if the server response's `content-length` header value doesn't match the number of bytes received.
|
|
@@ -1706,24 +1893,24 @@ export default class Options {
|
|
|
1706
1893
|
__Note__: Responses without a `content-length` header are not validated.
|
|
1707
1894
|
__Note__: When enabled and validation fails, a `ReadError` with code `ERR_HTTP_CONTENT_LENGTH_MISMATCH` will be thrown.
|
|
1708
1895
|
|
|
1709
|
-
@default
|
|
1896
|
+
@default true
|
|
1710
1897
|
*/
|
|
1711
1898
|
get strictContentLength() {
|
|
1712
|
-
return this.
|
|
1899
|
+
return this.#internals.strictContentLength;
|
|
1713
1900
|
}
|
|
1714
1901
|
set strictContentLength(value) {
|
|
1715
1902
|
assert.boolean(value);
|
|
1716
|
-
this.
|
|
1903
|
+
this.#internals.strictContentLength = value;
|
|
1717
1904
|
}
|
|
1718
1905
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
1719
1906
|
toJSON() {
|
|
1720
|
-
return { ...this
|
|
1907
|
+
return { ...this.#internals };
|
|
1721
1908
|
}
|
|
1722
1909
|
[Symbol.for('nodejs.util.inspect.custom')](_depth, options) {
|
|
1723
|
-
return inspect(this
|
|
1910
|
+
return inspect(this.#internals, options);
|
|
1724
1911
|
}
|
|
1725
1912
|
createNativeRequestOptions() {
|
|
1726
|
-
const internals = this
|
|
1913
|
+
const internals = this.#internals;
|
|
1727
1914
|
const url = internals.url;
|
|
1728
1915
|
let agent;
|
|
1729
1916
|
if (url.protocol === 'https:') {
|
|
@@ -1750,9 +1937,20 @@ export default class Options {
|
|
|
1750
1937
|
passphrase: object.passphrase,
|
|
1751
1938
|
}));
|
|
1752
1939
|
}
|
|
1940
|
+
const unixSocketPath = getUnixSocketPath(url);
|
|
1941
|
+
if (usesUnixSocket(url) && !internals.enableUnixSockets) {
|
|
1942
|
+
throw new Error('Using UNIX domain sockets but option `enableUnixSockets` is not enabled');
|
|
1943
|
+
}
|
|
1944
|
+
let unixSocketGroups;
|
|
1945
|
+
if (unixSocketPath !== undefined) {
|
|
1946
|
+
unixSocketGroups = /^(?<socketPath>[^:]+):(?<path>.+)$/v.exec(`${url.pathname}${url.search}`)?.groups;
|
|
1947
|
+
}
|
|
1948
|
+
const unixOptions = unixSocketGroups
|
|
1949
|
+
? { socketPath: unixSocketGroups.socketPath, path: unixSocketGroups.path, host: '' }
|
|
1950
|
+
: undefined;
|
|
1753
1951
|
return {
|
|
1754
1952
|
...internals.cacheOptions,
|
|
1755
|
-
...
|
|
1953
|
+
...unixOptions,
|
|
1756
1954
|
// HTTPS options
|
|
1757
1955
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
1758
1956
|
ALPNProtocols: https.alpnProtocols,
|
|
@@ -1760,7 +1958,7 @@ export default class Options {
|
|
|
1760
1958
|
cert: https.certificate,
|
|
1761
1959
|
key: https.key,
|
|
1762
1960
|
passphrase: https.passphrase,
|
|
1763
|
-
pfx
|
|
1961
|
+
pfx,
|
|
1764
1962
|
rejectUnauthorized: https.rejectUnauthorized,
|
|
1765
1963
|
checkServerIdentity: https.checkServerIdentity ?? checkServerIdentity,
|
|
1766
1964
|
servername: https.serverName,
|
|
@@ -1790,33 +1988,24 @@ export default class Options {
|
|
|
1790
1988
|
};
|
|
1791
1989
|
}
|
|
1792
1990
|
getRequestFunction() {
|
|
1793
|
-
const
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
const url = this._internals.url;
|
|
1802
|
-
if (!url) {
|
|
1803
|
-
return;
|
|
1804
|
-
}
|
|
1805
|
-
if (url.protocol === 'https:') {
|
|
1806
|
-
if (this._internals.http2) {
|
|
1807
|
-
if (major < 15 || (major === 15 && minor < 10)) {
|
|
1808
|
-
const error = new Error('To use the `http2` option, install Node.js 15.10.0 or above');
|
|
1809
|
-
error.code = 'EUNSUPPORTED';
|
|
1810
|
-
throw error;
|
|
1811
|
-
}
|
|
1812
|
-
return http2wrapper.auto;
|
|
1991
|
+
const { request: customRequest } = this.#internals;
|
|
1992
|
+
if (!customRequest) {
|
|
1993
|
+
return this.#getFallbackRequestFunction();
|
|
1994
|
+
}
|
|
1995
|
+
const requestWithFallback = (url, options, callback) => {
|
|
1996
|
+
const result = customRequest(url, options, callback);
|
|
1997
|
+
if (is.promise(result)) {
|
|
1998
|
+
return this.#resolveRequestWithFallback(result, url, options, callback);
|
|
1813
1999
|
}
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
2000
|
+
if (result !== undefined) {
|
|
2001
|
+
return result;
|
|
2002
|
+
}
|
|
2003
|
+
return this.#callFallbackRequest(url, options, callback);
|
|
2004
|
+
};
|
|
2005
|
+
return requestWithFallback;
|
|
1817
2006
|
}
|
|
1818
2007
|
freeze() {
|
|
1819
|
-
const options = this
|
|
2008
|
+
const options = this.#internals;
|
|
1820
2009
|
Object.freeze(options);
|
|
1821
2010
|
Object.freeze(options.hooks);
|
|
1822
2011
|
Object.freeze(options.hooks.afterResponse);
|
|
@@ -1835,4 +2024,126 @@ export default class Options {
|
|
|
1835
2024
|
Object.freeze(options.retry.methods);
|
|
1836
2025
|
Object.freeze(options.retry.statusCodes);
|
|
1837
2026
|
}
|
|
2027
|
+
#createHeadersProxy() {
|
|
2028
|
+
return new Proxy(this.#internals.headers, {
|
|
2029
|
+
get(target, property, receiver) {
|
|
2030
|
+
if (typeof property === 'string') {
|
|
2031
|
+
if (Reflect.has(target, property)) {
|
|
2032
|
+
return Reflect.get(target, property, receiver);
|
|
2033
|
+
}
|
|
2034
|
+
const normalizedProperty = property.toLowerCase();
|
|
2035
|
+
return Reflect.get(target, normalizedProperty, receiver);
|
|
2036
|
+
}
|
|
2037
|
+
return Reflect.get(target, property, receiver);
|
|
2038
|
+
},
|
|
2039
|
+
set: (target, property, value) => {
|
|
2040
|
+
if (typeof property === 'string') {
|
|
2041
|
+
const normalizedProperty = property.toLowerCase();
|
|
2042
|
+
assertValidHeaderName(normalizedProperty);
|
|
2043
|
+
const isSuccess = Reflect.set(target, normalizedProperty, value);
|
|
2044
|
+
if (isSuccess) {
|
|
2045
|
+
markHeaderAsExplicit(this.#explicitHeaders, this.#trackedStateMutations, normalizedProperty);
|
|
2046
|
+
}
|
|
2047
|
+
return isSuccess;
|
|
2048
|
+
}
|
|
2049
|
+
return Reflect.set(target, property, value);
|
|
2050
|
+
},
|
|
2051
|
+
deleteProperty: (target, property) => {
|
|
2052
|
+
if (typeof property === 'string') {
|
|
2053
|
+
const normalizedProperty = property.toLowerCase();
|
|
2054
|
+
const isSuccess = Reflect.deleteProperty(target, normalizedProperty);
|
|
2055
|
+
if (isSuccess) {
|
|
2056
|
+
this.#explicitHeaders.delete(normalizedProperty);
|
|
2057
|
+
trackStateMutation(this.#trackedStateMutations, normalizedProperty);
|
|
2058
|
+
}
|
|
2059
|
+
return isSuccess;
|
|
2060
|
+
}
|
|
2061
|
+
return Reflect.deleteProperty(target, property);
|
|
2062
|
+
},
|
|
2063
|
+
});
|
|
2064
|
+
}
|
|
2065
|
+
#getFallbackRequestFunction() {
|
|
2066
|
+
const url = this.#internals.url;
|
|
2067
|
+
if (!url) {
|
|
2068
|
+
return;
|
|
2069
|
+
}
|
|
2070
|
+
if (url.protocol === 'https:') {
|
|
2071
|
+
if (this.#internals.http2) {
|
|
2072
|
+
if (major < 15 || (major === 15 && minor < 10)) {
|
|
2073
|
+
const error = new Error('To use the `http2` option, install Node.js 15.10.0 or above');
|
|
2074
|
+
error.code = 'EUNSUPPORTED';
|
|
2075
|
+
throw error;
|
|
2076
|
+
}
|
|
2077
|
+
return http2wrapper.auto;
|
|
2078
|
+
}
|
|
2079
|
+
return https.request;
|
|
2080
|
+
}
|
|
2081
|
+
return http.request;
|
|
2082
|
+
}
|
|
2083
|
+
#callFallbackRequest(url, options, callback) {
|
|
2084
|
+
const fallbackRequest = this.#getFallbackRequestFunction();
|
|
2085
|
+
if (!fallbackRequest) {
|
|
2086
|
+
throw new TypeError('The request function must return a value');
|
|
2087
|
+
}
|
|
2088
|
+
const fallbackResult = fallbackRequest(url, options, callback);
|
|
2089
|
+
if (fallbackResult === undefined) {
|
|
2090
|
+
throw new TypeError('The request function must return a value');
|
|
2091
|
+
}
|
|
2092
|
+
if (is.promise(fallbackResult)) {
|
|
2093
|
+
return this.#resolveFallbackRequestResult(fallbackResult);
|
|
2094
|
+
}
|
|
2095
|
+
return fallbackResult;
|
|
2096
|
+
}
|
|
2097
|
+
async #resolveRequestWithFallback(requestResult, url, options, callback) {
|
|
2098
|
+
const result = await requestResult;
|
|
2099
|
+
if (result !== undefined) {
|
|
2100
|
+
return result;
|
|
2101
|
+
}
|
|
2102
|
+
return this.#callFallbackRequest(url, options, callback);
|
|
2103
|
+
}
|
|
2104
|
+
async #resolveFallbackRequestResult(fallbackResult) {
|
|
2105
|
+
const resolvedFallbackResult = await fallbackResult;
|
|
2106
|
+
if (resolvedFallbackResult === undefined) {
|
|
2107
|
+
throw new TypeError('The request function must return a value');
|
|
2108
|
+
}
|
|
2109
|
+
return resolvedFallbackResult;
|
|
2110
|
+
}
|
|
1838
2111
|
}
|
|
2112
|
+
export const snapshotCrossOriginState = (options) => ({
|
|
2113
|
+
headers: { ...options.getInternalHeaders() },
|
|
2114
|
+
username: options.username,
|
|
2115
|
+
password: options.password,
|
|
2116
|
+
body: options.body,
|
|
2117
|
+
json: options.json,
|
|
2118
|
+
form: options.form,
|
|
2119
|
+
bodySnapshot: cloneCrossOriginBodyValue(options.body),
|
|
2120
|
+
jsonSnapshot: cloneCrossOriginBodyValue(options.json),
|
|
2121
|
+
formSnapshot: cloneCrossOriginBodyValue(options.form),
|
|
2122
|
+
});
|
|
2123
|
+
const cloneCrossOriginBodyValue = (value) => {
|
|
2124
|
+
if (value === undefined || value === null || typeof value !== 'object') {
|
|
2125
|
+
return value;
|
|
2126
|
+
}
|
|
2127
|
+
try {
|
|
2128
|
+
return structuredClone(value);
|
|
2129
|
+
}
|
|
2130
|
+
catch {
|
|
2131
|
+
return undefined;
|
|
2132
|
+
}
|
|
2133
|
+
};
|
|
2134
|
+
const isUnchangedCrossOriginBodyValue = (currentValue, previousValue, previousSnapshot) => {
|
|
2135
|
+
if (currentValue !== previousValue) {
|
|
2136
|
+
return false;
|
|
2137
|
+
}
|
|
2138
|
+
if (currentValue === undefined || currentValue === null || typeof currentValue !== 'object') {
|
|
2139
|
+
return true;
|
|
2140
|
+
}
|
|
2141
|
+
if (previousSnapshot === undefined) {
|
|
2142
|
+
return true;
|
|
2143
|
+
}
|
|
2144
|
+
return isDeepStrictEqual(currentValue, previousSnapshot);
|
|
2145
|
+
};
|
|
2146
|
+
export const isCrossOriginCredentialChanged = (previousUrl, nextUrl, credential) => (nextUrl[credential] !== '' && nextUrl[credential] !== previousUrl[credential]);
|
|
2147
|
+
export const isBodyUnchanged = (options, previousState) => isUnchangedCrossOriginBodyValue(options.body, previousState.body, previousState.bodySnapshot)
|
|
2148
|
+
&& isUnchangedCrossOriginBodyValue(options.json, previousState.json, previousState.jsonSnapshot)
|
|
2149
|
+
&& isUnchangedCrossOriginBodyValue(options.form, previousState.form, previousState.formSnapshot);
|