got 14.6.0 → 14.6.2

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.
@@ -40,7 +40,7 @@ export default function asPromise(firstRequest) {
40
40
  request.once('response', async (response) => {
41
41
  // Parse body
42
42
  const contentEncoding = (response.headers['content-encoding'] ?? '').toLowerCase();
43
- const isCompressed = contentEncoding === 'gzip' || contentEncoding === 'deflate' || contentEncoding === 'br';
43
+ const isCompressed = contentEncoding === 'gzip' || contentEncoding === 'deflate' || contentEncoding === 'br' || contentEncoding === 'zstd';
44
44
  const { options } = request;
45
45
  if (isCompressed && !options.decompress) {
46
46
  response.body = response.rawBody;
@@ -170,27 +170,35 @@ export default function asPromise(firstRequest) {
170
170
  emitter.off(event, function_);
171
171
  return promise;
172
172
  };
173
- const shortcut = (responseType) => {
173
+ const shortcut = (promiseToAwait, responseType) => {
174
174
  const newPromise = (async () => {
175
175
  // Wait until downloading has ended
176
- await promise;
176
+ await promiseToAwait;
177
177
  const { options } = globalResponse.request;
178
178
  return parseBody(globalResponse, responseType, options.parseJson, options.encoding);
179
179
  })();
180
180
  // eslint-disable-next-line @typescript-eslint/no-floating-promises
181
- Object.defineProperties(newPromise, Object.getOwnPropertyDescriptors(promise));
181
+ Object.defineProperties(newPromise, Object.getOwnPropertyDescriptors(promiseToAwait));
182
182
  return newPromise;
183
183
  };
184
- promise.json = () => {
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 () {
185
189
  if (globalRequest.options) {
186
190
  const { headers } = globalRequest.options;
187
191
  if (!globalRequest.writableFinished && !('accept' in headers)) {
188
192
  headers.accept = 'application/json';
189
193
  }
190
194
  }
191
- 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');
192
202
  };
193
- promise.buffer = () => shortcut('buffer');
194
- promise.text = () => shortcut('text');
195
203
  return promise;
196
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
- input?: string;
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
- this.name = 'RequestError';
21
- this.code = error.code ?? 'ERR_GOT_REQUEST_ERROR';
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(`Response code ${response.statusCode} (${response.statusMessage})`, {}, response.request);
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.name = 'CacheError';
83
- this.code = this.code === 'ERR_GOT_REQUEST_ERROR' ? 'ERR_CACHE_ACCESS' : this.code;
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.name = 'UploadError';
93
- this.code = this.code === 'ERR_GOT_REQUEST_ERROR' ? 'ERR_UPLOAD' : this.code;
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.name = 'ReadError';
117
- this.code = this.code === 'ERR_GOT_REQUEST_ERROR' ? 'ERR_READING_RESPONSE_STREAM' : this.code;
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
  }
@@ -107,7 +107,8 @@ export default class Request extends Duplex implements RequestEvents<Request> {
107
107
  private _flushed;
108
108
  private _aborted;
109
109
  private _expectedContentLength?;
110
- private _byteCounter?;
110
+ private _compressedBytesCount?;
111
+ private readonly _requestId;
111
112
  private _requestInitialized;
112
113
  constructor(url: UrlType, options?: OptionsType, defaults?: DefaultsType);
113
114
  flush(): Promise<void>;
@@ -183,5 +184,9 @@ export default class Request extends Duplex implements RequestEvents<Request> {
183
184
  */
184
185
  get isFromCache(): boolean | undefined;
185
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;
186
191
  }
187
192
  export {};