undici 7.14.0 → 7.16.0
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/README.md +1 -1
- package/docs/docs/api/Agent.md +1 -0
- package/docs/docs/api/Dispatcher.md +59 -0
- package/docs/docs/api/Errors.md +0 -1
- package/index-fetch.js +2 -2
- package/index.js +6 -9
- package/lib/api/api-request.js +22 -8
- package/lib/api/readable.js +7 -5
- package/lib/core/errors.js +217 -13
- package/lib/core/request.js +5 -1
- package/lib/core/util.js +45 -11
- package/lib/dispatcher/agent.js +44 -23
- package/lib/dispatcher/client-h1.js +20 -9
- package/lib/dispatcher/client-h2.js +13 -3
- package/lib/dispatcher/client.js +57 -57
- package/lib/dispatcher/dispatcher-base.js +12 -7
- package/lib/dispatcher/env-http-proxy-agent.js +12 -16
- package/lib/dispatcher/fixed-queue.js +15 -39
- package/lib/dispatcher/h2c-client.js +6 -6
- package/lib/dispatcher/pool-base.js +60 -43
- package/lib/dispatcher/pool.js +2 -2
- package/lib/dispatcher/proxy-agent.js +14 -9
- package/lib/global.js +19 -1
- package/lib/interceptor/cache.js +61 -0
- package/lib/interceptor/decompress.js +253 -0
- package/lib/llhttp/constants.d.ts +99 -1
- package/lib/llhttp/constants.js +34 -1
- package/lib/llhttp/llhttp-wasm.js +1 -1
- package/lib/llhttp/llhttp_simd-wasm.js +1 -1
- package/lib/llhttp/utils.d.ts +2 -2
- package/lib/llhttp/utils.js +3 -6
- package/lib/mock/mock-agent.js +4 -4
- package/lib/mock/mock-errors.js +10 -0
- package/lib/mock/mock-utils.js +12 -10
- package/lib/util/cache.js +6 -7
- package/lib/util/date.js +534 -140
- package/lib/web/cookies/index.js +1 -1
- package/lib/web/cookies/parse.js +2 -2
- package/lib/web/eventsource/eventsource-stream.js +2 -2
- package/lib/web/eventsource/eventsource.js +34 -29
- package/lib/web/eventsource/util.js +1 -9
- package/lib/web/fetch/body.js +20 -26
- package/lib/web/fetch/index.js +15 -16
- package/lib/web/fetch/response.js +2 -4
- package/lib/web/fetch/util.js +8 -230
- package/lib/web/subresource-integrity/Readme.md +9 -0
- package/lib/web/subresource-integrity/subresource-integrity.js +306 -0
- package/lib/web/webidl/index.js +203 -42
- package/lib/web/websocket/connection.js +4 -3
- package/lib/web/websocket/events.js +1 -1
- package/lib/web/websocket/stream/websocketerror.js +22 -1
- package/lib/web/websocket/stream/websocketstream.js +16 -7
- package/lib/web/websocket/websocket.js +32 -42
- package/package.json +9 -7
- package/types/agent.d.ts +1 -0
- package/types/diagnostics-channel.d.ts +0 -1
- package/types/errors.d.ts +5 -15
- package/types/interceptors.d.ts +5 -0
- package/types/snapshot-agent.d.ts +5 -3
- package/types/webidl.d.ts +82 -21
- package/lib/api/util.js +0 -95
- package/lib/llhttp/constants.js.map +0 -1
- package/lib/llhttp/utils.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# undici
|
|
2
2
|
|
|
3
|
-
[](https://github.com/nodejs/undici/actions/workflows/nodejs.yml) [](https://github.com/neostandard/neostandard) [](https://badge.fury.io/js/undici) [](https://codecov.io/gh/nodejs/undici)
|
|
4
4
|
|
|
5
5
|
An HTTP/1.1 client, written from scratch for Node.js.
|
|
6
6
|
|
package/docs/docs/api/Agent.md
CHANGED
|
@@ -19,6 +19,7 @@ Returns: `Agent`
|
|
|
19
19
|
Extends: [`PoolOptions`](/docs/docs/api/Pool.md#parameter-pooloptions)
|
|
20
20
|
|
|
21
21
|
* **factory** `(origin: URL, opts: Object) => Dispatcher` - Default: `(origin, opts) => new Pool(origin, opts)`
|
|
22
|
+
* **maxOrigins** `number` (optional) - Default: `Infinity` - Limits the total number of origins that can receive requests at a time, throwing an `MaxOriginsReachedError` error when attempting to dispatch when the max is reached. If `Infinity`, no limit is enforced.
|
|
22
23
|
|
|
23
24
|
## Instance Properties
|
|
24
25
|
|
|
@@ -1094,6 +1094,65 @@ await client.request({
|
|
|
1094
1094
|
});
|
|
1095
1095
|
```
|
|
1096
1096
|
|
|
1097
|
+
##### `decompress`
|
|
1098
|
+
|
|
1099
|
+
⚠️ The decompress interceptor is experimental and subject to change.
|
|
1100
|
+
|
|
1101
|
+
The `decompress` interceptor automatically decompresses response bodies that are compressed with gzip, deflate, brotli, or zstd compression. It removes the `content-encoding` and `content-length` headers from decompressed responses and supports RFC-9110 compliant multiple encodings.
|
|
1102
|
+
|
|
1103
|
+
**Options**
|
|
1104
|
+
|
|
1105
|
+
- `skipErrorResponses` - Whether to skip decompression for error responses (status codes >= 400). Default: `true`.
|
|
1106
|
+
- `skipStatusCodes` - Array of status codes to skip decompression for. Default: `[204, 304]`.
|
|
1107
|
+
|
|
1108
|
+
**Example - Basic Decompress Interceptor**
|
|
1109
|
+
|
|
1110
|
+
```js
|
|
1111
|
+
const { Client, interceptors } = require("undici");
|
|
1112
|
+
const { decompress } = interceptors;
|
|
1113
|
+
|
|
1114
|
+
const client = new Client("http://example.com").compose(
|
|
1115
|
+
decompress()
|
|
1116
|
+
);
|
|
1117
|
+
|
|
1118
|
+
// Automatically decompresses gzip/deflate/brotli/zstd responses
|
|
1119
|
+
const response = await client.request({
|
|
1120
|
+
method: "GET",
|
|
1121
|
+
path: "/"
|
|
1122
|
+
});
|
|
1123
|
+
```
|
|
1124
|
+
|
|
1125
|
+
**Example - Custom Options**
|
|
1126
|
+
|
|
1127
|
+
```js
|
|
1128
|
+
const { Client, interceptors } = require("undici");
|
|
1129
|
+
const { decompress } = interceptors;
|
|
1130
|
+
|
|
1131
|
+
const client = new Client("http://example.com").compose(
|
|
1132
|
+
decompress({
|
|
1133
|
+
skipErrorResponses: false, // Decompress 5xx responses
|
|
1134
|
+
skipStatusCodes: [204, 304, 201] // Skip these status codes
|
|
1135
|
+
})
|
|
1136
|
+
);
|
|
1137
|
+
```
|
|
1138
|
+
|
|
1139
|
+
**Supported Encodings**
|
|
1140
|
+
|
|
1141
|
+
- `gzip` / `x-gzip` - GZIP compression
|
|
1142
|
+
- `deflate` / `x-compress` - DEFLATE compression
|
|
1143
|
+
- `br` - Brotli compression
|
|
1144
|
+
- `zstd` - Zstandard compression
|
|
1145
|
+
- Multiple encodings (e.g., `gzip, deflate`) are supported per RFC-9110
|
|
1146
|
+
|
|
1147
|
+
**Behavior**
|
|
1148
|
+
|
|
1149
|
+
- Skips decompression for status codes < 200 or >= 400 (configurable)
|
|
1150
|
+
- Skips decompression for 204 No Content and 304 Not Modified by default
|
|
1151
|
+
- Removes `content-encoding` and `content-length` headers when decompressing
|
|
1152
|
+
- Passes through unsupported encodings unchanged
|
|
1153
|
+
- Handles case-insensitive encoding names
|
|
1154
|
+
- Supports streaming decompression without buffering
|
|
1155
|
+
|
|
1097
1156
|
##### `Cache Interceptor`
|
|
1098
1157
|
|
|
1099
1158
|
The `cache` interceptor implements client-side response caching as described in
|
package/docs/docs/api/Errors.md
CHANGED
|
@@ -14,7 +14,6 @@ import { errors } from 'undici'
|
|
|
14
14
|
| `HeadersTimeoutError` | `UND_ERR_HEADERS_TIMEOUT` | socket is destroyed due to headers timeout. |
|
|
15
15
|
| `HeadersOverflowError` | `UND_ERR_HEADERS_OVERFLOW` | socket is destroyed due to headers' max size being exceeded. |
|
|
16
16
|
| `BodyTimeoutError` | `UND_ERR_BODY_TIMEOUT` | socket is destroyed due to body timeout. |
|
|
17
|
-
| `ResponseStatusCodeError` | `UND_ERR_RESPONSE_STATUS_CODE` | an error is thrown when `throwOnError` is `true` for status codes >= 400. |
|
|
18
17
|
| `InvalidArgumentError` | `UND_ERR_INVALID_ARG` | passed an invalid argument. |
|
|
19
18
|
| `InvalidReturnValueError` | `UND_ERR_INVALID_RETURN_VALUE` | returned an invalid value. |
|
|
20
19
|
| `RequestAbortedError` | `UND_ERR_ABORTED` | the request has been aborted by the user |
|
package/index-fetch.js
CHANGED
|
@@ -4,8 +4,8 @@ const { getGlobalDispatcher, setGlobalDispatcher } = require('./lib/global')
|
|
|
4
4
|
const EnvHttpProxyAgent = require('./lib/dispatcher/env-http-proxy-agent')
|
|
5
5
|
const fetchImpl = require('./lib/web/fetch').fetch
|
|
6
6
|
|
|
7
|
-
module.exports.fetch = function fetch (
|
|
8
|
-
return fetchImpl(
|
|
7
|
+
module.exports.fetch = function fetch (init, options = undefined) {
|
|
8
|
+
return fetchImpl(init, options).catch(err => {
|
|
9
9
|
if (err && typeof err === 'object') {
|
|
10
10
|
Error.captureStackTrace(err)
|
|
11
11
|
}
|
package/index.js
CHANGED
|
@@ -46,7 +46,8 @@ module.exports.interceptors = {
|
|
|
46
46
|
retry: require('./lib/interceptor/retry'),
|
|
47
47
|
dump: require('./lib/interceptor/dump'),
|
|
48
48
|
dns: require('./lib/interceptor/dns'),
|
|
49
|
-
cache: require('./lib/interceptor/cache')
|
|
49
|
+
cache: require('./lib/interceptor/cache'),
|
|
50
|
+
decompress: require('./lib/interceptor/decompress')
|
|
50
51
|
}
|
|
51
52
|
|
|
52
53
|
module.exports.cacheStores = {
|
|
@@ -116,16 +117,14 @@ module.exports.setGlobalDispatcher = setGlobalDispatcher
|
|
|
116
117
|
module.exports.getGlobalDispatcher = getGlobalDispatcher
|
|
117
118
|
|
|
118
119
|
const fetchImpl = require('./lib/web/fetch').fetch
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
} catch (err) {
|
|
120
|
+
|
|
121
|
+
module.exports.fetch = function fetch (init, options = undefined) {
|
|
122
|
+
return fetchImpl(init, options).catch(err => {
|
|
123
123
|
if (err && typeof err === 'object') {
|
|
124
124
|
Error.captureStackTrace(err)
|
|
125
125
|
}
|
|
126
|
-
|
|
127
126
|
throw err
|
|
128
|
-
}
|
|
127
|
+
})
|
|
129
128
|
}
|
|
130
129
|
module.exports.Headers = require('./lib/web/fetch/headers').Headers
|
|
131
130
|
module.exports.Response = require('./lib/web/fetch/response').Response
|
|
@@ -140,8 +139,6 @@ module.exports.getGlobalOrigin = getGlobalOrigin
|
|
|
140
139
|
const { CacheStorage } = require('./lib/web/cache/cachestorage')
|
|
141
140
|
const { kConstruct } = require('./lib/core/symbols')
|
|
142
141
|
|
|
143
|
-
// Cache & CacheStorage are tightly coupled with fetch. Even if it may run
|
|
144
|
-
// in an older version of Node, it doesn't have any use without fetch.
|
|
145
142
|
module.exports.caches = new CacheStorage(kConstruct)
|
|
146
143
|
|
|
147
144
|
const { deleteCookie, getCookies, getSetCookies, setCookie, parseCookie } = require('./lib/web/cookies')
|
package/lib/api/api-request.js
CHANGED
|
@@ -118,14 +118,28 @@ class RequestHandler extends AsyncResource {
|
|
|
118
118
|
this.callback = null
|
|
119
119
|
this.res = res
|
|
120
120
|
if (callback !== null) {
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
121
|
+
try {
|
|
122
|
+
this.runInAsyncScope(callback, null, null, {
|
|
123
|
+
statusCode,
|
|
124
|
+
headers,
|
|
125
|
+
trailers: this.trailers,
|
|
126
|
+
opaque,
|
|
127
|
+
body: res,
|
|
128
|
+
context
|
|
129
|
+
})
|
|
130
|
+
} catch (err) {
|
|
131
|
+
// If the callback throws synchronously, we need to handle it
|
|
132
|
+
// Remove reference to res to allow res being garbage collected
|
|
133
|
+
this.res = null
|
|
134
|
+
|
|
135
|
+
// Destroy the response stream
|
|
136
|
+
util.destroy(res.on('error', noop), err)
|
|
137
|
+
|
|
138
|
+
// Use queueMicrotask to re-throw the error so it reaches uncaughtException
|
|
139
|
+
queueMicrotask(() => {
|
|
140
|
+
throw err
|
|
141
|
+
})
|
|
142
|
+
}
|
|
129
143
|
}
|
|
130
144
|
}
|
|
131
145
|
|
package/lib/api/readable.js
CHANGED
|
@@ -262,24 +262,26 @@ class BodyReadable extends Readable {
|
|
|
262
262
|
* @param {AbortSignal} [opts.signal] An AbortSignal to cancel the dump.
|
|
263
263
|
* @returns {Promise<null>}
|
|
264
264
|
*/
|
|
265
|
-
|
|
265
|
+
dump (opts) {
|
|
266
266
|
const signal = opts?.signal
|
|
267
267
|
|
|
268
268
|
if (signal != null && (typeof signal !== 'object' || !('aborted' in signal))) {
|
|
269
|
-
|
|
269
|
+
return Promise.reject(new InvalidArgumentError('signal must be an AbortSignal'))
|
|
270
270
|
}
|
|
271
271
|
|
|
272
272
|
const limit = opts?.limit && Number.isFinite(opts.limit)
|
|
273
273
|
? opts.limit
|
|
274
274
|
: 128 * 1024
|
|
275
275
|
|
|
276
|
-
signal?.
|
|
276
|
+
if (signal?.aborted) {
|
|
277
|
+
return Promise.reject(signal.reason ?? new AbortError())
|
|
278
|
+
}
|
|
277
279
|
|
|
278
280
|
if (this._readableState.closeEmitted) {
|
|
279
|
-
return null
|
|
281
|
+
return Promise.resolve(null)
|
|
280
282
|
}
|
|
281
283
|
|
|
282
|
-
return
|
|
284
|
+
return new Promise((resolve, reject) => {
|
|
283
285
|
if (
|
|
284
286
|
(this[kContentLength] && (this[kContentLength] > limit)) ||
|
|
285
287
|
this[kBytesRead] > limit
|
package/lib/core/errors.js
CHANGED
|
@@ -1,13 +1,23 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
+
const kUndiciError = Symbol.for('undici.error.UND_ERR')
|
|
3
4
|
class UndiciError extends Error {
|
|
4
5
|
constructor (message, options) {
|
|
5
6
|
super(message, options)
|
|
6
7
|
this.name = 'UndiciError'
|
|
7
8
|
this.code = 'UND_ERR'
|
|
8
9
|
}
|
|
10
|
+
|
|
11
|
+
static [Symbol.hasInstance] (instance) {
|
|
12
|
+
return instance && instance[kUndiciError] === true
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
get [kUndiciError] () {
|
|
16
|
+
return true
|
|
17
|
+
}
|
|
9
18
|
}
|
|
10
19
|
|
|
20
|
+
const kConnectTimeoutError = Symbol.for('undici.error.UND_ERR_CONNECT_TIMEOUT')
|
|
11
21
|
class ConnectTimeoutError extends UndiciError {
|
|
12
22
|
constructor (message) {
|
|
13
23
|
super(message)
|
|
@@ -15,8 +25,17 @@ class ConnectTimeoutError extends UndiciError {
|
|
|
15
25
|
this.message = message || 'Connect Timeout Error'
|
|
16
26
|
this.code = 'UND_ERR_CONNECT_TIMEOUT'
|
|
17
27
|
}
|
|
28
|
+
|
|
29
|
+
static [Symbol.hasInstance] (instance) {
|
|
30
|
+
return instance && instance[kConnectTimeoutError] === true
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
get [kConnectTimeoutError] () {
|
|
34
|
+
return true
|
|
35
|
+
}
|
|
18
36
|
}
|
|
19
37
|
|
|
38
|
+
const kHeadersTimeoutError = Symbol.for('undici.error.UND_ERR_HEADERS_TIMEOUT')
|
|
20
39
|
class HeadersTimeoutError extends UndiciError {
|
|
21
40
|
constructor (message) {
|
|
22
41
|
super(message)
|
|
@@ -24,8 +43,17 @@ class HeadersTimeoutError extends UndiciError {
|
|
|
24
43
|
this.message = message || 'Headers Timeout Error'
|
|
25
44
|
this.code = 'UND_ERR_HEADERS_TIMEOUT'
|
|
26
45
|
}
|
|
46
|
+
|
|
47
|
+
static [Symbol.hasInstance] (instance) {
|
|
48
|
+
return instance && instance[kHeadersTimeoutError] === true
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
get [kHeadersTimeoutError] () {
|
|
52
|
+
return true
|
|
53
|
+
}
|
|
27
54
|
}
|
|
28
55
|
|
|
56
|
+
const kHeadersOverflowError = Symbol.for('undici.error.UND_ERR_HEADERS_OVERFLOW')
|
|
29
57
|
class HeadersOverflowError extends UndiciError {
|
|
30
58
|
constructor (message) {
|
|
31
59
|
super(message)
|
|
@@ -33,8 +61,17 @@ class HeadersOverflowError extends UndiciError {
|
|
|
33
61
|
this.message = message || 'Headers Overflow Error'
|
|
34
62
|
this.code = 'UND_ERR_HEADERS_OVERFLOW'
|
|
35
63
|
}
|
|
64
|
+
|
|
65
|
+
static [Symbol.hasInstance] (instance) {
|
|
66
|
+
return instance && instance[kHeadersOverflowError] === true
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
get [kHeadersOverflowError] () {
|
|
70
|
+
return true
|
|
71
|
+
}
|
|
36
72
|
}
|
|
37
73
|
|
|
74
|
+
const kBodyTimeoutError = Symbol.for('undici.error.UND_ERR_BODY_TIMEOUT')
|
|
38
75
|
class BodyTimeoutError extends UndiciError {
|
|
39
76
|
constructor (message) {
|
|
40
77
|
super(message)
|
|
@@ -42,21 +79,17 @@ class BodyTimeoutError extends UndiciError {
|
|
|
42
79
|
this.message = message || 'Body Timeout Error'
|
|
43
80
|
this.code = 'UND_ERR_BODY_TIMEOUT'
|
|
44
81
|
}
|
|
45
|
-
}
|
|
46
82
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
this.body = body
|
|
54
|
-
this.status = statusCode
|
|
55
|
-
this.statusCode = statusCode
|
|
56
|
-
this.headers = headers
|
|
83
|
+
static [Symbol.hasInstance] (instance) {
|
|
84
|
+
return instance && instance[kBodyTimeoutError] === true
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
get [kBodyTimeoutError] () {
|
|
88
|
+
return true
|
|
57
89
|
}
|
|
58
90
|
}
|
|
59
91
|
|
|
92
|
+
const kInvalidArgumentError = Symbol.for('undici.error.UND_ERR_INVALID_ARG')
|
|
60
93
|
class InvalidArgumentError extends UndiciError {
|
|
61
94
|
constructor (message) {
|
|
62
95
|
super(message)
|
|
@@ -64,8 +97,17 @@ class InvalidArgumentError extends UndiciError {
|
|
|
64
97
|
this.message = message || 'Invalid Argument Error'
|
|
65
98
|
this.code = 'UND_ERR_INVALID_ARG'
|
|
66
99
|
}
|
|
100
|
+
|
|
101
|
+
static [Symbol.hasInstance] (instance) {
|
|
102
|
+
return instance && instance[kInvalidArgumentError] === true
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
get [kInvalidArgumentError] () {
|
|
106
|
+
return true
|
|
107
|
+
}
|
|
67
108
|
}
|
|
68
109
|
|
|
110
|
+
const kInvalidReturnValueError = Symbol.for('undici.error.UND_ERR_INVALID_RETURN_VALUE')
|
|
69
111
|
class InvalidReturnValueError extends UndiciError {
|
|
70
112
|
constructor (message) {
|
|
71
113
|
super(message)
|
|
@@ -73,16 +115,35 @@ class InvalidReturnValueError extends UndiciError {
|
|
|
73
115
|
this.message = message || 'Invalid Return Value Error'
|
|
74
116
|
this.code = 'UND_ERR_INVALID_RETURN_VALUE'
|
|
75
117
|
}
|
|
118
|
+
|
|
119
|
+
static [Symbol.hasInstance] (instance) {
|
|
120
|
+
return instance && instance[kInvalidReturnValueError] === true
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
get [kInvalidReturnValueError] () {
|
|
124
|
+
return true
|
|
125
|
+
}
|
|
76
126
|
}
|
|
77
127
|
|
|
128
|
+
const kAbortError = Symbol.for('undici.error.UND_ERR_ABORT')
|
|
78
129
|
class AbortError extends UndiciError {
|
|
79
130
|
constructor (message) {
|
|
80
131
|
super(message)
|
|
81
132
|
this.name = 'AbortError'
|
|
82
133
|
this.message = message || 'The operation was aborted'
|
|
134
|
+
this.code = 'UND_ERR_ABORT'
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
static [Symbol.hasInstance] (instance) {
|
|
138
|
+
return instance && instance[kAbortError] === true
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
get [kAbortError] () {
|
|
142
|
+
return true
|
|
83
143
|
}
|
|
84
144
|
}
|
|
85
145
|
|
|
146
|
+
const kRequestAbortedError = Symbol.for('undici.error.UND_ERR_ABORTED')
|
|
86
147
|
class RequestAbortedError extends AbortError {
|
|
87
148
|
constructor (message) {
|
|
88
149
|
super(message)
|
|
@@ -90,8 +151,17 @@ class RequestAbortedError extends AbortError {
|
|
|
90
151
|
this.message = message || 'Request aborted'
|
|
91
152
|
this.code = 'UND_ERR_ABORTED'
|
|
92
153
|
}
|
|
154
|
+
|
|
155
|
+
static [Symbol.hasInstance] (instance) {
|
|
156
|
+
return instance && instance[kRequestAbortedError] === true
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
get [kRequestAbortedError] () {
|
|
160
|
+
return true
|
|
161
|
+
}
|
|
93
162
|
}
|
|
94
163
|
|
|
164
|
+
const kInformationalError = Symbol.for('undici.error.UND_ERR_INFO')
|
|
95
165
|
class InformationalError extends UndiciError {
|
|
96
166
|
constructor (message) {
|
|
97
167
|
super(message)
|
|
@@ -99,8 +169,17 @@ class InformationalError extends UndiciError {
|
|
|
99
169
|
this.message = message || 'Request information'
|
|
100
170
|
this.code = 'UND_ERR_INFO'
|
|
101
171
|
}
|
|
172
|
+
|
|
173
|
+
static [Symbol.hasInstance] (instance) {
|
|
174
|
+
return instance && instance[kInformationalError] === true
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
get [kInformationalError] () {
|
|
178
|
+
return true
|
|
179
|
+
}
|
|
102
180
|
}
|
|
103
181
|
|
|
182
|
+
const kRequestContentLengthMismatchError = Symbol.for('undici.error.UND_ERR_REQ_CONTENT_LENGTH_MISMATCH')
|
|
104
183
|
class RequestContentLengthMismatchError extends UndiciError {
|
|
105
184
|
constructor (message) {
|
|
106
185
|
super(message)
|
|
@@ -108,8 +187,17 @@ class RequestContentLengthMismatchError extends UndiciError {
|
|
|
108
187
|
this.message = message || 'Request body length does not match content-length header'
|
|
109
188
|
this.code = 'UND_ERR_REQ_CONTENT_LENGTH_MISMATCH'
|
|
110
189
|
}
|
|
190
|
+
|
|
191
|
+
static [Symbol.hasInstance] (instance) {
|
|
192
|
+
return instance && instance[kRequestContentLengthMismatchError] === true
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
get [kRequestContentLengthMismatchError] () {
|
|
196
|
+
return true
|
|
197
|
+
}
|
|
111
198
|
}
|
|
112
199
|
|
|
200
|
+
const kResponseContentLengthMismatchError = Symbol.for('undici.error.UND_ERR_RES_CONTENT_LENGTH_MISMATCH')
|
|
113
201
|
class ResponseContentLengthMismatchError extends UndiciError {
|
|
114
202
|
constructor (message) {
|
|
115
203
|
super(message)
|
|
@@ -117,8 +205,17 @@ class ResponseContentLengthMismatchError extends UndiciError {
|
|
|
117
205
|
this.message = message || 'Response body length does not match content-length header'
|
|
118
206
|
this.code = 'UND_ERR_RES_CONTENT_LENGTH_MISMATCH'
|
|
119
207
|
}
|
|
208
|
+
|
|
209
|
+
static [Symbol.hasInstance] (instance) {
|
|
210
|
+
return instance && instance[kResponseContentLengthMismatchError] === true
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
get [kResponseContentLengthMismatchError] () {
|
|
214
|
+
return true
|
|
215
|
+
}
|
|
120
216
|
}
|
|
121
217
|
|
|
218
|
+
const kClientDestroyedError = Symbol.for('undici.error.UND_ERR_DESTROYED')
|
|
122
219
|
class ClientDestroyedError extends UndiciError {
|
|
123
220
|
constructor (message) {
|
|
124
221
|
super(message)
|
|
@@ -126,8 +223,17 @@ class ClientDestroyedError extends UndiciError {
|
|
|
126
223
|
this.message = message || 'The client is destroyed'
|
|
127
224
|
this.code = 'UND_ERR_DESTROYED'
|
|
128
225
|
}
|
|
226
|
+
|
|
227
|
+
static [Symbol.hasInstance] (instance) {
|
|
228
|
+
return instance && instance[kClientDestroyedError] === true
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
get [kClientDestroyedError] () {
|
|
232
|
+
return true
|
|
233
|
+
}
|
|
129
234
|
}
|
|
130
235
|
|
|
236
|
+
const kClientClosedError = Symbol.for('undici.error.UND_ERR_CLOSED')
|
|
131
237
|
class ClientClosedError extends UndiciError {
|
|
132
238
|
constructor (message) {
|
|
133
239
|
super(message)
|
|
@@ -135,8 +241,17 @@ class ClientClosedError extends UndiciError {
|
|
|
135
241
|
this.message = message || 'The client is closed'
|
|
136
242
|
this.code = 'UND_ERR_CLOSED'
|
|
137
243
|
}
|
|
244
|
+
|
|
245
|
+
static [Symbol.hasInstance] (instance) {
|
|
246
|
+
return instance && instance[kClientClosedError] === true
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
get [kClientClosedError] () {
|
|
250
|
+
return true
|
|
251
|
+
}
|
|
138
252
|
}
|
|
139
253
|
|
|
254
|
+
const kSocketError = Symbol.for('undici.error.UND_ERR_SOCKET')
|
|
140
255
|
class SocketError extends UndiciError {
|
|
141
256
|
constructor (message, socket) {
|
|
142
257
|
super(message)
|
|
@@ -145,8 +260,17 @@ class SocketError extends UndiciError {
|
|
|
145
260
|
this.code = 'UND_ERR_SOCKET'
|
|
146
261
|
this.socket = socket
|
|
147
262
|
}
|
|
263
|
+
|
|
264
|
+
static [Symbol.hasInstance] (instance) {
|
|
265
|
+
return instance && instance[kSocketError] === true
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
get [kSocketError] () {
|
|
269
|
+
return true
|
|
270
|
+
}
|
|
148
271
|
}
|
|
149
272
|
|
|
273
|
+
const kNotSupportedError = Symbol.for('undici.error.UND_ERR_NOT_SUPPORTED')
|
|
150
274
|
class NotSupportedError extends UndiciError {
|
|
151
275
|
constructor (message) {
|
|
152
276
|
super(message)
|
|
@@ -154,8 +278,17 @@ class NotSupportedError extends UndiciError {
|
|
|
154
278
|
this.message = message || 'Not supported error'
|
|
155
279
|
this.code = 'UND_ERR_NOT_SUPPORTED'
|
|
156
280
|
}
|
|
281
|
+
|
|
282
|
+
static [Symbol.hasInstance] (instance) {
|
|
283
|
+
return instance && instance[kNotSupportedError] === true
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
get [kNotSupportedError] () {
|
|
287
|
+
return true
|
|
288
|
+
}
|
|
157
289
|
}
|
|
158
290
|
|
|
291
|
+
const kBalancedPoolMissingUpstreamError = Symbol.for('undici.error.UND_ERR_BPL_MISSING_UPSTREAM')
|
|
159
292
|
class BalancedPoolMissingUpstreamError extends UndiciError {
|
|
160
293
|
constructor (message) {
|
|
161
294
|
super(message)
|
|
@@ -163,8 +296,17 @@ class BalancedPoolMissingUpstreamError extends UndiciError {
|
|
|
163
296
|
this.message = message || 'No upstream has been added to the BalancedPool'
|
|
164
297
|
this.code = 'UND_ERR_BPL_MISSING_UPSTREAM'
|
|
165
298
|
}
|
|
299
|
+
|
|
300
|
+
static [Symbol.hasInstance] (instance) {
|
|
301
|
+
return instance && instance[kBalancedPoolMissingUpstreamError] === true
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
get [kBalancedPoolMissingUpstreamError] () {
|
|
305
|
+
return true
|
|
306
|
+
}
|
|
166
307
|
}
|
|
167
308
|
|
|
309
|
+
const kHTTPParserError = Symbol.for('undici.error.UND_ERR_HTTP_PARSER')
|
|
168
310
|
class HTTPParserError extends Error {
|
|
169
311
|
constructor (message, code, data) {
|
|
170
312
|
super(message)
|
|
@@ -172,8 +314,17 @@ class HTTPParserError extends Error {
|
|
|
172
314
|
this.code = code ? `HPE_${code}` : undefined
|
|
173
315
|
this.data = data ? data.toString() : undefined
|
|
174
316
|
}
|
|
317
|
+
|
|
318
|
+
static [Symbol.hasInstance] (instance) {
|
|
319
|
+
return instance && instance[kHTTPParserError] === true
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
get [kHTTPParserError] () {
|
|
323
|
+
return true
|
|
324
|
+
}
|
|
175
325
|
}
|
|
176
326
|
|
|
327
|
+
const kResponseExceededMaxSizeError = Symbol.for('undici.error.UND_ERR_RES_EXCEEDED_MAX_SIZE')
|
|
177
328
|
class ResponseExceededMaxSizeError extends UndiciError {
|
|
178
329
|
constructor (message) {
|
|
179
330
|
super(message)
|
|
@@ -181,8 +332,17 @@ class ResponseExceededMaxSizeError extends UndiciError {
|
|
|
181
332
|
this.message = message || 'Response content exceeded max size'
|
|
182
333
|
this.code = 'UND_ERR_RES_EXCEEDED_MAX_SIZE'
|
|
183
334
|
}
|
|
335
|
+
|
|
336
|
+
static [Symbol.hasInstance] (instance) {
|
|
337
|
+
return instance && instance[kResponseExceededMaxSizeError] === true
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
get [kResponseExceededMaxSizeError] () {
|
|
341
|
+
return true
|
|
342
|
+
}
|
|
184
343
|
}
|
|
185
344
|
|
|
345
|
+
const kRequestRetryError = Symbol.for('undici.error.UND_ERR_REQ_RETRY')
|
|
186
346
|
class RequestRetryError extends UndiciError {
|
|
187
347
|
constructor (message, code, { headers, data }) {
|
|
188
348
|
super(message)
|
|
@@ -193,8 +353,17 @@ class RequestRetryError extends UndiciError {
|
|
|
193
353
|
this.data = data
|
|
194
354
|
this.headers = headers
|
|
195
355
|
}
|
|
356
|
+
|
|
357
|
+
static [Symbol.hasInstance] (instance) {
|
|
358
|
+
return instance && instance[kRequestRetryError] === true
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
get [kRequestRetryError] () {
|
|
362
|
+
return true
|
|
363
|
+
}
|
|
196
364
|
}
|
|
197
365
|
|
|
366
|
+
const kResponseError = Symbol.for('undici.error.UND_ERR_RESPONSE')
|
|
198
367
|
class ResponseError extends UndiciError {
|
|
199
368
|
constructor (message, code, { headers, body }) {
|
|
200
369
|
super(message)
|
|
@@ -205,8 +374,17 @@ class ResponseError extends UndiciError {
|
|
|
205
374
|
this.body = body
|
|
206
375
|
this.headers = headers
|
|
207
376
|
}
|
|
377
|
+
|
|
378
|
+
static [Symbol.hasInstance] (instance) {
|
|
379
|
+
return instance && instance[kResponseError] === true
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
get [kResponseError] () {
|
|
383
|
+
return true
|
|
384
|
+
}
|
|
208
385
|
}
|
|
209
386
|
|
|
387
|
+
const kSecureProxyConnectionError = Symbol.for('undici.error.UND_ERR_PRX_TLS')
|
|
210
388
|
class SecureProxyConnectionError extends UndiciError {
|
|
211
389
|
constructor (cause, message, options = {}) {
|
|
212
390
|
super(message, { cause, ...options })
|
|
@@ -215,6 +393,32 @@ class SecureProxyConnectionError extends UndiciError {
|
|
|
215
393
|
this.code = 'UND_ERR_PRX_TLS'
|
|
216
394
|
this.cause = cause
|
|
217
395
|
}
|
|
396
|
+
|
|
397
|
+
static [Symbol.hasInstance] (instance) {
|
|
398
|
+
return instance && instance[kSecureProxyConnectionError] === true
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
get [kSecureProxyConnectionError] () {
|
|
402
|
+
return true
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
const kMaxOriginsReachedError = Symbol.for('undici.error.UND_ERR_MAX_ORIGINS_REACHED')
|
|
407
|
+
class MaxOriginsReachedError extends UndiciError {
|
|
408
|
+
constructor (message) {
|
|
409
|
+
super(message)
|
|
410
|
+
this.name = 'MaxOriginsReachedError'
|
|
411
|
+
this.message = message || 'Maximum allowed origins reached'
|
|
412
|
+
this.code = 'UND_ERR_MAX_ORIGINS_REACHED'
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
static [Symbol.hasInstance] (instance) {
|
|
416
|
+
return instance && instance[kMaxOriginsReachedError] === true
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
get [kMaxOriginsReachedError] () {
|
|
420
|
+
return true
|
|
421
|
+
}
|
|
218
422
|
}
|
|
219
423
|
|
|
220
424
|
module.exports = {
|
|
@@ -226,7 +430,6 @@ module.exports = {
|
|
|
226
430
|
BodyTimeoutError,
|
|
227
431
|
RequestContentLengthMismatchError,
|
|
228
432
|
ConnectTimeoutError,
|
|
229
|
-
ResponseStatusCodeError,
|
|
230
433
|
InvalidArgumentError,
|
|
231
434
|
InvalidReturnValueError,
|
|
232
435
|
RequestAbortedError,
|
|
@@ -240,5 +443,6 @@ module.exports = {
|
|
|
240
443
|
ResponseExceededMaxSizeError,
|
|
241
444
|
RequestRetryError,
|
|
242
445
|
ResponseError,
|
|
243
|
-
SecureProxyConnectionError
|
|
446
|
+
SecureProxyConnectionError,
|
|
447
|
+
MaxOriginsReachedError
|
|
244
448
|
}
|
package/lib/core/request.js
CHANGED
|
@@ -17,7 +17,8 @@ const {
|
|
|
17
17
|
serializePathWithQuery,
|
|
18
18
|
assertRequestHandler,
|
|
19
19
|
getServerName,
|
|
20
|
-
normalizedMethodRecords
|
|
20
|
+
normalizedMethodRecords,
|
|
21
|
+
getProtocolFromUrlString
|
|
21
22
|
} = require('./util')
|
|
22
23
|
const { channels } = require('./diagnostics.js')
|
|
23
24
|
const { headerNameLowerCasedRecord } = require('./constants')
|
|
@@ -141,8 +142,11 @@ class Request {
|
|
|
141
142
|
|
|
142
143
|
this.path = query ? serializePathWithQuery(path, query) : path
|
|
143
144
|
|
|
145
|
+
// TODO: shall we maybe standardize it to an URL object?
|
|
144
146
|
this.origin = origin
|
|
145
147
|
|
|
148
|
+
this.protocol = getProtocolFromUrlString(origin)
|
|
149
|
+
|
|
146
150
|
this.idempotent = idempotent == null
|
|
147
151
|
? method === 'HEAD' || method === 'GET'
|
|
148
152
|
: idempotent
|