undici 6.20.0 → 7.0.0-alpha.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.
- package/README.md +6 -10
- package/docs/docs/api/Agent.md +0 -3
- package/docs/docs/api/Client.md +1 -3
- package/docs/docs/api/Debug.md +1 -1
- package/docs/docs/api/Dispatcher.md +60 -8
- package/docs/docs/api/EnvHttpProxyAgent.md +0 -1
- package/docs/docs/api/Fetch.md +1 -0
- package/docs/docs/api/MockAgent.md +2 -0
- package/docs/docs/api/MockPool.md +2 -1
- package/docs/docs/api/Pool.md +0 -1
- package/docs/docs/api/RetryAgent.md +1 -1
- package/docs/docs/api/RetryHandler.md +1 -1
- package/docs/docs/api/WebSocket.md +45 -3
- package/index.js +6 -6
- package/lib/api/abort-signal.js +2 -0
- package/lib/api/api-connect.js +3 -1
- package/lib/api/api-pipeline.js +7 -6
- package/lib/api/api-request.js +32 -47
- package/lib/api/api-stream.js +39 -50
- package/lib/api/api-upgrade.js +5 -3
- package/lib/api/readable.js +261 -64
- package/lib/api/util.js +2 -0
- package/lib/core/constants.js +11 -9
- package/lib/core/diagnostics.js +122 -128
- package/lib/core/errors.js +4 -4
- package/lib/core/request.js +11 -9
- package/lib/core/symbols.js +2 -1
- package/lib/core/tree.js +9 -1
- package/lib/core/util.js +219 -48
- package/lib/dispatcher/agent.js +3 -17
- package/lib/dispatcher/balanced-pool.js +5 -8
- package/lib/dispatcher/client-h1.js +278 -54
- package/lib/dispatcher/client-h2.js +1 -1
- package/lib/dispatcher/client.js +23 -34
- package/lib/dispatcher/dispatcher-base.js +2 -34
- package/lib/dispatcher/dispatcher.js +3 -24
- package/lib/dispatcher/fixed-queue.js +91 -49
- package/lib/dispatcher/pool-stats.js +2 -0
- package/lib/dispatcher/pool.js +3 -6
- package/lib/dispatcher/proxy-agent.js +6 -7
- package/lib/handler/decorator-handler.js +24 -0
- package/lib/handler/redirect-handler.js +11 -2
- package/lib/handler/retry-handler.js +12 -3
- package/lib/interceptor/dns.js +346 -0
- package/lib/interceptor/dump.js +2 -2
- package/lib/interceptor/redirect.js +11 -14
- package/lib/interceptor/response-error.js +4 -1
- package/lib/llhttp/constants.d.ts +97 -0
- package/lib/llhttp/constants.js +412 -192
- package/lib/llhttp/constants.js.map +1 -0
- package/lib/llhttp/llhttp-wasm.js +11 -1
- package/lib/llhttp/llhttp_simd-wasm.js +11 -1
- package/lib/llhttp/utils.d.ts +2 -0
- package/lib/llhttp/utils.js +9 -9
- package/lib/llhttp/utils.js.map +1 -0
- package/lib/mock/mock-agent.js +5 -8
- package/lib/mock/mock-client.js +9 -4
- package/lib/mock/mock-errors.js +3 -1
- package/lib/mock/mock-interceptor.js +8 -6
- package/lib/mock/mock-pool.js +9 -4
- package/lib/mock/mock-symbols.js +3 -1
- package/lib/mock/mock-utils.js +29 -5
- package/lib/web/cache/cache.js +24 -21
- package/lib/web/cache/cachestorage.js +1 -1
- package/lib/web/cookies/index.js +17 -13
- package/lib/web/cookies/parse.js +2 -2
- package/lib/web/eventsource/eventsource-stream.js +9 -8
- package/lib/web/eventsource/eventsource.js +10 -6
- package/lib/web/fetch/body.js +42 -36
- package/lib/web/fetch/constants.js +35 -26
- package/lib/web/fetch/data-url.js +1 -1
- package/lib/web/fetch/formdata-parser.js +2 -2
- package/lib/web/fetch/formdata.js +65 -54
- package/lib/web/fetch/headers.js +117 -85
- package/lib/web/fetch/index.js +55 -62
- package/lib/web/fetch/request.js +135 -77
- package/lib/web/fetch/response.js +86 -56
- package/lib/web/fetch/util.js +90 -64
- package/lib/web/fetch/webidl.js +99 -64
- package/lib/web/websocket/connection.js +76 -147
- package/lib/web/websocket/constants.js +3 -4
- package/lib/web/websocket/events.js +4 -2
- package/lib/web/websocket/frame.js +45 -3
- package/lib/web/websocket/receiver.js +29 -33
- package/lib/web/websocket/sender.js +18 -13
- package/lib/web/websocket/stream/websocketerror.js +83 -0
- package/lib/web/websocket/stream/websocketstream.js +485 -0
- package/lib/web/websocket/util.js +128 -77
- package/lib/web/websocket/websocket.js +234 -135
- package/package.json +20 -33
- package/scripts/strip-comments.js +3 -1
- package/types/agent.d.ts +7 -7
- package/types/api.d.ts +24 -24
- package/types/balanced-pool.d.ts +11 -11
- package/types/client.d.ts +11 -12
- package/types/diagnostics-channel.d.ts +10 -10
- package/types/dispatcher.d.ts +96 -97
- package/types/env-http-proxy-agent.d.ts +2 -2
- package/types/errors.d.ts +53 -47
- package/types/fetch.d.ts +8 -8
- package/types/formdata.d.ts +7 -7
- package/types/global-dispatcher.d.ts +4 -4
- package/types/global-origin.d.ts +5 -5
- package/types/handlers.d.ts +4 -4
- package/types/header.d.ts +157 -1
- package/types/index.d.ts +42 -46
- package/types/interceptors.d.ts +22 -8
- package/types/mock-agent.d.ts +21 -18
- package/types/mock-client.d.ts +4 -4
- package/types/mock-errors.d.ts +3 -3
- package/types/mock-interceptor.d.ts +19 -19
- package/types/mock-pool.d.ts +4 -4
- package/types/patch.d.ts +0 -4
- package/types/pool-stats.d.ts +8 -8
- package/types/pool.d.ts +12 -12
- package/types/proxy-agent.d.ts +4 -4
- package/types/readable.d.ts +22 -14
- package/types/retry-agent.d.ts +1 -1
- package/types/retry-handler.d.ts +8 -8
- package/types/util.d.ts +3 -3
- package/types/utility.d.ts +7 -0
- package/types/webidl.d.ts +44 -6
- package/types/websocket.d.ts +34 -1
- package/docs/docs/api/DispatchInterceptor.md +0 -60
- package/lib/interceptor/redirect-interceptor.js +0 -21
- package/lib/mock/pluralizer.js +0 -29
- package/lib/web/cache/symbols.js +0 -5
- package/lib/web/fetch/file.js +0 -126
- package/lib/web/fetch/symbols.js +0 -9
- package/lib/web/fileapi/encoding.js +0 -290
- package/lib/web/fileapi/filereader.js +0 -344
- package/lib/web/fileapi/progressevent.js +0 -78
- package/lib/web/fileapi/symbols.js +0 -10
- package/lib/web/fileapi/util.js +0 -391
- package/lib/web/websocket/symbols.js +0 -12
- package/types/file.d.ts +0 -39
- package/types/filereader.d.ts +0 -54
|
@@ -78,56 +78,107 @@ async function lazyllhttp () {
|
|
|
78
78
|
|
|
79
79
|
return await WebAssembly.instantiate(mod, {
|
|
80
80
|
env: {
|
|
81
|
-
|
|
82
|
-
|
|
81
|
+
/**
|
|
82
|
+
* @param {number} p
|
|
83
|
+
* @param {number} at
|
|
84
|
+
* @param {number} len
|
|
85
|
+
* @returns {number}
|
|
86
|
+
*/
|
|
83
87
|
wasm_on_url: (p, at, len) => {
|
|
84
88
|
/* istanbul ignore next */
|
|
85
89
|
return 0
|
|
86
90
|
},
|
|
91
|
+
/**
|
|
92
|
+
* @param {number} p
|
|
93
|
+
* @param {number} at
|
|
94
|
+
* @param {number} len
|
|
95
|
+
* @returns {number}
|
|
96
|
+
*/
|
|
87
97
|
wasm_on_status: (p, at, len) => {
|
|
88
98
|
assert(currentParser.ptr === p)
|
|
89
99
|
const start = at - currentBufferPtr + currentBufferRef.byteOffset
|
|
90
|
-
return currentParser.onStatus(new FastBuffer(currentBufferRef.buffer, start, len))
|
|
100
|
+
return currentParser.onStatus(new FastBuffer(currentBufferRef.buffer, start, len))
|
|
91
101
|
},
|
|
102
|
+
/**
|
|
103
|
+
* @param {number} p
|
|
104
|
+
* @returns {number}
|
|
105
|
+
*/
|
|
92
106
|
wasm_on_message_begin: (p) => {
|
|
93
107
|
assert(currentParser.ptr === p)
|
|
94
|
-
return currentParser.onMessageBegin()
|
|
108
|
+
return currentParser.onMessageBegin()
|
|
95
109
|
},
|
|
110
|
+
/**
|
|
111
|
+
* @param {number} p
|
|
112
|
+
* @param {number} at
|
|
113
|
+
* @param {number} len
|
|
114
|
+
* @returns {number}
|
|
115
|
+
*/
|
|
96
116
|
wasm_on_header_field: (p, at, len) => {
|
|
97
117
|
assert(currentParser.ptr === p)
|
|
98
118
|
const start = at - currentBufferPtr + currentBufferRef.byteOffset
|
|
99
|
-
return currentParser.onHeaderField(new FastBuffer(currentBufferRef.buffer, start, len))
|
|
119
|
+
return currentParser.onHeaderField(new FastBuffer(currentBufferRef.buffer, start, len))
|
|
100
120
|
},
|
|
121
|
+
/**
|
|
122
|
+
* @param {number} p
|
|
123
|
+
* @param {number} at
|
|
124
|
+
* @param {number} len
|
|
125
|
+
* @returns {number}
|
|
126
|
+
*/
|
|
101
127
|
wasm_on_header_value: (p, at, len) => {
|
|
102
128
|
assert(currentParser.ptr === p)
|
|
103
129
|
const start = at - currentBufferPtr + currentBufferRef.byteOffset
|
|
104
|
-
return currentParser.onHeaderValue(new FastBuffer(currentBufferRef.buffer, start, len))
|
|
130
|
+
return currentParser.onHeaderValue(new FastBuffer(currentBufferRef.buffer, start, len))
|
|
105
131
|
},
|
|
132
|
+
/**
|
|
133
|
+
* @param {number} p
|
|
134
|
+
* @param {number} statusCode
|
|
135
|
+
* @param {0|1} upgrade
|
|
136
|
+
* @param {0|1} shouldKeepAlive
|
|
137
|
+
* @returns {number}
|
|
138
|
+
*/
|
|
106
139
|
wasm_on_headers_complete: (p, statusCode, upgrade, shouldKeepAlive) => {
|
|
107
140
|
assert(currentParser.ptr === p)
|
|
108
|
-
return currentParser.onHeadersComplete(statusCode,
|
|
141
|
+
return currentParser.onHeadersComplete(statusCode, upgrade === 1, shouldKeepAlive === 1)
|
|
109
142
|
},
|
|
143
|
+
/**
|
|
144
|
+
* @param {number} p
|
|
145
|
+
* @param {number} at
|
|
146
|
+
* @param {number} len
|
|
147
|
+
* @returns {number}
|
|
148
|
+
*/
|
|
110
149
|
wasm_on_body: (p, at, len) => {
|
|
111
150
|
assert(currentParser.ptr === p)
|
|
112
151
|
const start = at - currentBufferPtr + currentBufferRef.byteOffset
|
|
113
|
-
return currentParser.onBody(new FastBuffer(currentBufferRef.buffer, start, len))
|
|
152
|
+
return currentParser.onBody(new FastBuffer(currentBufferRef.buffer, start, len))
|
|
114
153
|
},
|
|
154
|
+
/**
|
|
155
|
+
* @param {number} p
|
|
156
|
+
* @returns {number}
|
|
157
|
+
*/
|
|
115
158
|
wasm_on_message_complete: (p) => {
|
|
116
159
|
assert(currentParser.ptr === p)
|
|
117
|
-
return currentParser.onMessageComplete()
|
|
160
|
+
return currentParser.onMessageComplete()
|
|
118
161
|
}
|
|
119
162
|
|
|
120
|
-
/* eslint-enable camelcase */
|
|
121
163
|
}
|
|
122
164
|
})
|
|
123
165
|
}
|
|
124
166
|
|
|
125
167
|
let llhttpInstance = null
|
|
168
|
+
/**
|
|
169
|
+
* @type {Promise<WebAssembly.Instance>|null}
|
|
170
|
+
*/
|
|
126
171
|
let llhttpPromise = lazyllhttp()
|
|
127
172
|
llhttpPromise.catch()
|
|
128
173
|
|
|
174
|
+
/**
|
|
175
|
+
* @type {Parser|null}
|
|
176
|
+
*/
|
|
129
177
|
let currentParser = null
|
|
130
178
|
let currentBufferRef = null
|
|
179
|
+
/**
|
|
180
|
+
* @type {number}
|
|
181
|
+
*/
|
|
131
182
|
let currentBufferSize = 0
|
|
132
183
|
let currentBufferPtr = null
|
|
133
184
|
|
|
@@ -144,17 +195,23 @@ const TIMEOUT_BODY = 4 | USE_FAST_TIMER
|
|
|
144
195
|
const TIMEOUT_KEEP_ALIVE = 8 | USE_NATIVE_TIMER
|
|
145
196
|
|
|
146
197
|
class Parser {
|
|
198
|
+
/**
|
|
199
|
+
* @param {import('./client.js')} client
|
|
200
|
+
* @param {import('net').Socket} socket
|
|
201
|
+
* @param {*} llhttp
|
|
202
|
+
*/
|
|
147
203
|
constructor (client, socket, { exports }) {
|
|
148
|
-
assert(Number.isFinite(client[kMaxHeadersSize]) && client[kMaxHeadersSize] > 0)
|
|
149
|
-
|
|
150
204
|
this.llhttp = exports
|
|
151
205
|
this.ptr = this.llhttp.llhttp_alloc(constants.TYPE.RESPONSE)
|
|
152
206
|
this.client = client
|
|
207
|
+
/**
|
|
208
|
+
* @type {import('net').Socket}
|
|
209
|
+
*/
|
|
153
210
|
this.socket = socket
|
|
154
211
|
this.timeout = null
|
|
155
212
|
this.timeoutValue = null
|
|
156
213
|
this.timeoutType = null
|
|
157
|
-
this.statusCode =
|
|
214
|
+
this.statusCode = 0
|
|
158
215
|
this.statusText = ''
|
|
159
216
|
this.upgrade = false
|
|
160
217
|
this.headers = []
|
|
@@ -213,7 +270,7 @@ class Parser {
|
|
|
213
270
|
}
|
|
214
271
|
|
|
215
272
|
assert(this.ptr != null)
|
|
216
|
-
assert(currentParser
|
|
273
|
+
assert(currentParser === null)
|
|
217
274
|
|
|
218
275
|
this.llhttp.llhttp_resume(this.ptr)
|
|
219
276
|
|
|
@@ -240,22 +297,27 @@ class Parser {
|
|
|
240
297
|
}
|
|
241
298
|
}
|
|
242
299
|
|
|
243
|
-
|
|
300
|
+
/**
|
|
301
|
+
* @param {Buffer} chunk
|
|
302
|
+
*/
|
|
303
|
+
execute (chunk) {
|
|
304
|
+
assert(currentParser === null)
|
|
244
305
|
assert(this.ptr != null)
|
|
245
|
-
assert(currentParser == null)
|
|
246
306
|
assert(!this.paused)
|
|
247
307
|
|
|
248
308
|
const { socket, llhttp } = this
|
|
249
309
|
|
|
250
|
-
if
|
|
310
|
+
// Allocate a new buffer if the current buffer is too small.
|
|
311
|
+
if (chunk.length > currentBufferSize) {
|
|
251
312
|
if (currentBufferPtr) {
|
|
252
313
|
llhttp.free(currentBufferPtr)
|
|
253
314
|
}
|
|
254
|
-
|
|
315
|
+
// Allocate a buffer that is a multiple of 4096 bytes.
|
|
316
|
+
currentBufferSize = Math.ceil(chunk.length / 4096) * 4096
|
|
255
317
|
currentBufferPtr = llhttp.malloc(currentBufferSize)
|
|
256
318
|
}
|
|
257
319
|
|
|
258
|
-
new Uint8Array(llhttp.memory.buffer, currentBufferPtr, currentBufferSize).set(
|
|
320
|
+
new Uint8Array(llhttp.memory.buffer, currentBufferPtr, currentBufferSize).set(chunk)
|
|
259
321
|
|
|
260
322
|
// Call `execute` on the wasm parser.
|
|
261
323
|
// We pass the `llhttp_parser` pointer address, the pointer address of buffer view data,
|
|
@@ -265,9 +327,9 @@ class Parser {
|
|
|
265
327
|
let ret
|
|
266
328
|
|
|
267
329
|
try {
|
|
268
|
-
currentBufferRef =
|
|
330
|
+
currentBufferRef = chunk
|
|
269
331
|
currentParser = this
|
|
270
|
-
ret = llhttp.llhttp_execute(this.ptr, currentBufferPtr,
|
|
332
|
+
ret = llhttp.llhttp_execute(this.ptr, currentBufferPtr, chunk.length)
|
|
271
333
|
/* eslint-disable-next-line no-useless-catch */
|
|
272
334
|
} catch (err) {
|
|
273
335
|
/* istanbul ignore next: difficult to make a test case for */
|
|
@@ -277,25 +339,27 @@ class Parser {
|
|
|
277
339
|
currentBufferRef = null
|
|
278
340
|
}
|
|
279
341
|
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
342
|
+
if (ret !== constants.ERROR.OK) {
|
|
343
|
+
const data = chunk.subarray(llhttp.llhttp_get_error_pos(this.ptr) - currentBufferPtr)
|
|
344
|
+
|
|
345
|
+
if (ret === constants.ERROR.PAUSED_UPGRADE) {
|
|
346
|
+
this.onUpgrade(data)
|
|
347
|
+
} else if (ret === constants.ERROR.PAUSED) {
|
|
348
|
+
this.paused = true
|
|
349
|
+
socket.unshift(data)
|
|
350
|
+
} else {
|
|
351
|
+
const ptr = llhttp.llhttp_get_error_reason(this.ptr)
|
|
352
|
+
let message = ''
|
|
353
|
+
/* istanbul ignore else: difficult to make a test case for */
|
|
354
|
+
if (ptr) {
|
|
355
|
+
const len = new Uint8Array(llhttp.memory.buffer, ptr).indexOf(0)
|
|
356
|
+
message =
|
|
357
|
+
'Response does not match the HTTP/1.1 protocol (' +
|
|
358
|
+
Buffer.from(llhttp.memory.buffer, ptr, len).toString() +
|
|
359
|
+
')'
|
|
360
|
+
}
|
|
361
|
+
throw new HTTPParserError(message, constants.ERROR[ret], data)
|
|
297
362
|
}
|
|
298
|
-
throw new HTTPParserError(message, constants.ERROR[ret], data.slice(offset))
|
|
299
363
|
}
|
|
300
364
|
} catch (err) {
|
|
301
365
|
util.destroy(socket, err)
|
|
@@ -303,8 +367,8 @@ class Parser {
|
|
|
303
367
|
}
|
|
304
368
|
|
|
305
369
|
destroy () {
|
|
370
|
+
assert(currentParser === null)
|
|
306
371
|
assert(this.ptr != null)
|
|
307
|
-
assert(currentParser == null)
|
|
308
372
|
|
|
309
373
|
this.llhttp.llhttp_free(this.ptr)
|
|
310
374
|
this.ptr = null
|
|
@@ -317,10 +381,18 @@ class Parser {
|
|
|
317
381
|
this.paused = false
|
|
318
382
|
}
|
|
319
383
|
|
|
384
|
+
/**
|
|
385
|
+
* @param {Buffer} buf
|
|
386
|
+
* @returns {0}
|
|
387
|
+
*/
|
|
320
388
|
onStatus (buf) {
|
|
321
389
|
this.statusText = buf.toString()
|
|
390
|
+
return 0
|
|
322
391
|
}
|
|
323
392
|
|
|
393
|
+
/**
|
|
394
|
+
* @returns {0|-1}
|
|
395
|
+
*/
|
|
324
396
|
onMessageBegin () {
|
|
325
397
|
const { socket, client } = this
|
|
326
398
|
|
|
@@ -334,8 +406,14 @@ class Parser {
|
|
|
334
406
|
return -1
|
|
335
407
|
}
|
|
336
408
|
request.onResponseStarted()
|
|
409
|
+
|
|
410
|
+
return 0
|
|
337
411
|
}
|
|
338
412
|
|
|
413
|
+
/**
|
|
414
|
+
* @param {Buffer} buf
|
|
415
|
+
* @returns {number}
|
|
416
|
+
*/
|
|
339
417
|
onHeaderField (buf) {
|
|
340
418
|
const len = this.headers.length
|
|
341
419
|
|
|
@@ -346,8 +424,14 @@ class Parser {
|
|
|
346
424
|
}
|
|
347
425
|
|
|
348
426
|
this.trackHeader(buf.length)
|
|
427
|
+
|
|
428
|
+
return 0
|
|
349
429
|
}
|
|
350
430
|
|
|
431
|
+
/**
|
|
432
|
+
* @param {Buffer} buf
|
|
433
|
+
* @returns {number}
|
|
434
|
+
*/
|
|
351
435
|
onHeaderValue (buf) {
|
|
352
436
|
let len = this.headers.length
|
|
353
437
|
|
|
@@ -371,8 +455,13 @@ class Parser {
|
|
|
371
455
|
}
|
|
372
456
|
|
|
373
457
|
this.trackHeader(buf.length)
|
|
458
|
+
|
|
459
|
+
return 0
|
|
374
460
|
}
|
|
375
461
|
|
|
462
|
+
/**
|
|
463
|
+
* @param {number} len
|
|
464
|
+
*/
|
|
376
465
|
trackHeader (len) {
|
|
377
466
|
this.headersSize += len
|
|
378
467
|
if (this.headersSize >= this.headersMaxSize) {
|
|
@@ -380,6 +469,9 @@ class Parser {
|
|
|
380
469
|
}
|
|
381
470
|
}
|
|
382
471
|
|
|
472
|
+
/**
|
|
473
|
+
* @param {Buffer} head
|
|
474
|
+
*/
|
|
383
475
|
onUpgrade (head) {
|
|
384
476
|
const { upgrade, client, socket, headers, statusCode } = this
|
|
385
477
|
|
|
@@ -393,9 +485,9 @@ class Parser {
|
|
|
393
485
|
assert(request)
|
|
394
486
|
assert(request.upgrade || request.method === 'CONNECT')
|
|
395
487
|
|
|
396
|
-
this.statusCode =
|
|
488
|
+
this.statusCode = 0
|
|
397
489
|
this.statusText = ''
|
|
398
|
-
this.shouldKeepAlive =
|
|
490
|
+
this.shouldKeepAlive = false
|
|
399
491
|
|
|
400
492
|
this.headers = []
|
|
401
493
|
this.headersSize = 0
|
|
@@ -424,6 +516,12 @@ class Parser {
|
|
|
424
516
|
client[kResume]()
|
|
425
517
|
}
|
|
426
518
|
|
|
519
|
+
/**
|
|
520
|
+
* @param {number} statusCode
|
|
521
|
+
* @param {boolean} upgrade
|
|
522
|
+
* @param {boolean} shouldKeepAlive
|
|
523
|
+
* @returns {number}
|
|
524
|
+
*/
|
|
427
525
|
onHeadersComplete (statusCode, upgrade, shouldKeepAlive) {
|
|
428
526
|
const { client, socket, headers, statusText } = this
|
|
429
527
|
|
|
@@ -533,6 +631,10 @@ class Parser {
|
|
|
533
631
|
return pause ? constants.ERROR.PAUSED : 0
|
|
534
632
|
}
|
|
535
633
|
|
|
634
|
+
/**
|
|
635
|
+
* @param {Buffer} buf
|
|
636
|
+
* @returns {number}
|
|
637
|
+
*/
|
|
536
638
|
onBody (buf) {
|
|
537
639
|
const { client, socket, statusCode, maxResponseSize } = this
|
|
538
640
|
|
|
@@ -563,8 +665,13 @@ class Parser {
|
|
|
563
665
|
if (request.onData(buf) === false) {
|
|
564
666
|
return constants.ERROR.PAUSED
|
|
565
667
|
}
|
|
668
|
+
|
|
669
|
+
return 0
|
|
566
670
|
}
|
|
567
671
|
|
|
672
|
+
/**
|
|
673
|
+
* @returns {number}
|
|
674
|
+
*/
|
|
568
675
|
onMessageComplete () {
|
|
569
676
|
const { client, socket, statusCode, upgrade, headers, contentLength, bytesRead, shouldKeepAlive } = this
|
|
570
677
|
|
|
@@ -573,7 +680,7 @@ class Parser {
|
|
|
573
680
|
}
|
|
574
681
|
|
|
575
682
|
if (upgrade) {
|
|
576
|
-
return
|
|
683
|
+
return 0
|
|
577
684
|
}
|
|
578
685
|
|
|
579
686
|
assert(statusCode >= 100)
|
|
@@ -582,7 +689,7 @@ class Parser {
|
|
|
582
689
|
const request = client[kQueue][client[kRunningIdx]]
|
|
583
690
|
assert(request)
|
|
584
691
|
|
|
585
|
-
this.statusCode =
|
|
692
|
+
this.statusCode = 0
|
|
586
693
|
this.statusText = ''
|
|
587
694
|
this.bytesRead = 0
|
|
588
695
|
this.contentLength = ''
|
|
@@ -593,7 +700,7 @@ class Parser {
|
|
|
593
700
|
this.headersSize = 0
|
|
594
701
|
|
|
595
702
|
if (statusCode < 200) {
|
|
596
|
-
return
|
|
703
|
+
return 0
|
|
597
704
|
}
|
|
598
705
|
|
|
599
706
|
/* istanbul ignore next: should be handled by llhttp? */
|
|
@@ -629,6 +736,8 @@ class Parser {
|
|
|
629
736
|
} else {
|
|
630
737
|
client[kResume]()
|
|
631
738
|
}
|
|
739
|
+
|
|
740
|
+
return 0
|
|
632
741
|
}
|
|
633
742
|
}
|
|
634
743
|
|
|
@@ -651,6 +760,11 @@ function onParserTimeout (parser) {
|
|
|
651
760
|
}
|
|
652
761
|
}
|
|
653
762
|
|
|
763
|
+
/**
|
|
764
|
+
* @param {import ('./client.js')} client
|
|
765
|
+
* @param {import('net').Socket} socket
|
|
766
|
+
* @returns
|
|
767
|
+
*/
|
|
654
768
|
async function connectH1 (client, socket) {
|
|
655
769
|
client[kSocket] = socket
|
|
656
770
|
|
|
@@ -683,11 +797,7 @@ async function connectH1 (client, socket) {
|
|
|
683
797
|
this[kClient][kOnError](err)
|
|
684
798
|
})
|
|
685
799
|
addListener(socket, 'readable', function () {
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
if (parser) {
|
|
689
|
-
parser.readMore()
|
|
690
|
-
}
|
|
800
|
+
this[kParser]?.readMore()
|
|
691
801
|
})
|
|
692
802
|
addListener(socket, 'end', function () {
|
|
693
803
|
const parser = this[kParser]
|
|
@@ -701,7 +811,6 @@ async function connectH1 (client, socket) {
|
|
|
701
811
|
util.destroy(this, new SocketError('other side closed', util.getSocketInfo(this)))
|
|
702
812
|
})
|
|
703
813
|
addListener(socket, 'close', function () {
|
|
704
|
-
const client = this[kClient]
|
|
705
814
|
const parser = this[kParser]
|
|
706
815
|
|
|
707
816
|
if (parser) {
|
|
@@ -716,6 +825,8 @@ async function connectH1 (client, socket) {
|
|
|
716
825
|
|
|
717
826
|
const err = this[kError] || new SocketError('closed', util.getSocketInfo(this))
|
|
718
827
|
|
|
828
|
+
const client = this[kClient]
|
|
829
|
+
|
|
719
830
|
client[kSocket] = null
|
|
720
831
|
client[kHTTPContext] = null // TODO (fix): This is hacky...
|
|
721
832
|
|
|
@@ -753,22 +864,34 @@ async function connectH1 (client, socket) {
|
|
|
753
864
|
return {
|
|
754
865
|
version: 'h1',
|
|
755
866
|
defaultPipelining: 1,
|
|
756
|
-
write (
|
|
757
|
-
return writeH1(client,
|
|
867
|
+
write (request) {
|
|
868
|
+
return writeH1(client, request)
|
|
758
869
|
},
|
|
759
870
|
resume () {
|
|
760
871
|
resumeH1(client)
|
|
761
872
|
},
|
|
873
|
+
/**
|
|
874
|
+
* @param {Error|undefined} err
|
|
875
|
+
* @param {() => void} callback
|
|
876
|
+
*/
|
|
762
877
|
destroy (err, callback) {
|
|
763
878
|
if (closed) {
|
|
764
879
|
queueMicrotask(callback)
|
|
765
880
|
} else {
|
|
766
|
-
socket.
|
|
881
|
+
socket.on('close', callback)
|
|
882
|
+
socket.destroy(err)
|
|
767
883
|
}
|
|
768
884
|
},
|
|
885
|
+
/**
|
|
886
|
+
* @returns {boolean}
|
|
887
|
+
*/
|
|
769
888
|
get destroyed () {
|
|
770
889
|
return socket.destroyed
|
|
771
890
|
},
|
|
891
|
+
/**
|
|
892
|
+
* @param {import('../core/request.js')} request
|
|
893
|
+
* @returns {boolean}
|
|
894
|
+
*/
|
|
772
895
|
busy (request) {
|
|
773
896
|
if (socket[kWriting] || socket[kReset] || socket[kBlocking]) {
|
|
774
897
|
return true
|
|
@@ -808,6 +931,9 @@ async function connectH1 (client, socket) {
|
|
|
808
931
|
}
|
|
809
932
|
}
|
|
810
933
|
|
|
934
|
+
/**
|
|
935
|
+
* @param {import('./client.js')} client
|
|
936
|
+
*/
|
|
811
937
|
function resumeH1 (client) {
|
|
812
938
|
const socket = client[kSocket]
|
|
813
939
|
|
|
@@ -843,6 +969,11 @@ function shouldSendContentLength (method) {
|
|
|
843
969
|
return method !== 'GET' && method !== 'HEAD' && method !== 'OPTIONS' && method !== 'TRACE' && method !== 'CONNECT'
|
|
844
970
|
}
|
|
845
971
|
|
|
972
|
+
/**
|
|
973
|
+
* @param {import('./client.js')} client
|
|
974
|
+
* @param {import('../core/request.js')} request
|
|
975
|
+
* @returns
|
|
976
|
+
*/
|
|
846
977
|
function writeH1 (client, request) {
|
|
847
978
|
const { method, path, host, upgrade, blocking, reset } = request
|
|
848
979
|
|
|
@@ -913,6 +1044,10 @@ function writeH1 (client, request) {
|
|
|
913
1044
|
|
|
914
1045
|
const socket = client[kSocket]
|
|
915
1046
|
|
|
1047
|
+
/**
|
|
1048
|
+
* @param {Error} [err]
|
|
1049
|
+
* @returns {void}
|
|
1050
|
+
*/
|
|
916
1051
|
const abort = (err) => {
|
|
917
1052
|
if (request.aborted || request.completed) {
|
|
918
1053
|
return
|
|
@@ -1018,6 +1153,16 @@ function writeH1 (client, request) {
|
|
|
1018
1153
|
return true
|
|
1019
1154
|
}
|
|
1020
1155
|
|
|
1156
|
+
/**
|
|
1157
|
+
* @param {AbortCallback} abort
|
|
1158
|
+
* @param {import('stream').Stream} body
|
|
1159
|
+
* @param {import('./client.js')} client
|
|
1160
|
+
* @param {import('../core/request.js')} request
|
|
1161
|
+
* @param {import('net').Socket} socket
|
|
1162
|
+
* @param {number} contentLength
|
|
1163
|
+
* @param {string} header
|
|
1164
|
+
* @param {boolean} expectsPayload
|
|
1165
|
+
*/
|
|
1021
1166
|
function writeStream (abort, body, client, request, socket, contentLength, header, expectsPayload) {
|
|
1022
1167
|
assert(contentLength !== 0 || client[kRunning] === 0, 'stream body cannot be pipelined')
|
|
1023
1168
|
|
|
@@ -1025,6 +1170,10 @@ function writeStream (abort, body, client, request, socket, contentLength, heade
|
|
|
1025
1170
|
|
|
1026
1171
|
const writer = new AsyncWriter({ abort, socket, request, contentLength, client, expectsPayload, header })
|
|
1027
1172
|
|
|
1173
|
+
/**
|
|
1174
|
+
* @param {Buffer} chunk
|
|
1175
|
+
* @returns {void}
|
|
1176
|
+
*/
|
|
1028
1177
|
const onData = function (chunk) {
|
|
1029
1178
|
if (finished) {
|
|
1030
1179
|
return
|
|
@@ -1038,6 +1187,10 @@ function writeStream (abort, body, client, request, socket, contentLength, heade
|
|
|
1038
1187
|
util.destroy(this, err)
|
|
1039
1188
|
}
|
|
1040
1189
|
}
|
|
1190
|
+
|
|
1191
|
+
/**
|
|
1192
|
+
* @returns {void}
|
|
1193
|
+
*/
|
|
1041
1194
|
const onDrain = function () {
|
|
1042
1195
|
if (finished) {
|
|
1043
1196
|
return
|
|
@@ -1047,6 +1200,10 @@ function writeStream (abort, body, client, request, socket, contentLength, heade
|
|
|
1047
1200
|
body.resume()
|
|
1048
1201
|
}
|
|
1049
1202
|
}
|
|
1203
|
+
|
|
1204
|
+
/**
|
|
1205
|
+
* @returns {void}
|
|
1206
|
+
*/
|
|
1050
1207
|
const onClose = function () {
|
|
1051
1208
|
// 'close' might be emitted *before* 'error' for
|
|
1052
1209
|
// broken streams. Wait a tick to avoid this case.
|
|
@@ -1061,6 +1218,11 @@ function writeStream (abort, body, client, request, socket, contentLength, heade
|
|
|
1061
1218
|
queueMicrotask(() => onFinished(err))
|
|
1062
1219
|
}
|
|
1063
1220
|
}
|
|
1221
|
+
|
|
1222
|
+
/**
|
|
1223
|
+
* @param {Error} [err]
|
|
1224
|
+
* @returns
|
|
1225
|
+
*/
|
|
1064
1226
|
const onFinished = function (err) {
|
|
1065
1227
|
if (finished) {
|
|
1066
1228
|
return
|
|
@@ -1121,6 +1283,24 @@ function writeStream (abort, body, client, request, socket, contentLength, heade
|
|
|
1121
1283
|
}
|
|
1122
1284
|
}
|
|
1123
1285
|
|
|
1286
|
+
/**
|
|
1287
|
+
* @typedef AbortCallback
|
|
1288
|
+
* @type {Function}
|
|
1289
|
+
* @param {Error} [err]
|
|
1290
|
+
* @returns {void}
|
|
1291
|
+
*/
|
|
1292
|
+
|
|
1293
|
+
/**
|
|
1294
|
+
* @param {AbortCallback} abort
|
|
1295
|
+
* @param {Uint8Array|null} body
|
|
1296
|
+
* @param {import('./client.js')} client
|
|
1297
|
+
* @param {import('../core/request.js')} request
|
|
1298
|
+
* @param {import('net').Socket} socket
|
|
1299
|
+
* @param {number} contentLength
|
|
1300
|
+
* @param {string} header
|
|
1301
|
+
* @param {boolean} expectsPayload
|
|
1302
|
+
* @returns {void}
|
|
1303
|
+
*/
|
|
1124
1304
|
function writeBuffer (abort, body, client, request, socket, contentLength, header, expectsPayload) {
|
|
1125
1305
|
try {
|
|
1126
1306
|
if (!body) {
|
|
@@ -1151,6 +1331,17 @@ function writeBuffer (abort, body, client, request, socket, contentLength, heade
|
|
|
1151
1331
|
}
|
|
1152
1332
|
}
|
|
1153
1333
|
|
|
1334
|
+
/**
|
|
1335
|
+
* @param {AbortCallback} abort
|
|
1336
|
+
* @param {Blob} body
|
|
1337
|
+
* @param {import('./client.js')} client
|
|
1338
|
+
* @param {import('../core/request.js')} request
|
|
1339
|
+
* @param {import('net').Socket} socket
|
|
1340
|
+
* @param {number} contentLength
|
|
1341
|
+
* @param {string} header
|
|
1342
|
+
* @param {boolean} expectsPayload
|
|
1343
|
+
* @returns {Promise<void>}
|
|
1344
|
+
*/
|
|
1154
1345
|
async function writeBlob (abort, body, client, request, socket, contentLength, header, expectsPayload) {
|
|
1155
1346
|
assert(contentLength === body.size, 'blob body must have content length')
|
|
1156
1347
|
|
|
@@ -1179,6 +1370,17 @@ async function writeBlob (abort, body, client, request, socket, contentLength, h
|
|
|
1179
1370
|
}
|
|
1180
1371
|
}
|
|
1181
1372
|
|
|
1373
|
+
/**
|
|
1374
|
+
* @param {AbortCallback} abort
|
|
1375
|
+
* @param {Iterable} body
|
|
1376
|
+
* @param {import('./client.js')} client
|
|
1377
|
+
* @param {import('../core/request.js')} request
|
|
1378
|
+
* @param {import('net').Socket} socket
|
|
1379
|
+
* @param {number} contentLength
|
|
1380
|
+
* @param {string} header
|
|
1381
|
+
* @param {boolean} expectsPayload
|
|
1382
|
+
* @returns {Promise<void>}
|
|
1383
|
+
*/
|
|
1182
1384
|
async function writeIterable (abort, body, client, request, socket, contentLength, header, expectsPayload) {
|
|
1183
1385
|
assert(contentLength !== 0 || client[kRunning] === 0, 'iterator body cannot be pipelined')
|
|
1184
1386
|
|
|
@@ -1229,6 +1431,17 @@ async function writeIterable (abort, body, client, request, socket, contentLengt
|
|
|
1229
1431
|
}
|
|
1230
1432
|
|
|
1231
1433
|
class AsyncWriter {
|
|
1434
|
+
/**
|
|
1435
|
+
*
|
|
1436
|
+
* @param {object} arg
|
|
1437
|
+
* @param {AbortCallback} arg.abort
|
|
1438
|
+
* @param {import('net').Socket} arg.socket
|
|
1439
|
+
* @param {import('../core/request.js')} arg.request
|
|
1440
|
+
* @param {number} arg.contentLength
|
|
1441
|
+
* @param {import('./client.js')} arg.client
|
|
1442
|
+
* @param {boolean} arg.expectsPayload
|
|
1443
|
+
* @param {string} arg.header
|
|
1444
|
+
*/
|
|
1232
1445
|
constructor ({ abort, socket, request, contentLength, client, expectsPayload, header }) {
|
|
1233
1446
|
this.socket = socket
|
|
1234
1447
|
this.request = request
|
|
@@ -1242,6 +1455,10 @@ class AsyncWriter {
|
|
|
1242
1455
|
socket[kWriting] = true
|
|
1243
1456
|
}
|
|
1244
1457
|
|
|
1458
|
+
/**
|
|
1459
|
+
* @param {Buffer} chunk
|
|
1460
|
+
* @returns
|
|
1461
|
+
*/
|
|
1245
1462
|
write (chunk) {
|
|
1246
1463
|
const { socket, request, contentLength, client, bytesWritten, expectsPayload, header } = this
|
|
1247
1464
|
|
|
@@ -1305,6 +1522,9 @@ class AsyncWriter {
|
|
|
1305
1522
|
return ret
|
|
1306
1523
|
}
|
|
1307
1524
|
|
|
1525
|
+
/**
|
|
1526
|
+
* @returns {void}
|
|
1527
|
+
*/
|
|
1308
1528
|
end () {
|
|
1309
1529
|
const { socket, contentLength, client, bytesWritten, expectsPayload, header, request } = this
|
|
1310
1530
|
request.onRequestSent()
|
|
@@ -1352,6 +1572,10 @@ class AsyncWriter {
|
|
|
1352
1572
|
client[kResume]()
|
|
1353
1573
|
}
|
|
1354
1574
|
|
|
1575
|
+
/**
|
|
1576
|
+
* @param {Error} [err]
|
|
1577
|
+
* @returns {void}
|
|
1578
|
+
*/
|
|
1355
1579
|
destroy (err) {
|
|
1356
1580
|
const { socket, client, abort } = this
|
|
1357
1581
|
|
|
@@ -281,7 +281,7 @@ function writeH2 (client, request) {
|
|
|
281
281
|
}
|
|
282
282
|
|
|
283
283
|
// We do not destroy the socket as we can continue using the session
|
|
284
|
-
// the stream
|
|
284
|
+
// the stream gets destroyed and the session remains to create new streams
|
|
285
285
|
util.destroy(body, err)
|
|
286
286
|
}
|
|
287
287
|
|