undici 6.6.2 → 6.7.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/README.md +49 -27
- package/docs/{api → docs/api}/DiagnosticsChannel.md +2 -2
- package/docs/{api → docs/api}/Dispatcher.md +39 -3
- package/docs/docs/api/Fetch.md +57 -0
- package/docs/{api → docs/api}/ProxyAgent.md +5 -1
- package/docs/docs/api/RetryAgent.md +45 -0
- package/docs/{api → docs/api}/RetryHandler.md +1 -1
- package/docs/{api → docs/api}/api-lifecycle.md +33 -4
- package/docs/{best-practices → docs/best-practices}/proxy.md +6 -6
- package/index-fetch.js +9 -8
- package/index.js +31 -25
- package/lib/api/api-request.js +1 -1
- package/lib/api/readable.js +12 -9
- package/lib/api/util.js +8 -6
- package/lib/core/request.js +72 -135
- package/lib/core/symbols.js +6 -5
- package/lib/core/tree.js +46 -26
- package/lib/core/util.js +41 -20
- package/lib/{agent.js → dispatcher/agent.js} +4 -4
- package/lib/{balanced-pool.js → dispatcher/balanced-pool.js} +3 -3
- package/lib/dispatcher/client-h1.js +1352 -0
- package/lib/dispatcher/client-h2.js +639 -0
- package/lib/dispatcher/client.js +611 -0
- package/lib/{dispatcher-base.js → dispatcher/dispatcher-base.js} +2 -2
- package/lib/{pool-base.js → dispatcher/pool-base.js} +3 -3
- package/lib/{pool-stats.js → dispatcher/pool-stats.js} +1 -1
- package/lib/{pool.js → dispatcher/pool.js} +4 -4
- package/lib/{proxy-agent.js → dispatcher/proxy-agent.js} +29 -35
- package/lib/dispatcher/retry-agent.js +35 -0
- package/lib/global.js +1 -1
- package/lib/handler/{RetryHandler.js → retry-handler.js} +2 -2
- package/lib/interceptor/{redirectInterceptor.js → redirect-interceptor.js} +1 -1
- package/lib/mock/mock-agent.js +2 -2
- package/lib/mock/mock-client.js +1 -1
- package/lib/mock/mock-interceptor.js +2 -2
- package/lib/mock/mock-pool.js +1 -1
- package/lib/mock/mock-utils.js +6 -4
- package/lib/{cache → web/cache}/cache.js +2 -4
- package/lib/{cache → web/cache}/cachestorage.js +1 -1
- package/lib/web/cache/symbols.js +5 -0
- package/lib/{cache → web/cache}/util.js +5 -9
- package/lib/{cookies → web/cookies}/parse.js +1 -1
- package/lib/{cookies → web/cookies}/util.js +76 -60
- package/lib/{eventsource → web/eventsource}/eventsource.js +2 -6
- package/lib/{fetch → web/fetch}/body.js +56 -175
- package/lib/{fetch/dataURL.js → web/fetch/data-url.js} +5 -2
- package/lib/{compat → web/fetch}/dispatcher-weakref.js +1 -1
- package/lib/{fetch → web/fetch}/file.js +7 -8
- package/lib/web/fetch/formdata-parser.js +488 -0
- package/lib/{fetch → web/fetch}/formdata.js +7 -68
- package/lib/{fetch → web/fetch}/headers.js +99 -71
- package/lib/{fetch → web/fetch}/index.js +33 -25
- package/lib/{fetch → web/fetch}/request.js +15 -7
- package/lib/{fetch → web/fetch}/response.js +3 -3
- package/lib/{fetch → web/fetch}/symbols.js +2 -1
- package/lib/{fetch → web/fetch}/util.js +171 -48
- package/lib/{fetch → web/fetch}/webidl.js +46 -16
- package/lib/{fileapi → web/fileapi}/filereader.js +1 -1
- package/lib/{fileapi → web/fileapi}/util.js +1 -1
- package/lib/{websocket → web/websocket}/connection.js +20 -10
- package/lib/{websocket → web/websocket}/constants.js +7 -0
- package/lib/{websocket → web/websocket}/events.js +1 -1
- package/lib/{websocket → web/websocket}/frame.js +1 -0
- package/lib/{websocket → web/websocket}/receiver.js +9 -16
- package/lib/{websocket → web/websocket}/util.js +37 -23
- package/lib/{websocket → web/websocket}/websocket.js +21 -9
- package/package.json +26 -54
- package/types/dispatcher.d.ts +1 -1
- package/types/fetch.d.ts +20 -21
- package/types/index.d.ts +2 -1
- package/types/retry-agent.d.ts +11 -0
- package/types/webidl.d.ts +6 -1
- package/docs/api/Fetch.md +0 -27
- package/docs/assets/lifecycle-diagram.png +0 -0
- package/lib/cache/symbols.js +0 -5
- package/lib/client.js +0 -2295
- package/lib/llhttp/llhttp.wasm +0 -0
- package/lib/llhttp/llhttp_simd.wasm +0 -0
- /package/docs/{api → docs/api}/Agent.md +0 -0
- /package/docs/{api → docs/api}/BalancedPool.md +0 -0
- /package/docs/{api → docs/api}/CacheStorage.md +0 -0
- /package/docs/{api → docs/api}/Client.md +0 -0
- /package/docs/{api → docs/api}/Connector.md +0 -0
- /package/docs/{api → docs/api}/ContentType.md +0 -0
- /package/docs/{api → docs/api}/Cookies.md +0 -0
- /package/docs/{api → docs/api}/Debug.md +0 -0
- /package/docs/{api → docs/api}/DispatchInterceptor.md +0 -0
- /package/docs/{api → docs/api}/Errors.md +0 -0
- /package/docs/{api → docs/api}/EventSource.md +0 -0
- /package/docs/{api → docs/api}/MockAgent.md +0 -0
- /package/docs/{api → docs/api}/MockClient.md +0 -0
- /package/docs/{api → docs/api}/MockErrors.md +0 -0
- /package/docs/{api → docs/api}/MockPool.md +0 -0
- /package/docs/{api → docs/api}/Pool.md +0 -0
- /package/docs/{api → docs/api}/PoolStats.md +0 -0
- /package/docs/{api → docs/api}/RedirectHandler.md +0 -0
- /package/docs/{api → docs/api}/Util.md +0 -0
- /package/docs/{api → docs/api}/WebSocket.md +0 -0
- /package/docs/{best-practices → docs/best-practices}/client-certificate.md +0 -0
- /package/docs/{best-practices → docs/best-practices}/mocking-request.md +0 -0
- /package/docs/{best-practices → docs/best-practices}/writing-tests.md +0 -0
- /package/lib/{dispatcher.js → dispatcher/dispatcher.js} +0 -0
- /package/lib/{node → dispatcher}/fixed-queue.js +0 -0
- /package/lib/handler/{DecoratorHandler.js → decorator-handler.js} +0 -0
- /package/lib/handler/{RedirectHandler.js → redirect-handler.js} +0 -0
- /package/lib/{timers.js → util/timers.js} +0 -0
- /package/lib/{cookies → web/cookies}/constants.js +0 -0
- /package/lib/{cookies → web/cookies}/index.js +0 -0
- /package/lib/{eventsource → web/eventsource}/eventsource-stream.js +0 -0
- /package/lib/{eventsource → web/eventsource}/util.js +0 -0
- /package/lib/{fetch → web/fetch}/LICENSE +0 -0
- /package/lib/{fetch → web/fetch}/constants.js +0 -0
- /package/lib/{fetch → web/fetch}/global.js +0 -0
- /package/lib/{fileapi → web/fileapi}/encoding.js +0 -0
- /package/lib/{fileapi → web/fileapi}/progressevent.js +0 -0
- /package/lib/{fileapi → web/fileapi}/symbols.js +0 -0
- /package/lib/{websocket → web/websocket}/symbols.js +0 -0
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
const { Writable } = require('node:stream')
|
|
4
|
-
const { parserStates, opcodes, states, emptyBuffer } = require('./constants')
|
|
4
|
+
const { parserStates, opcodes, states, emptyBuffer, sentCloseFrameState } = require('./constants')
|
|
5
5
|
const { kReadyState, kSentClose, kResponse, kReceivedClose } = require('./symbols')
|
|
6
|
-
const { channels } = require('
|
|
6
|
+
const { channels } = require('../../core/diagnostics')
|
|
7
7
|
const { isValidStatusCode, failWebsocketConnection, websocketMessageReceived } = require('./util')
|
|
8
8
|
const { WebsocketFrameSend } = require('./frame')
|
|
9
9
|
|
|
@@ -12,6 +12,8 @@ const { WebsocketFrameSend } = require('./frame')
|
|
|
12
12
|
// Copyright (c) 2013 Arnout Kazemier and contributors
|
|
13
13
|
// Copyright (c) 2016 Luigi Pinca and contributors
|
|
14
14
|
|
|
15
|
+
const textDecoder = new TextDecoder('utf-8', { fatal: true })
|
|
16
|
+
|
|
15
17
|
class ByteParser extends Writable {
|
|
16
18
|
#buffers = []
|
|
17
19
|
#byteOffset = 0
|
|
@@ -100,9 +102,9 @@ class ByteParser extends Writable {
|
|
|
100
102
|
|
|
101
103
|
const body = this.consume(payloadLength)
|
|
102
104
|
|
|
103
|
-
this.#info.closeInfo = this.parseCloseBody(
|
|
105
|
+
this.#info.closeInfo = this.parseCloseBody(body)
|
|
104
106
|
|
|
105
|
-
if (
|
|
107
|
+
if (this.ws[kSentClose] !== sentCloseFrameState.SENT) {
|
|
106
108
|
// If an endpoint receives a Close frame and did not previously send a
|
|
107
109
|
// Close frame, the endpoint MUST send a Close frame in response. (When
|
|
108
110
|
// sending a Close frame in response, the endpoint typically echos the
|
|
@@ -118,7 +120,7 @@ class ByteParser extends Writable {
|
|
|
118
120
|
closeFrame.createFrame(opcodes.CLOSE),
|
|
119
121
|
(err) => {
|
|
120
122
|
if (!err) {
|
|
121
|
-
this.ws[kSentClose] =
|
|
123
|
+
this.ws[kSentClose] = sentCloseFrameState.SENT
|
|
122
124
|
}
|
|
123
125
|
}
|
|
124
126
|
)
|
|
@@ -288,7 +290,7 @@ class ByteParser extends Writable {
|
|
|
288
290
|
return buffer
|
|
289
291
|
}
|
|
290
292
|
|
|
291
|
-
parseCloseBody (
|
|
293
|
+
parseCloseBody (data) {
|
|
292
294
|
// https://datatracker.ietf.org/doc/html/rfc6455#section-7.1.5
|
|
293
295
|
/** @type {number|undefined} */
|
|
294
296
|
let code
|
|
@@ -300,14 +302,6 @@ class ByteParser extends Writable {
|
|
|
300
302
|
code = data.readUInt16BE(0)
|
|
301
303
|
}
|
|
302
304
|
|
|
303
|
-
if (onlyCode) {
|
|
304
|
-
if (!isValidStatusCode(code)) {
|
|
305
|
-
return null
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
return { code }
|
|
309
|
-
}
|
|
310
|
-
|
|
311
305
|
// https://datatracker.ietf.org/doc/html/rfc6455#section-7.1.6
|
|
312
306
|
/** @type {Buffer} */
|
|
313
307
|
let reason = data.subarray(2)
|
|
@@ -322,8 +316,7 @@ class ByteParser extends Writable {
|
|
|
322
316
|
}
|
|
323
317
|
|
|
324
318
|
try {
|
|
325
|
-
|
|
326
|
-
reason = new TextDecoder('utf-8', { fatal: true }).decode(reason)
|
|
319
|
+
reason = textDecoder.decode(reason)
|
|
327
320
|
} catch {
|
|
328
321
|
return null
|
|
329
322
|
}
|
|
@@ -8,6 +8,17 @@ const { MessageEvent, ErrorEvent } = require('./events')
|
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* @param {import('./websocket').WebSocket} ws
|
|
11
|
+
* @returns {boolean}
|
|
12
|
+
*/
|
|
13
|
+
function isConnecting (ws) {
|
|
14
|
+
// If the WebSocket connection is not yet established, and the connection
|
|
15
|
+
// is not yet closed, then the WebSocket connection is in the CONNECTING state.
|
|
16
|
+
return ws[kReadyState] === states.CONNECTING
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @param {import('./websocket').WebSocket} ws
|
|
21
|
+
* @returns {boolean}
|
|
11
22
|
*/
|
|
12
23
|
function isEstablished (ws) {
|
|
13
24
|
// If the server's response is validated as provided for above, it is
|
|
@@ -18,6 +29,7 @@ function isEstablished (ws) {
|
|
|
18
29
|
|
|
19
30
|
/**
|
|
20
31
|
* @param {import('./websocket').WebSocket} ws
|
|
32
|
+
* @returns {boolean}
|
|
21
33
|
*/
|
|
22
34
|
function isClosing (ws) {
|
|
23
35
|
// Upon either sending or receiving a Close control frame, it is said
|
|
@@ -28,6 +40,7 @@ function isClosing (ws) {
|
|
|
28
40
|
|
|
29
41
|
/**
|
|
30
42
|
* @param {import('./websocket').WebSocket} ws
|
|
43
|
+
* @returns {boolean}
|
|
31
44
|
*/
|
|
32
45
|
function isClosed (ws) {
|
|
33
46
|
return ws[kReadyState] === states.CLOSED
|
|
@@ -55,6 +68,8 @@ function fireEvent (e, target, eventConstructor = Event, eventInitDict = {}) {
|
|
|
55
68
|
target.dispatchEvent(event)
|
|
56
69
|
}
|
|
57
70
|
|
|
71
|
+
const textDecoder = new TextDecoder('utf-8', { fatal: true })
|
|
72
|
+
|
|
58
73
|
/**
|
|
59
74
|
* @see https://websockets.spec.whatwg.org/#feedback-from-the-protocol
|
|
60
75
|
* @param {import('./websocket').WebSocket} ws
|
|
@@ -74,7 +89,7 @@ function websocketMessageReceived (ws, type, data) {
|
|
|
74
89
|
// -> type indicates that the data is Text
|
|
75
90
|
// a new DOMString containing data
|
|
76
91
|
try {
|
|
77
|
-
dataForEvent =
|
|
92
|
+
dataForEvent = textDecoder.decode(data)
|
|
78
93
|
} catch {
|
|
79
94
|
failWebsocketConnection(ws, 'Received invalid UTF-8 in text frame.')
|
|
80
95
|
return
|
|
@@ -119,31 +134,29 @@ function isValidSubprotocol (protocol) {
|
|
|
119
134
|
return false
|
|
120
135
|
}
|
|
121
136
|
|
|
122
|
-
for (
|
|
123
|
-
const code =
|
|
137
|
+
for (let i = 0; i < protocol.length; ++i) {
|
|
138
|
+
const code = protocol.charCodeAt(i)
|
|
124
139
|
|
|
125
140
|
if (
|
|
126
|
-
code < 0x21 ||
|
|
141
|
+
code < 0x21 || // CTL, contains SP (0x20) and HT (0x09)
|
|
127
142
|
code > 0x7E ||
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
code === 32 || // SP
|
|
146
|
-
code === 9 // HT
|
|
143
|
+
code === 0x22 || // "
|
|
144
|
+
code === 0x28 || // (
|
|
145
|
+
code === 0x29 || // )
|
|
146
|
+
code === 0x2C || // ,
|
|
147
|
+
code === 0x2F || // /
|
|
148
|
+
code === 0x3A || // :
|
|
149
|
+
code === 0x3B || // ;
|
|
150
|
+
code === 0x3C || // <
|
|
151
|
+
code === 0x3D || // =
|
|
152
|
+
code === 0x3E || // >
|
|
153
|
+
code === 0x3F || // ?
|
|
154
|
+
code === 0x40 || // @
|
|
155
|
+
code === 0x5B || // [
|
|
156
|
+
code === 0x5C || // \
|
|
157
|
+
code === 0x5D || // ]
|
|
158
|
+
code === 0x7B || // {
|
|
159
|
+
code === 0x7D // }
|
|
147
160
|
) {
|
|
148
161
|
return false
|
|
149
162
|
}
|
|
@@ -190,6 +203,7 @@ function failWebsocketConnection (ws, reason) {
|
|
|
190
203
|
}
|
|
191
204
|
|
|
192
205
|
module.exports = {
|
|
206
|
+
isConnecting,
|
|
193
207
|
isEstablished,
|
|
194
208
|
isClosing,
|
|
195
209
|
isClosed,
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
const { webidl } = require('../fetch/webidl')
|
|
4
|
-
const { URLSerializer } = require('../fetch/
|
|
4
|
+
const { URLSerializer } = require('../fetch/data-url')
|
|
5
5
|
const { getGlobalOrigin } = require('../fetch/global')
|
|
6
|
-
const { staticPropertyDescriptors, states, opcodes, emptyBuffer } = require('./constants')
|
|
6
|
+
const { staticPropertyDescriptors, states, sentCloseFrameState, opcodes, emptyBuffer } = require('./constants')
|
|
7
7
|
const {
|
|
8
8
|
kWebSocketURL,
|
|
9
9
|
kReadyState,
|
|
@@ -13,12 +13,20 @@ const {
|
|
|
13
13
|
kSentClose,
|
|
14
14
|
kByteParser
|
|
15
15
|
} = require('./symbols')
|
|
16
|
-
const {
|
|
16
|
+
const {
|
|
17
|
+
isConnecting,
|
|
18
|
+
isEstablished,
|
|
19
|
+
isClosed,
|
|
20
|
+
isClosing,
|
|
21
|
+
isValidSubprotocol,
|
|
22
|
+
failWebsocketConnection,
|
|
23
|
+
fireEvent
|
|
24
|
+
} = require('./util')
|
|
17
25
|
const { establishWebSocketConnection } = require('./connection')
|
|
18
26
|
const { WebsocketFrameSend } = require('./frame')
|
|
19
27
|
const { ByteParser } = require('./receiver')
|
|
20
|
-
const { kEnumerableProperty, isBlobLike } = require('
|
|
21
|
-
const { getGlobalDispatcher } = require('
|
|
28
|
+
const { kEnumerableProperty, isBlobLike } = require('../../core/util')
|
|
29
|
+
const { getGlobalDispatcher } = require('../../global')
|
|
22
30
|
const { types } = require('node:util')
|
|
23
31
|
|
|
24
32
|
let experimentalWarned = false
|
|
@@ -132,6 +140,8 @@ class WebSocket extends EventTarget {
|
|
|
132
140
|
// be CONNECTING (0).
|
|
133
141
|
this[kReadyState] = WebSocket.CONNECTING
|
|
134
142
|
|
|
143
|
+
this[kSentClose] = sentCloseFrameState.NOT_SENT
|
|
144
|
+
|
|
135
145
|
// The extensions attribute must initially return the empty string.
|
|
136
146
|
|
|
137
147
|
// The protocol attribute must initially return the empty string.
|
|
@@ -184,7 +194,7 @@ class WebSocket extends EventTarget {
|
|
|
184
194
|
}
|
|
185
195
|
|
|
186
196
|
// 3. Run the first matching steps from the following list:
|
|
187
|
-
if (this
|
|
197
|
+
if (isClosing(this) || isClosed(this)) {
|
|
188
198
|
// If this's ready state is CLOSING (2) or CLOSED (3)
|
|
189
199
|
// Do nothing.
|
|
190
200
|
} else if (!isEstablished(this)) {
|
|
@@ -193,7 +203,7 @@ class WebSocket extends EventTarget {
|
|
|
193
203
|
// to CLOSING (2).
|
|
194
204
|
failWebsocketConnection(this, 'Connection was closed before it was established.')
|
|
195
205
|
this[kReadyState] = WebSocket.CLOSING
|
|
196
|
-
} else if (
|
|
206
|
+
} else if (this[kSentClose] === sentCloseFrameState.NOT_SENT) {
|
|
197
207
|
// If the WebSocket closing handshake has not yet been started
|
|
198
208
|
// Start the WebSocket closing handshake and set this's ready
|
|
199
209
|
// state to CLOSING (2).
|
|
@@ -204,6 +214,8 @@ class WebSocket extends EventTarget {
|
|
|
204
214
|
// - If reason is also present, then reasonBytes must be
|
|
205
215
|
// provided in the Close message after the status code.
|
|
206
216
|
|
|
217
|
+
this[kSentClose] = sentCloseFrameState.PROCESSING
|
|
218
|
+
|
|
207
219
|
const frame = new WebsocketFrameSend()
|
|
208
220
|
|
|
209
221
|
// If neither code nor reason is present, the WebSocket Close
|
|
@@ -230,7 +242,7 @@ class WebSocket extends EventTarget {
|
|
|
230
242
|
|
|
231
243
|
socket.write(frame.createFrame(opcodes.CLOSE), (err) => {
|
|
232
244
|
if (!err) {
|
|
233
|
-
this[kSentClose] =
|
|
245
|
+
this[kSentClose] = sentCloseFrameState.SENT
|
|
234
246
|
}
|
|
235
247
|
})
|
|
236
248
|
|
|
@@ -258,7 +270,7 @@ class WebSocket extends EventTarget {
|
|
|
258
270
|
|
|
259
271
|
// 1. If this's ready state is CONNECTING, then throw an
|
|
260
272
|
// "InvalidStateError" DOMException.
|
|
261
|
-
if (this
|
|
273
|
+
if (isConnecting(this)) {
|
|
262
274
|
throw new DOMException('Sent before connected.', 'InvalidStateError')
|
|
263
275
|
}
|
|
264
276
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "undici",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.7.1",
|
|
4
4
|
"description": "An HTTP/1.1 client, written from scratch for Node.js",
|
|
5
5
|
"homepage": "https://undici.nodejs.org",
|
|
6
6
|
"bugs": {
|
|
@@ -61,42 +61,34 @@
|
|
|
61
61
|
],
|
|
62
62
|
"main": "index.js",
|
|
63
63
|
"types": "index.d.ts",
|
|
64
|
-
"files": [
|
|
65
|
-
"*.d.ts",
|
|
66
|
-
"index.js",
|
|
67
|
-
"index-fetch.js",
|
|
68
|
-
"loader.js",
|
|
69
|
-
"lib",
|
|
70
|
-
"types",
|
|
71
|
-
"docs"
|
|
72
|
-
],
|
|
73
64
|
"scripts": {
|
|
74
|
-
"build:node": "npx esbuild@0.19.4 index-fetch.js --bundle --platform=node --outfile=undici-fetch.js --define:esbuildDetection=1 --keep-names",
|
|
65
|
+
"build:node": "npx esbuild@0.19.4 index-fetch.js --bundle --platform=node --outfile=undici-fetch.js --define:esbuildDetection=1 --keep-names && node scripts/strip-comments.js",
|
|
75
66
|
"prebuild:wasm": "node build/wasm.js --prebuild",
|
|
76
67
|
"build:wasm": "node build/wasm.js --docker",
|
|
77
68
|
"lint": "standard | snazzy",
|
|
78
69
|
"lint:fix": "standard --fix | snazzy",
|
|
79
|
-
"test": "
|
|
80
|
-
"test:
|
|
81
|
-
"test:
|
|
82
|
-
"test:
|
|
83
|
-
"test:
|
|
84
|
-
"test:
|
|
85
|
-
"test:
|
|
86
|
-
"test:
|
|
87
|
-
"test:
|
|
70
|
+
"test": "npm run test:javascript && cross-env NODE_V8_COVERAGE= npm run test:typescript",
|
|
71
|
+
"test:javascript": "node scripts/generate-pem && npm run test:unit && npm run test:node-fetch && npm run test:fetch && npm run test:cookies && npm run test:eventsource && npm run test:wpt && npm run test:websocket && npm run test:node-test && npm run test:jest",
|
|
72
|
+
"test:cookies": "borp -p \"test/cookie/*.js\"",
|
|
73
|
+
"test:node-fetch": "borp -p \"test/node-fetch/**/*.js\"",
|
|
74
|
+
"test:eventsource": "npm run build:node && borp --expose-gc -p \"test/eventsource/*.js\"",
|
|
75
|
+
"test:fetch": "npm run build:node && borp --expose-gc -p \"test/fetch/*.js\" && borp -p \"test/webidl/*.js\" && borp -p \"test/busboy/*.js\"",
|
|
76
|
+
"test:jest": "cross-env NODE_V8_COVERAGE= jest",
|
|
77
|
+
"test:unit": "borp --expose-gc -p \"test/*.js\"",
|
|
78
|
+
"test:node-test": "borp -p \"test/node-test/**/*.js\"",
|
|
79
|
+
"test:tdd": "borp --expose-gc -p \"test/*.js\"",
|
|
88
80
|
"test:tdd:node-test": "borp -p \"test/node-test/**/*.js\" -w",
|
|
89
81
|
"test:typescript": "tsd && tsc --skipLibCheck test/imports/undici-import.ts",
|
|
90
|
-
"test:websocket": "borp
|
|
82
|
+
"test:websocket": "borp -p \"test/websocket/*.js\"",
|
|
91
83
|
"test:wpt": "node test/wpt/start-fetch.mjs && node test/wpt/start-FileAPI.mjs && node test/wpt/start-mimesniff.mjs && node test/wpt/start-xhr.mjs && node test/wpt/start-websockets.mjs && node test/wpt/start-cacheStorage.mjs && node test/wpt/start-eventsource.mjs",
|
|
92
|
-
"coverage": "
|
|
93
|
-
"coverage:ci": "
|
|
94
|
-
"
|
|
95
|
-
"
|
|
96
|
-
"
|
|
97
|
-
"bench
|
|
98
|
-
"serve:website": "
|
|
99
|
-
"prepare": "husky install",
|
|
84
|
+
"coverage": "npm run coverage:clean && cross-env NODE_V8_COVERAGE=./coverage/tmp npm run test:javascript && npm run coverage:report",
|
|
85
|
+
"coverage:ci": "npm run coverage:clean && cross-env NODE_V8_COVERAGE=./coverage/tmp npm run test:javascript && npm run coverage:report:ci",
|
|
86
|
+
"coverage:clean": "node ./scripts/clean-coverage.js",
|
|
87
|
+
"coverage:report": "cross-env NODE_V8_COVERAGE= c8 report",
|
|
88
|
+
"coverage:report:ci": "c8 report",
|
|
89
|
+
"bench": "echo \"Error: Benchmarks have been moved to '/benchmarks'\" && exit 1",
|
|
90
|
+
"serve:website": "echo \"Error: Documentation has been moved to '/docs'\" && exit 1",
|
|
91
|
+
"prepare": "husky install && node ./scripts/platform-shell.js",
|
|
100
92
|
"fuzz": "jsfuzz test/fuzzing/fuzz.js corpus"
|
|
101
93
|
},
|
|
102
94
|
"devDependencies": {
|
|
@@ -105,47 +97,30 @@
|
|
|
105
97
|
"@types/node": "^18.0.3",
|
|
106
98
|
"abort-controller": "^3.0.0",
|
|
107
99
|
"borp": "^0.9.1",
|
|
108
|
-
"
|
|
109
|
-
"
|
|
110
|
-
"chai-iterator": "^3.0.2",
|
|
111
|
-
"chai-string": "^1.5.0",
|
|
112
|
-
"concurrently": "^8.0.1",
|
|
113
|
-
"cronometro": "^2.0.2",
|
|
100
|
+
"c8": "^9.1.0",
|
|
101
|
+
"cross-env": "^7.0.3",
|
|
114
102
|
"dns-packet": "^5.4.0",
|
|
115
|
-
"docsify-cli": "^4.4.3",
|
|
116
103
|
"form-data": "^4.0.0",
|
|
117
104
|
"formdata-node": "^6.0.3",
|
|
118
105
|
"https-pem": "^3.0.0",
|
|
119
106
|
"husky": "^9.0.7",
|
|
120
|
-
"import-fresh": "^3.3.0",
|
|
121
107
|
"jest": "^29.0.2",
|
|
122
108
|
"jsdom": "^24.0.0",
|
|
123
109
|
"jsfuzz": "^1.0.15",
|
|
124
|
-
"mitata": "^0.1.8",
|
|
125
|
-
"mocha": "^10.0.0",
|
|
126
|
-
"p-timeout": "^3.2.0",
|
|
127
110
|
"pre-commit": "^1.2.2",
|
|
128
|
-
"proxy": "^1.
|
|
129
|
-
"proxyquire": "^2.1.3",
|
|
130
|
-
"sinon": "^17.0.1",
|
|
111
|
+
"proxy": "^2.1.1",
|
|
131
112
|
"snazzy": "^9.0.0",
|
|
132
113
|
"standard": "^17.0.0",
|
|
133
|
-
"tap": "^16.1.0",
|
|
134
114
|
"tsd": "^0.30.1",
|
|
135
115
|
"typescript": "^5.0.2",
|
|
136
|
-
"
|
|
137
|
-
"ws": "^8.11.0",
|
|
138
|
-
"axios": "^1.6.5",
|
|
139
|
-
"got": "^14.0.0",
|
|
140
|
-
"node-fetch": "^3.3.2",
|
|
141
|
-
"request": "^2.88.2"
|
|
116
|
+
"ws": "^8.11.0"
|
|
142
117
|
},
|
|
143
118
|
"engines": {
|
|
144
119
|
"node": ">=18.0"
|
|
145
120
|
},
|
|
146
121
|
"standard": {
|
|
147
122
|
"env": [
|
|
148
|
-
"
|
|
123
|
+
"jest"
|
|
149
124
|
],
|
|
150
125
|
"ignore": [
|
|
151
126
|
"lib/llhttp/constants.js",
|
|
@@ -166,8 +141,5 @@
|
|
|
166
141
|
"testMatch": [
|
|
167
142
|
"<rootDir>/test/jest/**"
|
|
168
143
|
]
|
|
169
|
-
},
|
|
170
|
-
"dependencies": {
|
|
171
|
-
"@fastify/busboy": "^2.0.0"
|
|
172
144
|
}
|
|
173
145
|
}
|
package/types/dispatcher.d.ts
CHANGED
|
@@ -100,7 +100,7 @@ declare namespace Dispatcher {
|
|
|
100
100
|
/** Default: `null` */
|
|
101
101
|
body?: string | Buffer | Uint8Array | Readable | null | FormData;
|
|
102
102
|
/** Default: `null` */
|
|
103
|
-
headers?: IncomingHttpHeaders | string[] | null;
|
|
103
|
+
headers?: IncomingHttpHeaders | string[] | Iterable<[string, string | string[] | undefined]> | null;
|
|
104
104
|
/** Query string params to be embedded in the request URL. Default: `null` */
|
|
105
105
|
query?: Record<string, any>;
|
|
106
106
|
/** Whether the requests can be safely retried or not. If `false` the request won't be sent until all preceding requests in the pipeline have completed. Default: `true` if `method` is `HEAD` or `GET`. */
|
package/types/fetch.d.ts
CHANGED
|
@@ -27,12 +27,29 @@ export type BodyInit =
|
|
|
27
27
|
| null
|
|
28
28
|
| string
|
|
29
29
|
|
|
30
|
-
export
|
|
30
|
+
export class BodyMixin {
|
|
31
31
|
readonly body: ReadableStream | null
|
|
32
32
|
readonly bodyUsed: boolean
|
|
33
33
|
|
|
34
34
|
readonly arrayBuffer: () => Promise<ArrayBuffer>
|
|
35
35
|
readonly blob: () => Promise<Blob>
|
|
36
|
+
/**
|
|
37
|
+
* @deprecated This method is not recommended for parsing multipart/form-data bodies in server environments.
|
|
38
|
+
* It is recommended to use a library such as [@fastify/busboy](https://www.npmjs.com/package/@fastify/busboy) as follows:
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* ```js
|
|
42
|
+
* import { Busboy } from '@fastify/busboy'
|
|
43
|
+
* import { Readable } from 'node:stream'
|
|
44
|
+
*
|
|
45
|
+
* const response = await fetch('...')
|
|
46
|
+
* const busboy = new Busboy({ headers: { 'content-type': response.headers.get('content-type') } })
|
|
47
|
+
*
|
|
48
|
+
* // handle events emitted from `busboy`
|
|
49
|
+
*
|
|
50
|
+
* Readable.fromWeb(response.body).pipe(busboy)
|
|
51
|
+
* ```
|
|
52
|
+
*/
|
|
36
53
|
readonly formData: () => Promise<FormData>
|
|
37
54
|
readonly json: () => Promise<unknown>
|
|
38
55
|
readonly text: () => Promise<string>
|
|
@@ -135,7 +152,7 @@ export type RequestRedirect = 'error' | 'follow' | 'manual'
|
|
|
135
152
|
|
|
136
153
|
export type RequestDuplex = 'half'
|
|
137
154
|
|
|
138
|
-
export declare class Request
|
|
155
|
+
export declare class Request extends BodyMixin {
|
|
139
156
|
constructor (input: RequestInfo, init?: RequestInit)
|
|
140
157
|
|
|
141
158
|
readonly cache: RequestCache
|
|
@@ -153,15 +170,6 @@ export declare class Request implements BodyMixin {
|
|
|
153
170
|
readonly signal: AbortSignal
|
|
154
171
|
readonly duplex: RequestDuplex
|
|
155
172
|
|
|
156
|
-
readonly body: ReadableStream | null
|
|
157
|
-
readonly bodyUsed: boolean
|
|
158
|
-
|
|
159
|
-
readonly arrayBuffer: () => Promise<ArrayBuffer>
|
|
160
|
-
readonly blob: () => Promise<Blob>
|
|
161
|
-
readonly formData: () => Promise<FormData>
|
|
162
|
-
readonly json: () => Promise<unknown>
|
|
163
|
-
readonly text: () => Promise<string>
|
|
164
|
-
|
|
165
173
|
readonly clone: () => Request
|
|
166
174
|
}
|
|
167
175
|
|
|
@@ -181,7 +189,7 @@ export type ResponseType =
|
|
|
181
189
|
|
|
182
190
|
export type ResponseRedirectStatus = 301 | 302 | 303 | 307 | 308
|
|
183
191
|
|
|
184
|
-
export declare class Response
|
|
192
|
+
export declare class Response extends BodyMixin {
|
|
185
193
|
constructor (body?: BodyInit, init?: ResponseInit)
|
|
186
194
|
|
|
187
195
|
readonly headers: Headers
|
|
@@ -192,15 +200,6 @@ export declare class Response implements BodyMixin {
|
|
|
192
200
|
readonly url: string
|
|
193
201
|
readonly redirected: boolean
|
|
194
202
|
|
|
195
|
-
readonly body: ReadableStream | null
|
|
196
|
-
readonly bodyUsed: boolean
|
|
197
|
-
|
|
198
|
-
readonly arrayBuffer: () => Promise<ArrayBuffer>
|
|
199
|
-
readonly blob: () => Promise<Blob>
|
|
200
|
-
readonly formData: () => Promise<FormData>
|
|
201
|
-
readonly json: () => Promise<unknown>
|
|
202
|
-
readonly text: () => Promise<string>
|
|
203
|
-
|
|
204
203
|
readonly clone: () => Response
|
|
205
204
|
|
|
206
205
|
static error (): Response
|
package/types/index.d.ts
CHANGED
|
@@ -15,6 +15,7 @@ import MockAgent from'./mock-agent'
|
|
|
15
15
|
import mockErrors from'./mock-errors'
|
|
16
16
|
import ProxyAgent from'./proxy-agent'
|
|
17
17
|
import RetryHandler from'./retry-handler'
|
|
18
|
+
import RetryAgent from'./retry-agent'
|
|
18
19
|
import { request, pipeline, stream, connect, upgrade } from './api'
|
|
19
20
|
|
|
20
21
|
export * from './util'
|
|
@@ -30,7 +31,7 @@ export * from './content-type'
|
|
|
30
31
|
export * from './cache'
|
|
31
32
|
export { Interceptable } from './mock-interceptor'
|
|
32
33
|
|
|
33
|
-
export { Dispatcher, BalancedPool, Pool, Client, buildConnector, errors, Agent, request, stream, pipeline, connect, upgrade, setGlobalDispatcher, getGlobalDispatcher, setGlobalOrigin, getGlobalOrigin, MockClient, MockPool, MockAgent, mockErrors, ProxyAgent, RedirectHandler, DecoratorHandler, RetryHandler }
|
|
34
|
+
export { Dispatcher, BalancedPool, Pool, Client, buildConnector, errors, Agent, request, stream, pipeline, connect, upgrade, setGlobalDispatcher, getGlobalDispatcher, setGlobalOrigin, getGlobalOrigin, MockClient, MockPool, MockAgent, mockErrors, ProxyAgent, RedirectHandler, DecoratorHandler, RetryHandler, RetryAgent }
|
|
34
35
|
export default Undici
|
|
35
36
|
|
|
36
37
|
declare namespace Undici {
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import Agent from './agent'
|
|
2
|
+
import buildConnector from './connector';
|
|
3
|
+
import Dispatcher from './dispatcher'
|
|
4
|
+
import { IncomingHttpHeaders } from './header'
|
|
5
|
+
import RetryHandler from './retry-handler'
|
|
6
|
+
|
|
7
|
+
export default RetryAgent
|
|
8
|
+
|
|
9
|
+
declare class RetryAgent extends Dispatcher {
|
|
10
|
+
constructor(dispatcher: Dispatcher, options?: RetryHandler.RetryOptions)
|
|
11
|
+
}
|
package/types/webidl.d.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
type Converter<T> = (object: unknown) => T
|
|
7
7
|
|
|
8
|
-
type SequenceConverter<T> = (object: unknown) => T[]
|
|
8
|
+
type SequenceConverter<T> = (object: unknown, iterable?: IterableIterator<T>) => T[]
|
|
9
9
|
|
|
10
10
|
type RecordConverter<K extends string, V> = (object: unknown) => Record<K, V>
|
|
11
11
|
|
|
@@ -62,6 +62,11 @@ interface WebidlUtil {
|
|
|
62
62
|
* @see https://webidl.spec.whatwg.org/#abstract-opdef-converttoint
|
|
63
63
|
*/
|
|
64
64
|
IntegerPart (N: number): number
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Stringifies {@param V}
|
|
68
|
+
*/
|
|
69
|
+
Stringify (V: any): string
|
|
65
70
|
}
|
|
66
71
|
|
|
67
72
|
interface WebidlConverters {
|
package/docs/api/Fetch.md
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
# Fetch
|
|
2
|
-
|
|
3
|
-
Undici exposes a fetch() method starts the process of fetching a resource from the network.
|
|
4
|
-
|
|
5
|
-
Documentation and examples can be found on [MDN](https://developer.mozilla.org/en-US/docs/Web/API/fetch).
|
|
6
|
-
|
|
7
|
-
## File
|
|
8
|
-
|
|
9
|
-
This API is implemented as per the standard, you can find documentation on [MDN](https://developer.mozilla.org/en-US/docs/Web/API/File)
|
|
10
|
-
|
|
11
|
-
In Node versions v18.13.0 and above and v19.2.0 and above, undici will default to using Node's [File](https://nodejs.org/api/buffer.html#class-file) class. In versions where it's not available, it will default to the undici one.
|
|
12
|
-
|
|
13
|
-
## FormData
|
|
14
|
-
|
|
15
|
-
This API is implemented as per the standard, you can find documentation on [MDN](https://developer.mozilla.org/en-US/docs/Web/API/FormData)
|
|
16
|
-
|
|
17
|
-
## Response
|
|
18
|
-
|
|
19
|
-
This API is implemented as per the standard, you can find documentation on [MDN](https://developer.mozilla.org/en-US/docs/Web/API/Response)
|
|
20
|
-
|
|
21
|
-
## Request
|
|
22
|
-
|
|
23
|
-
This API is implemented as per the standard, you can find documentation on [MDN](https://developer.mozilla.org/en-US/docs/Web/API/Request)
|
|
24
|
-
|
|
25
|
-
## Header
|
|
26
|
-
|
|
27
|
-
This API is implemented as per the standard, you can find documentation on [MDN](https://developer.mozilla.org/en-US/docs/Web/API/Headers)
|
|
Binary file
|