got 14.5.0 → 14.6.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.js +46 -10
- package/dist/source/core/diagnostics-channel.d.ts +89 -0
- package/dist/source/core/diagnostics-channel.js +49 -0
- package/dist/source/core/errors.d.ts +14 -1
- package/dist/source/core/errors.js +27 -19
- package/dist/source/core/index.d.ts +9 -1
- package/dist/source/core/index.js +429 -181
- package/dist/source/core/options.d.ts +245 -11
- package/dist/source/core/options.js +194 -68
- package/dist/source/core/response.d.ts +2 -0
- package/dist/source/core/response.js +2 -2
- package/dist/source/core/timed-out.d.ts +1 -0
- package/dist/source/core/timed-out.js +2 -3
- package/dist/source/core/utils/get-body-size.js +4 -2
- package/dist/source/core/utils/is-unix-socket-url.d.ts +16 -0
- package/dist/source/core/utils/is-unix-socket-url.js +21 -0
- package/dist/source/core/utils/weakable-map.d.ts +0 -1
- package/dist/source/core/utils/weakable-map.js +2 -6
- package/dist/source/create.js +9 -1
- package/dist/source/index.d.ts +1 -0
- package/dist/source/index.js +1 -0
- package/package.json +10 -8
- package/readme.md +1 -0
|
@@ -18,12 +18,14 @@ export default function asPromise(firstRequest) {
|
|
|
18
18
|
let globalResponse;
|
|
19
19
|
let normalizedOptions;
|
|
20
20
|
const emitter = new EventEmitter();
|
|
21
|
+
let promiseSettled = false;
|
|
21
22
|
const promise = new PCancelable((resolve, reject, onCancel) => {
|
|
22
23
|
onCancel(() => {
|
|
23
24
|
globalRequest.destroy();
|
|
24
25
|
});
|
|
25
26
|
onCancel.shouldReject = false;
|
|
26
27
|
onCancel(() => {
|
|
28
|
+
promiseSettled = true;
|
|
27
29
|
reject(new CancelError(globalRequest));
|
|
28
30
|
});
|
|
29
31
|
const makeRequest = (retryCount) => {
|
|
@@ -38,7 +40,7 @@ export default function asPromise(firstRequest) {
|
|
|
38
40
|
request.once('response', async (response) => {
|
|
39
41
|
// Parse body
|
|
40
42
|
const contentEncoding = (response.headers['content-encoding'] ?? '').toLowerCase();
|
|
41
|
-
const isCompressed = contentEncoding === 'gzip' || contentEncoding === 'deflate' || contentEncoding === 'br';
|
|
43
|
+
const isCompressed = contentEncoding === 'gzip' || contentEncoding === 'deflate' || contentEncoding === 'br' || contentEncoding === 'zstd';
|
|
42
44
|
const { options } = request;
|
|
43
45
|
if (isCompressed && !options.decompress) {
|
|
44
46
|
response.body = response.rawBody;
|
|
@@ -82,7 +84,7 @@ export default function asPromise(firstRequest) {
|
|
|
82
84
|
}
|
|
83
85
|
throw new RetryError(request);
|
|
84
86
|
});
|
|
85
|
-
if (!(is.object(response) && is.number(response.statusCode) &&
|
|
87
|
+
if (!(is.object(response) && is.number(response.statusCode) && 'body' in response)) {
|
|
86
88
|
throw new TypeError('The `afterResponse` hook returned an invalid value');
|
|
87
89
|
}
|
|
88
90
|
}
|
|
@@ -97,12 +99,27 @@ export default function asPromise(firstRequest) {
|
|
|
97
99
|
return;
|
|
98
100
|
}
|
|
99
101
|
request.destroy();
|
|
102
|
+
promiseSettled = true;
|
|
100
103
|
resolve(request.options.resolveBodyOnly ? response.body : response);
|
|
101
104
|
});
|
|
105
|
+
let handledFinalError = false;
|
|
102
106
|
const onError = (error) => {
|
|
103
107
|
if (promise.isCanceled) {
|
|
104
108
|
return;
|
|
105
109
|
}
|
|
110
|
+
// Route errors emitted directly on the stream (e.g., EPIPE from Node.js)
|
|
111
|
+
// through retry logic first, then handle them here after retries are exhausted.
|
|
112
|
+
// See https://github.com/sindresorhus/got/issues/1995
|
|
113
|
+
if (!request._stopReading) {
|
|
114
|
+
request._beforeError(error);
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
// Allow the manual re-emission from Request to land only once.
|
|
118
|
+
if (handledFinalError) {
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
handledFinalError = true;
|
|
122
|
+
promiseSettled = true;
|
|
106
123
|
const { options } = request;
|
|
107
124
|
if (error instanceof HTTPError && !options.throwHttpErrors) {
|
|
108
125
|
const { response } = error;
|
|
@@ -112,10 +129,21 @@ export default function asPromise(firstRequest) {
|
|
|
112
129
|
}
|
|
113
130
|
reject(error);
|
|
114
131
|
};
|
|
115
|
-
|
|
132
|
+
// Use .on() instead of .once() to keep the listener active across retries.
|
|
133
|
+
// When _stopReading is false, we return early and the error gets re-emitted
|
|
134
|
+
// after retry logic completes, so we need this listener to remain active.
|
|
135
|
+
// See https://github.com/sindresorhus/got/issues/1995
|
|
136
|
+
request.on('error', onError);
|
|
116
137
|
const previousBody = request.options?.body;
|
|
117
138
|
request.once('retry', (newRetryCount, error) => {
|
|
118
139
|
firstRequest = undefined;
|
|
140
|
+
// If promise already settled, don't retry
|
|
141
|
+
// This prevents the race condition in #1489 where a late error
|
|
142
|
+
// (e.g., ECONNRESET after successful response) triggers retry
|
|
143
|
+
// after the promise has already resolved/rejected
|
|
144
|
+
if (promiseSettled) {
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
119
147
|
const newBody = request.options.body;
|
|
120
148
|
if (previousBody === newBody && is.nodeStream(newBody)) {
|
|
121
149
|
error.message = 'Cannot retry with consumed body stream';
|
|
@@ -142,27 +170,35 @@ export default function asPromise(firstRequest) {
|
|
|
142
170
|
emitter.off(event, function_);
|
|
143
171
|
return promise;
|
|
144
172
|
};
|
|
145
|
-
const shortcut = (responseType) => {
|
|
173
|
+
const shortcut = (promiseToAwait, responseType) => {
|
|
146
174
|
const newPromise = (async () => {
|
|
147
175
|
// Wait until downloading has ended
|
|
148
|
-
await
|
|
176
|
+
await promiseToAwait;
|
|
149
177
|
const { options } = globalResponse.request;
|
|
150
178
|
return parseBody(globalResponse, responseType, options.parseJson, options.encoding);
|
|
151
179
|
})();
|
|
152
180
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
153
|
-
Object.defineProperties(newPromise, Object.getOwnPropertyDescriptors(
|
|
181
|
+
Object.defineProperties(newPromise, Object.getOwnPropertyDescriptors(promiseToAwait));
|
|
154
182
|
return newPromise;
|
|
155
183
|
};
|
|
156
|
-
|
|
184
|
+
// Note: These use `function` syntax (not arrows) to access `this` context.
|
|
185
|
+
// When custom handlers wrap the promise to transform errors, these methods
|
|
186
|
+
// are copied to the handler's promise. Using `this` ensures we await the
|
|
187
|
+
// handler's wrapped promise, not the original, so errors propagate correctly.
|
|
188
|
+
promise.json = function () {
|
|
157
189
|
if (globalRequest.options) {
|
|
158
190
|
const { headers } = globalRequest.options;
|
|
159
191
|
if (!globalRequest.writableFinished && !('accept' in headers)) {
|
|
160
192
|
headers.accept = 'application/json';
|
|
161
193
|
}
|
|
162
194
|
}
|
|
163
|
-
return shortcut('json');
|
|
195
|
+
return shortcut(this, 'json');
|
|
196
|
+
};
|
|
197
|
+
promise.buffer = function () {
|
|
198
|
+
return shortcut(this, 'buffer');
|
|
199
|
+
};
|
|
200
|
+
promise.text = function () {
|
|
201
|
+
return shortcut(this, 'text');
|
|
164
202
|
};
|
|
165
|
-
promise.buffer = () => shortcut('buffer');
|
|
166
|
-
promise.text = () => shortcut('text');
|
|
167
203
|
return promise;
|
|
168
204
|
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import type { Timings } from '@szmarczak/http-timer';
|
|
2
|
+
import type { RequestError } from './errors.js';
|
|
3
|
+
export type RequestId = string;
|
|
4
|
+
/**
|
|
5
|
+
Message for the `got:request:create` diagnostic channel.
|
|
6
|
+
|
|
7
|
+
Emitted when a request is created.
|
|
8
|
+
*/
|
|
9
|
+
export type DiagnosticRequestCreate = {
|
|
10
|
+
requestId: RequestId;
|
|
11
|
+
url: string;
|
|
12
|
+
method: string;
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
Message for the `got:request:start` diagnostic channel.
|
|
16
|
+
|
|
17
|
+
Emitted before the native HTTP request is sent.
|
|
18
|
+
*/
|
|
19
|
+
export type DiagnosticRequestStart = {
|
|
20
|
+
requestId: RequestId;
|
|
21
|
+
url: string;
|
|
22
|
+
method: string;
|
|
23
|
+
headers: Record<string, string | string[] | undefined>;
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
Message for the `got:response:start` diagnostic channel.
|
|
27
|
+
|
|
28
|
+
Emitted when response headers are received.
|
|
29
|
+
*/
|
|
30
|
+
export type DiagnosticResponseStart = {
|
|
31
|
+
requestId: RequestId;
|
|
32
|
+
url: string;
|
|
33
|
+
statusCode: number;
|
|
34
|
+
headers: Record<string, string | string[] | undefined>;
|
|
35
|
+
isFromCache: boolean;
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
Message for the `got:response:end` diagnostic channel.
|
|
39
|
+
|
|
40
|
+
Emitted when the response completes.
|
|
41
|
+
*/
|
|
42
|
+
export type DiagnosticResponseEnd = {
|
|
43
|
+
requestId: RequestId;
|
|
44
|
+
url: string;
|
|
45
|
+
statusCode: number;
|
|
46
|
+
bodySize?: number;
|
|
47
|
+
timings?: Timings;
|
|
48
|
+
};
|
|
49
|
+
/**
|
|
50
|
+
Message for the `got:request:retry` diagnostic channel.
|
|
51
|
+
|
|
52
|
+
Emitted when retrying a request.
|
|
53
|
+
*/
|
|
54
|
+
export type DiagnosticRequestRetry = {
|
|
55
|
+
requestId: RequestId;
|
|
56
|
+
retryCount: number;
|
|
57
|
+
error: RequestError;
|
|
58
|
+
delay: number;
|
|
59
|
+
};
|
|
60
|
+
/**
|
|
61
|
+
Message for the `got:request:error` diagnostic channel.
|
|
62
|
+
|
|
63
|
+
Emitted when a request fails.
|
|
64
|
+
*/
|
|
65
|
+
export type DiagnosticRequestError = {
|
|
66
|
+
requestId: RequestId;
|
|
67
|
+
url: string;
|
|
68
|
+
error: RequestError;
|
|
69
|
+
timings?: Timings;
|
|
70
|
+
};
|
|
71
|
+
/**
|
|
72
|
+
Message for the `got:response:redirect` diagnostic channel.
|
|
73
|
+
|
|
74
|
+
Emitted when following a redirect.
|
|
75
|
+
*/
|
|
76
|
+
export type DiagnosticResponseRedirect = {
|
|
77
|
+
requestId: RequestId;
|
|
78
|
+
fromUrl: string;
|
|
79
|
+
toUrl: string;
|
|
80
|
+
statusCode: number;
|
|
81
|
+
};
|
|
82
|
+
export declare function generateRequestId(): RequestId;
|
|
83
|
+
export declare function publishRequestCreate(message: DiagnosticRequestCreate): void;
|
|
84
|
+
export declare function publishRequestStart(message: DiagnosticRequestStart): void;
|
|
85
|
+
export declare function publishResponseStart(message: DiagnosticResponseStart): void;
|
|
86
|
+
export declare function publishResponseEnd(message: DiagnosticResponseEnd): void;
|
|
87
|
+
export declare function publishRetry(message: DiagnosticRequestRetry): void;
|
|
88
|
+
export declare function publishError(message: DiagnosticRequestError): void;
|
|
89
|
+
export declare function publishRedirect(message: DiagnosticResponseRedirect): void;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import diagnosticsChannel from 'node:diagnostics_channel';
|
|
3
|
+
const channels = {
|
|
4
|
+
requestCreate: diagnosticsChannel.channel('got:request:create'),
|
|
5
|
+
requestStart: diagnosticsChannel.channel('got:request:start'),
|
|
6
|
+
responseStart: diagnosticsChannel.channel('got:response:start'),
|
|
7
|
+
responseEnd: diagnosticsChannel.channel('got:response:end'),
|
|
8
|
+
retry: diagnosticsChannel.channel('got:request:retry'),
|
|
9
|
+
error: diagnosticsChannel.channel('got:request:error'),
|
|
10
|
+
redirect: diagnosticsChannel.channel('got:response:redirect'),
|
|
11
|
+
};
|
|
12
|
+
export function generateRequestId() {
|
|
13
|
+
return randomUUID();
|
|
14
|
+
}
|
|
15
|
+
export function publishRequestCreate(message) {
|
|
16
|
+
if (channels.requestCreate.hasSubscribers) {
|
|
17
|
+
channels.requestCreate.publish(message);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
export function publishRequestStart(message) {
|
|
21
|
+
if (channels.requestStart.hasSubscribers) {
|
|
22
|
+
channels.requestStart.publish(message);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
export function publishResponseStart(message) {
|
|
26
|
+
if (channels.responseStart.hasSubscribers) {
|
|
27
|
+
channels.responseStart.publish(message);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
export function publishResponseEnd(message) {
|
|
31
|
+
if (channels.responseEnd.hasSubscribers) {
|
|
32
|
+
channels.responseEnd.publish(message);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
export function publishRetry(message) {
|
|
36
|
+
if (channels.retry.hasSubscribers) {
|
|
37
|
+
channels.retry.publish(message);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
export function publishError(message) {
|
|
41
|
+
if (channels.error.hasSubscribers) {
|
|
42
|
+
channels.error.publish(message);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
export function publishRedirect(message) {
|
|
46
|
+
if (channels.redirect.hasSubscribers) {
|
|
47
|
+
channels.redirect.publish(message);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -9,8 +9,9 @@ An error to be thrown when a request fails.
|
|
|
9
9
|
Contains a `code` property with error class code, like `ECONNREFUSED`.
|
|
10
10
|
*/
|
|
11
11
|
export declare class RequestError<T = unknown> extends Error {
|
|
12
|
-
|
|
12
|
+
name: string;
|
|
13
13
|
code: string;
|
|
14
|
+
input?: string;
|
|
14
15
|
stack: string;
|
|
15
16
|
readonly options: Options;
|
|
16
17
|
readonly response?: Response<T>;
|
|
@@ -25,6 +26,8 @@ An error to be thrown when the server redirects you more than ten times.
|
|
|
25
26
|
Includes a `response` property.
|
|
26
27
|
*/
|
|
27
28
|
export declare class MaxRedirectsError extends RequestError {
|
|
29
|
+
name: string;
|
|
30
|
+
code: string;
|
|
28
31
|
readonly response: Response;
|
|
29
32
|
readonly request: Request;
|
|
30
33
|
readonly timings: Timings;
|
|
@@ -35,6 +38,8 @@ An error to be thrown when the server response code is not 2xx nor 3xx if `optio
|
|
|
35
38
|
Includes a `response` property.
|
|
36
39
|
*/
|
|
37
40
|
export declare class HTTPError<T = any> extends RequestError<T> {
|
|
41
|
+
name: string;
|
|
42
|
+
code: string;
|
|
38
43
|
readonly response: Response<T>;
|
|
39
44
|
readonly request: Request;
|
|
40
45
|
readonly timings: Timings;
|
|
@@ -45,6 +50,7 @@ An error to be thrown when a cache method fails.
|
|
|
45
50
|
For example, if the database goes down or there's a filesystem error.
|
|
46
51
|
*/
|
|
47
52
|
export declare class CacheError extends RequestError {
|
|
53
|
+
name: string;
|
|
48
54
|
readonly request: Request;
|
|
49
55
|
constructor(error: Error, request: Request);
|
|
50
56
|
}
|
|
@@ -52,6 +58,7 @@ export declare class CacheError extends RequestError {
|
|
|
52
58
|
An error to be thrown when the request body is a stream and an error occurs while reading from that stream.
|
|
53
59
|
*/
|
|
54
60
|
export declare class UploadError extends RequestError {
|
|
61
|
+
name: string;
|
|
55
62
|
readonly request: Request;
|
|
56
63
|
constructor(error: Error, request: Request);
|
|
57
64
|
}
|
|
@@ -60,6 +67,7 @@ An error to be thrown when the request is aborted due to a timeout.
|
|
|
60
67
|
Includes an `event` and `timings` property.
|
|
61
68
|
*/
|
|
62
69
|
export declare class TimeoutError extends RequestError {
|
|
70
|
+
name: string;
|
|
63
71
|
readonly request: Request;
|
|
64
72
|
readonly timings: Timings;
|
|
65
73
|
readonly event: string;
|
|
@@ -69,6 +77,7 @@ export declare class TimeoutError extends RequestError {
|
|
|
69
77
|
An error to be thrown when reading from response stream fails.
|
|
70
78
|
*/
|
|
71
79
|
export declare class ReadError extends RequestError {
|
|
80
|
+
name: string;
|
|
72
81
|
readonly request: Request;
|
|
73
82
|
readonly response: Response;
|
|
74
83
|
readonly timings: Timings;
|
|
@@ -78,12 +87,16 @@ export declare class ReadError extends RequestError {
|
|
|
78
87
|
An error which always triggers a new retry when thrown.
|
|
79
88
|
*/
|
|
80
89
|
export declare class RetryError extends RequestError {
|
|
90
|
+
name: string;
|
|
91
|
+
code: string;
|
|
81
92
|
constructor(request: Request);
|
|
82
93
|
}
|
|
83
94
|
/**
|
|
84
95
|
An error to be thrown when the request is aborted by AbortController.
|
|
85
96
|
*/
|
|
86
97
|
export declare class AbortError extends RequestError {
|
|
98
|
+
name: string;
|
|
99
|
+
code: string;
|
|
87
100
|
constructor(request: Request);
|
|
88
101
|
}
|
|
89
102
|
export {};
|
|
@@ -8,8 +8,9 @@ An error to be thrown when a request fails.
|
|
|
8
8
|
Contains a `code` property with error class code, like `ECONNREFUSED`.
|
|
9
9
|
*/
|
|
10
10
|
export class RequestError extends Error {
|
|
11
|
+
name = 'RequestError';
|
|
12
|
+
code = 'ERR_GOT_REQUEST_ERROR';
|
|
11
13
|
input;
|
|
12
|
-
code;
|
|
13
14
|
stack;
|
|
14
15
|
response;
|
|
15
16
|
request;
|
|
@@ -17,8 +18,9 @@ export class RequestError extends Error {
|
|
|
17
18
|
constructor(message, error, self) {
|
|
18
19
|
super(message, { cause: error });
|
|
19
20
|
Error.captureStackTrace(this, this.constructor);
|
|
20
|
-
|
|
21
|
-
|
|
21
|
+
if (error.code) {
|
|
22
|
+
this.code = error.code;
|
|
23
|
+
}
|
|
22
24
|
this.input = error.input;
|
|
23
25
|
if (isRequest(self)) {
|
|
24
26
|
Object.defineProperty(this, 'request', {
|
|
@@ -53,10 +55,10 @@ An error to be thrown when the server redirects you more than ten times.
|
|
|
53
55
|
Includes a `response` property.
|
|
54
56
|
*/
|
|
55
57
|
export class MaxRedirectsError extends RequestError {
|
|
58
|
+
name = 'MaxRedirectsError';
|
|
59
|
+
code = 'ERR_TOO_MANY_REDIRECTS';
|
|
56
60
|
constructor(request) {
|
|
57
61
|
super(`Redirected ${request.options.maxRedirects} times. Aborting.`, {}, request);
|
|
58
|
-
this.name = 'MaxRedirectsError';
|
|
59
|
-
this.code = 'ERR_TOO_MANY_REDIRECTS';
|
|
60
62
|
}
|
|
61
63
|
}
|
|
62
64
|
/**
|
|
@@ -66,10 +68,10 @@ Includes a `response` property.
|
|
|
66
68
|
// TODO: Change `HTTPError<T = any>` to `HTTPError<T = unknown>` in the next major version to enforce type usage.
|
|
67
69
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
68
70
|
export class HTTPError extends RequestError {
|
|
71
|
+
name = 'HTTPError';
|
|
72
|
+
code = 'ERR_NON_2XX_3XX_RESPONSE';
|
|
69
73
|
constructor(response) {
|
|
70
|
-
super(`
|
|
71
|
-
this.name = 'HTTPError';
|
|
72
|
-
this.code = 'ERR_NON_2XX_3XX_RESPONSE';
|
|
74
|
+
super(`Request failed with status code ${response.statusCode} (${response.statusMessage}): ${response.request.options.method} ${response.request.options.url.toString()}`, {}, response.request);
|
|
73
75
|
}
|
|
74
76
|
}
|
|
75
77
|
/**
|
|
@@ -77,20 +79,24 @@ An error to be thrown when a cache method fails.
|
|
|
77
79
|
For example, if the database goes down or there's a filesystem error.
|
|
78
80
|
*/
|
|
79
81
|
export class CacheError extends RequestError {
|
|
82
|
+
name = 'CacheError';
|
|
80
83
|
constructor(error, request) {
|
|
81
84
|
super(error.message, error, request);
|
|
82
|
-
this.
|
|
83
|
-
|
|
85
|
+
if (this.code === 'ERR_GOT_REQUEST_ERROR') {
|
|
86
|
+
this.code = 'ERR_CACHE_ACCESS';
|
|
87
|
+
}
|
|
84
88
|
}
|
|
85
89
|
}
|
|
86
90
|
/**
|
|
87
91
|
An error to be thrown when the request body is a stream and an error occurs while reading from that stream.
|
|
88
92
|
*/
|
|
89
93
|
export class UploadError extends RequestError {
|
|
94
|
+
name = 'UploadError';
|
|
90
95
|
constructor(error, request) {
|
|
91
96
|
super(error.message, error, request);
|
|
92
|
-
this.
|
|
93
|
-
|
|
97
|
+
if (this.code === 'ERR_GOT_REQUEST_ERROR') {
|
|
98
|
+
this.code = 'ERR_UPLOAD';
|
|
99
|
+
}
|
|
94
100
|
}
|
|
95
101
|
}
|
|
96
102
|
/**
|
|
@@ -98,11 +104,11 @@ An error to be thrown when the request is aborted due to a timeout.
|
|
|
98
104
|
Includes an `event` and `timings` property.
|
|
99
105
|
*/
|
|
100
106
|
export class TimeoutError extends RequestError {
|
|
107
|
+
name = 'TimeoutError';
|
|
101
108
|
timings;
|
|
102
109
|
event;
|
|
103
110
|
constructor(error, timings, request) {
|
|
104
111
|
super(error.message, error, request);
|
|
105
|
-
this.name = 'TimeoutError';
|
|
106
112
|
this.event = error.event;
|
|
107
113
|
this.timings = timings;
|
|
108
114
|
}
|
|
@@ -111,29 +117,31 @@ export class TimeoutError extends RequestError {
|
|
|
111
117
|
An error to be thrown when reading from response stream fails.
|
|
112
118
|
*/
|
|
113
119
|
export class ReadError extends RequestError {
|
|
120
|
+
name = 'ReadError';
|
|
114
121
|
constructor(error, request) {
|
|
115
122
|
super(error.message, error, request);
|
|
116
|
-
this.
|
|
117
|
-
|
|
123
|
+
if (this.code === 'ERR_GOT_REQUEST_ERROR') {
|
|
124
|
+
this.code = 'ERR_READING_RESPONSE_STREAM';
|
|
125
|
+
}
|
|
118
126
|
}
|
|
119
127
|
}
|
|
120
128
|
/**
|
|
121
129
|
An error which always triggers a new retry when thrown.
|
|
122
130
|
*/
|
|
123
131
|
export class RetryError extends RequestError {
|
|
132
|
+
name = 'RetryError';
|
|
133
|
+
code = 'ERR_RETRYING';
|
|
124
134
|
constructor(request) {
|
|
125
135
|
super('Retrying', {}, request);
|
|
126
|
-
this.name = 'RetryError';
|
|
127
|
-
this.code = 'ERR_RETRYING';
|
|
128
136
|
}
|
|
129
137
|
}
|
|
130
138
|
/**
|
|
131
139
|
An error to be thrown when the request is aborted by AbortController.
|
|
132
140
|
*/
|
|
133
141
|
export class AbortError extends RequestError {
|
|
142
|
+
name = 'AbortError';
|
|
143
|
+
code = 'ERR_ABORTED';
|
|
134
144
|
constructor(request) {
|
|
135
145
|
super('This operation was aborted.', {}, request);
|
|
136
|
-
this.code = 'ERR_ABORTED';
|
|
137
|
-
this.name = 'AbortError';
|
|
138
146
|
}
|
|
139
147
|
}
|
|
@@ -88,11 +88,11 @@ export default class Request extends Duplex implements RequestEvents<Request> {
|
|
|
88
88
|
requestUrl?: URL;
|
|
89
89
|
redirectUrls: URL[];
|
|
90
90
|
retryCount: number;
|
|
91
|
+
_stopReading: boolean;
|
|
91
92
|
private _requestOptions;
|
|
92
93
|
private _stopRetry;
|
|
93
94
|
private _downloadedSize;
|
|
94
95
|
private _uploadedSize;
|
|
95
|
-
private _stopReading;
|
|
96
96
|
private readonly _pipedServerResponses;
|
|
97
97
|
private _request?;
|
|
98
98
|
private _responseSize?;
|
|
@@ -106,6 +106,9 @@ export default class Request extends Duplex implements RequestEvents<Request> {
|
|
|
106
106
|
private _nativeResponse?;
|
|
107
107
|
private _flushed;
|
|
108
108
|
private _aborted;
|
|
109
|
+
private _expectedContentLength?;
|
|
110
|
+
private _byteCounter?;
|
|
111
|
+
private readonly _requestId;
|
|
109
112
|
private _requestInitialized;
|
|
110
113
|
constructor(url: UrlType, options?: OptionsType, defaults?: DefaultsType);
|
|
111
114
|
flush(): Promise<void>;
|
|
@@ -118,6 +121,7 @@ export default class Request extends Duplex implements RequestEvents<Request> {
|
|
|
118
121
|
end?: boolean;
|
|
119
122
|
}): T;
|
|
120
123
|
unpipe<T extends NodeJS.WritableStream>(destination: T): this;
|
|
124
|
+
private _checkContentLengthMismatch;
|
|
121
125
|
private _finalizeBody;
|
|
122
126
|
private _onResponseBase;
|
|
123
127
|
private _setRawBody;
|
|
@@ -180,5 +184,9 @@ export default class Request extends Duplex implements RequestEvents<Request> {
|
|
|
180
184
|
*/
|
|
181
185
|
get isFromCache(): boolean | undefined;
|
|
182
186
|
get reusedSocket(): boolean | undefined;
|
|
187
|
+
/**
|
|
188
|
+
Whether the stream is read-only. Returns `true` when `body`, `json`, or `form` options are provided.
|
|
189
|
+
*/
|
|
190
|
+
get isReadonly(): boolean;
|
|
183
191
|
}
|
|
184
192
|
export {};
|