deepv-code 1.0.182 → 1.0.185
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/bundle/dvcode.js +757 -753
- package/package.json +1 -1
- package/bundle/assets/help/README.md +0 -113
- package/bundle/assets/sounds/README.md +0 -74
- package/bundle/node_modules/undici/LICENSE +0 -21
- package/bundle/node_modules/undici/README.md +0 -472
- package/bundle/node_modules/undici/docs/docs/api/Agent.md +0 -83
- package/bundle/node_modules/undici/docs/docs/api/BalancedPool.md +0 -99
- package/bundle/node_modules/undici/docs/docs/api/CacheStorage.md +0 -30
- package/bundle/node_modules/undici/docs/docs/api/CacheStore.md +0 -151
- package/bundle/node_modules/undici/docs/docs/api/Client.md +0 -281
- package/bundle/node_modules/undici/docs/docs/api/ClientStats.md +0 -27
- package/bundle/node_modules/undici/docs/docs/api/Connector.md +0 -115
- package/bundle/node_modules/undici/docs/docs/api/ContentType.md +0 -57
- package/bundle/node_modules/undici/docs/docs/api/Cookies.md +0 -101
- package/bundle/node_modules/undici/docs/docs/api/Debug.md +0 -62
- package/bundle/node_modules/undici/docs/docs/api/DiagnosticsChannel.md +0 -204
- package/bundle/node_modules/undici/docs/docs/api/Dispatcher.md +0 -1200
- package/bundle/node_modules/undici/docs/docs/api/EnvHttpProxyAgent.md +0 -159
- package/bundle/node_modules/undici/docs/docs/api/Errors.md +0 -49
- package/bundle/node_modules/undici/docs/docs/api/EventSource.md +0 -45
- package/bundle/node_modules/undici/docs/docs/api/Fetch.md +0 -52
- package/bundle/node_modules/undici/docs/docs/api/H2CClient.md +0 -262
- package/bundle/node_modules/undici/docs/docs/api/MockAgent.md +0 -603
- package/bundle/node_modules/undici/docs/docs/api/MockCallHistory.md +0 -197
- package/bundle/node_modules/undici/docs/docs/api/MockCallHistoryLog.md +0 -43
- package/bundle/node_modules/undici/docs/docs/api/MockClient.md +0 -77
- package/bundle/node_modules/undici/docs/docs/api/MockErrors.md +0 -12
- package/bundle/node_modules/undici/docs/docs/api/MockPool.md +0 -548
- package/bundle/node_modules/undici/docs/docs/api/Pool.md +0 -84
- package/bundle/node_modules/undici/docs/docs/api/PoolStats.md +0 -35
- package/bundle/node_modules/undici/docs/docs/api/ProxyAgent.md +0 -227
- package/bundle/node_modules/undici/docs/docs/api/RedirectHandler.md +0 -96
- package/bundle/node_modules/undici/docs/docs/api/RetryAgent.md +0 -45
- package/bundle/node_modules/undici/docs/docs/api/RetryHandler.md +0 -117
- package/bundle/node_modules/undici/docs/docs/api/Util.md +0 -25
- package/bundle/node_modules/undici/docs/docs/api/WebSocket.md +0 -85
- package/bundle/node_modules/undici/docs/docs/api/api-lifecycle.md +0 -91
- package/bundle/node_modules/undici/docs/docs/best-practices/client-certificate.md +0 -64
- package/bundle/node_modules/undici/docs/docs/best-practices/mocking-request.md +0 -190
- package/bundle/node_modules/undici/docs/docs/best-practices/proxy.md +0 -127
- package/bundle/node_modules/undici/docs/docs/best-practices/writing-tests.md +0 -20
- package/bundle/node_modules/undici/index-fetch.js +0 -35
- package/bundle/node_modules/undici/index.d.ts +0 -3
- package/bundle/node_modules/undici/index.js +0 -183
- package/bundle/node_modules/undici/lib/api/abort-signal.js +0 -59
- package/bundle/node_modules/undici/lib/api/api-connect.js +0 -110
- package/bundle/node_modules/undici/lib/api/api-pipeline.js +0 -252
- package/bundle/node_modules/undici/lib/api/api-request.js +0 -199
- package/bundle/node_modules/undici/lib/api/api-stream.js +0 -209
- package/bundle/node_modules/undici/lib/api/api-upgrade.js +0 -110
- package/bundle/node_modules/undici/lib/api/index.js +0 -7
- package/bundle/node_modules/undici/lib/api/readable.js +0 -558
- package/bundle/node_modules/undici/lib/api/util.js +0 -95
- package/bundle/node_modules/undici/lib/cache/memory-cache-store.js +0 -234
- package/bundle/node_modules/undici/lib/cache/sqlite-cache-store.js +0 -461
- package/bundle/node_modules/undici/lib/core/connect.js +0 -164
- package/bundle/node_modules/undici/lib/core/constants.js +0 -143
- package/bundle/node_modules/undici/lib/core/diagnostics.js +0 -196
- package/bundle/node_modules/undici/lib/core/errors.js +0 -244
- package/bundle/node_modules/undici/lib/core/request.js +0 -397
- package/bundle/node_modules/undici/lib/core/symbols.js +0 -68
- package/bundle/node_modules/undici/lib/core/tree.js +0 -160
- package/bundle/node_modules/undici/lib/core/util.js +0 -988
- package/bundle/node_modules/undici/lib/dispatcher/agent.js +0 -135
- package/bundle/node_modules/undici/lib/dispatcher/balanced-pool.js +0 -206
- package/bundle/node_modules/undici/lib/dispatcher/client-h1.js +0 -1615
- package/bundle/node_modules/undici/lib/dispatcher/client-h2.js +0 -798
- package/bundle/node_modules/undici/lib/dispatcher/client.js +0 -614
- package/bundle/node_modules/undici/lib/dispatcher/dispatcher-base.js +0 -161
- package/bundle/node_modules/undici/lib/dispatcher/dispatcher.js +0 -48
- package/bundle/node_modules/undici/lib/dispatcher/env-http-proxy-agent.js +0 -151
- package/bundle/node_modules/undici/lib/dispatcher/fixed-queue.js +0 -159
- package/bundle/node_modules/undici/lib/dispatcher/h2c-client.js +0 -122
- package/bundle/node_modules/undici/lib/dispatcher/pool-base.js +0 -191
- package/bundle/node_modules/undici/lib/dispatcher/pool.js +0 -118
- package/bundle/node_modules/undici/lib/dispatcher/proxy-agent.js +0 -275
- package/bundle/node_modules/undici/lib/dispatcher/retry-agent.js +0 -35
- package/bundle/node_modules/undici/lib/global.js +0 -32
- package/bundle/node_modules/undici/lib/handler/cache-handler.js +0 -448
- package/bundle/node_modules/undici/lib/handler/cache-revalidation-handler.js +0 -124
- package/bundle/node_modules/undici/lib/handler/decorator-handler.js +0 -67
- package/bundle/node_modules/undici/lib/handler/redirect-handler.js +0 -227
- package/bundle/node_modules/undici/lib/handler/retry-handler.js +0 -342
- package/bundle/node_modules/undici/lib/handler/unwrap-handler.js +0 -96
- package/bundle/node_modules/undici/lib/handler/wrap-handler.js +0 -95
- package/bundle/node_modules/undici/lib/interceptor/cache.js +0 -372
- package/bundle/node_modules/undici/lib/interceptor/dns.js +0 -432
- package/bundle/node_modules/undici/lib/interceptor/dump.js +0 -111
- package/bundle/node_modules/undici/lib/interceptor/redirect.js +0 -21
- package/bundle/node_modules/undici/lib/interceptor/response-error.js +0 -95
- package/bundle/node_modules/undici/lib/interceptor/retry.js +0 -19
- package/bundle/node_modules/undici/lib/llhttp/.gitkeep +0 -0
- package/bundle/node_modules/undici/lib/llhttp/constants.d.ts +0 -97
- package/bundle/node_modules/undici/lib/llhttp/constants.js +0 -498
- package/bundle/node_modules/undici/lib/llhttp/constants.js.map +0 -1
- package/bundle/node_modules/undici/lib/llhttp/llhttp-wasm.js +0 -15
- package/bundle/node_modules/undici/lib/llhttp/llhttp_simd-wasm.js +0 -15
- package/bundle/node_modules/undici/lib/llhttp/utils.d.ts +0 -2
- package/bundle/node_modules/undici/lib/llhttp/utils.js +0 -15
- package/bundle/node_modules/undici/lib/llhttp/utils.js.map +0 -1
- package/bundle/node_modules/undici/lib/mock/mock-agent.js +0 -224
- package/bundle/node_modules/undici/lib/mock/mock-call-history.js +0 -248
- package/bundle/node_modules/undici/lib/mock/mock-client.js +0 -64
- package/bundle/node_modules/undici/lib/mock/mock-errors.js +0 -19
- package/bundle/node_modules/undici/lib/mock/mock-interceptor.js +0 -209
- package/bundle/node_modules/undici/lib/mock/mock-pool.js +0 -64
- package/bundle/node_modules/undici/lib/mock/mock-symbols.js +0 -31
- package/bundle/node_modules/undici/lib/mock/mock-utils.js +0 -433
- package/bundle/node_modules/undici/lib/mock/pending-interceptors-formatter.js +0 -43
- package/bundle/node_modules/undici/lib/util/cache.js +0 -368
- package/bundle/node_modules/undici/lib/util/date.js +0 -259
- package/bundle/node_modules/undici/lib/util/stats.js +0 -32
- package/bundle/node_modules/undici/lib/util/timers.js +0 -423
- package/bundle/node_modules/undici/lib/web/cache/cache.js +0 -862
- package/bundle/node_modules/undici/lib/web/cache/cachestorage.js +0 -152
- package/bundle/node_modules/undici/lib/web/cache/util.js +0 -45
- package/bundle/node_modules/undici/lib/web/cookies/constants.js +0 -12
- package/bundle/node_modules/undici/lib/web/cookies/index.js +0 -199
- package/bundle/node_modules/undici/lib/web/cookies/parse.js +0 -322
- package/bundle/node_modules/undici/lib/web/cookies/util.js +0 -282
- package/bundle/node_modules/undici/lib/web/eventsource/eventsource-stream.js +0 -399
- package/bundle/node_modules/undici/lib/web/eventsource/eventsource.js +0 -484
- package/bundle/node_modules/undici/lib/web/eventsource/util.js +0 -37
- package/bundle/node_modules/undici/lib/web/fetch/LICENSE +0 -21
- package/bundle/node_modules/undici/lib/web/fetch/body.js +0 -532
- package/bundle/node_modules/undici/lib/web/fetch/constants.js +0 -131
- package/bundle/node_modules/undici/lib/web/fetch/data-url.js +0 -744
- package/bundle/node_modules/undici/lib/web/fetch/dispatcher-weakref.js +0 -46
- package/bundle/node_modules/undici/lib/web/fetch/formdata-parser.js +0 -501
- package/bundle/node_modules/undici/lib/web/fetch/formdata.js +0 -263
- package/bundle/node_modules/undici/lib/web/fetch/global.js +0 -40
- package/bundle/node_modules/undici/lib/web/fetch/headers.js +0 -719
- package/bundle/node_modules/undici/lib/web/fetch/index.js +0 -2258
- package/bundle/node_modules/undici/lib/web/fetch/request.js +0 -1099
- package/bundle/node_modules/undici/lib/web/fetch/response.js +0 -636
- package/bundle/node_modules/undici/lib/web/fetch/util.js +0 -1782
- package/bundle/node_modules/undici/lib/web/fetch/webidl.js +0 -740
- package/bundle/node_modules/undici/lib/web/websocket/connection.js +0 -325
- package/bundle/node_modules/undici/lib/web/websocket/constants.js +0 -126
- package/bundle/node_modules/undici/lib/web/websocket/events.js +0 -331
- package/bundle/node_modules/undici/lib/web/websocket/frame.js +0 -138
- package/bundle/node_modules/undici/lib/web/websocket/permessage-deflate.js +0 -70
- package/bundle/node_modules/undici/lib/web/websocket/receiver.js +0 -454
- package/bundle/node_modules/undici/lib/web/websocket/sender.js +0 -109
- package/bundle/node_modules/undici/lib/web/websocket/stream/websocketerror.js +0 -83
- package/bundle/node_modules/undici/lib/web/websocket/stream/websocketstream.js +0 -485
- package/bundle/node_modules/undici/lib/web/websocket/util.js +0 -338
- package/bundle/node_modules/undici/lib/web/websocket/websocket.js +0 -686
- package/bundle/node_modules/undici/package.json +0 -149
- package/bundle/node_modules/undici/scripts/strip-comments.js +0 -10
- package/bundle/node_modules/undici/types/README.md +0 -6
- package/bundle/node_modules/undici/types/agent.d.ts +0 -35
- package/bundle/node_modules/undici/types/api.d.ts +0 -43
- package/bundle/node_modules/undici/types/balanced-pool.d.ts +0 -29
- package/bundle/node_modules/undici/types/cache-interceptor.d.ts +0 -172
- package/bundle/node_modules/undici/types/cache.d.ts +0 -36
- package/bundle/node_modules/undici/types/client-stats.d.ts +0 -15
- package/bundle/node_modules/undici/types/client.d.ts +0 -110
- package/bundle/node_modules/undici/types/connector.d.ts +0 -34
- package/bundle/node_modules/undici/types/content-type.d.ts +0 -21
- package/bundle/node_modules/undici/types/cookies.d.ts +0 -30
- package/bundle/node_modules/undici/types/diagnostics-channel.d.ts +0 -66
- package/bundle/node_modules/undici/types/dispatcher.d.ts +0 -281
- package/bundle/node_modules/undici/types/env-http-proxy-agent.d.ts +0 -21
- package/bundle/node_modules/undici/types/errors.d.ts +0 -171
- package/bundle/node_modules/undici/types/eventsource.d.ts +0 -61
- package/bundle/node_modules/undici/types/fetch.d.ts +0 -210
- package/bundle/node_modules/undici/types/formdata.d.ts +0 -108
- package/bundle/node_modules/undici/types/global-dispatcher.d.ts +0 -9
- package/bundle/node_modules/undici/types/global-origin.d.ts +0 -7
- package/bundle/node_modules/undici/types/h2c-client.d.ts +0 -75
- package/bundle/node_modules/undici/types/handlers.d.ts +0 -15
- package/bundle/node_modules/undici/types/header.d.ts +0 -160
- package/bundle/node_modules/undici/types/index.d.ts +0 -75
- package/bundle/node_modules/undici/types/interceptors.d.ts +0 -34
- package/bundle/node_modules/undici/types/mock-agent.d.ts +0 -68
- package/bundle/node_modules/undici/types/mock-call-history.d.ts +0 -111
- package/bundle/node_modules/undici/types/mock-client.d.ts +0 -25
- package/bundle/node_modules/undici/types/mock-errors.d.ts +0 -12
- package/bundle/node_modules/undici/types/mock-interceptor.d.ts +0 -93
- package/bundle/node_modules/undici/types/mock-pool.d.ts +0 -25
- package/bundle/node_modules/undici/types/patch.d.ts +0 -29
- package/bundle/node_modules/undici/types/pool-stats.d.ts +0 -19
- package/bundle/node_modules/undici/types/pool.d.ts +0 -41
- package/bundle/node_modules/undici/types/proxy-agent.d.ts +0 -29
- package/bundle/node_modules/undici/types/readable.d.ts +0 -68
- package/bundle/node_modules/undici/types/retry-agent.d.ts +0 -8
- package/bundle/node_modules/undici/types/retry-handler.d.ts +0 -116
- package/bundle/node_modules/undici/types/util.d.ts +0 -18
- package/bundle/node_modules/undici/types/utility.d.ts +0 -7
- package/bundle/node_modules/undici/types/webidl.d.ts +0 -266
- package/bundle/node_modules/undici/types/websocket.d.ts +0 -184
|
@@ -1,798 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
const assert = require('node:assert')
|
|
4
|
-
const { pipeline } = require('node:stream')
|
|
5
|
-
const util = require('../core/util.js')
|
|
6
|
-
const {
|
|
7
|
-
RequestContentLengthMismatchError,
|
|
8
|
-
RequestAbortedError,
|
|
9
|
-
SocketError,
|
|
10
|
-
InformationalError
|
|
11
|
-
} = require('../core/errors.js')
|
|
12
|
-
const {
|
|
13
|
-
kUrl,
|
|
14
|
-
kReset,
|
|
15
|
-
kClient,
|
|
16
|
-
kRunning,
|
|
17
|
-
kPending,
|
|
18
|
-
kQueue,
|
|
19
|
-
kPendingIdx,
|
|
20
|
-
kRunningIdx,
|
|
21
|
-
kError,
|
|
22
|
-
kSocket,
|
|
23
|
-
kStrictContentLength,
|
|
24
|
-
kOnError,
|
|
25
|
-
kMaxConcurrentStreams,
|
|
26
|
-
kHTTP2Session,
|
|
27
|
-
kResume,
|
|
28
|
-
kSize,
|
|
29
|
-
kHTTPContext,
|
|
30
|
-
kClosed,
|
|
31
|
-
kBodyTimeout
|
|
32
|
-
} = require('../core/symbols.js')
|
|
33
|
-
const { channels } = require('../core/diagnostics.js')
|
|
34
|
-
|
|
35
|
-
const kOpenStreams = Symbol('open streams')
|
|
36
|
-
|
|
37
|
-
let extractBody
|
|
38
|
-
|
|
39
|
-
/** @type {import('http2')} */
|
|
40
|
-
let http2
|
|
41
|
-
try {
|
|
42
|
-
http2 = require('node:http2')
|
|
43
|
-
} catch {
|
|
44
|
-
// @ts-ignore
|
|
45
|
-
http2 = { constants: {} }
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
const {
|
|
49
|
-
constants: {
|
|
50
|
-
HTTP2_HEADER_AUTHORITY,
|
|
51
|
-
HTTP2_HEADER_METHOD,
|
|
52
|
-
HTTP2_HEADER_PATH,
|
|
53
|
-
HTTP2_HEADER_SCHEME,
|
|
54
|
-
HTTP2_HEADER_CONTENT_LENGTH,
|
|
55
|
-
HTTP2_HEADER_EXPECT,
|
|
56
|
-
HTTP2_HEADER_STATUS
|
|
57
|
-
}
|
|
58
|
-
} = http2
|
|
59
|
-
|
|
60
|
-
function parseH2Headers (headers) {
|
|
61
|
-
const result = []
|
|
62
|
-
|
|
63
|
-
for (const [name, value] of Object.entries(headers)) {
|
|
64
|
-
// h2 may concat the header value by array
|
|
65
|
-
// e.g. Set-Cookie
|
|
66
|
-
if (Array.isArray(value)) {
|
|
67
|
-
for (const subvalue of value) {
|
|
68
|
-
// we need to provide each header value of header name
|
|
69
|
-
// because the headers handler expect name-value pair
|
|
70
|
-
result.push(Buffer.from(name), Buffer.from(subvalue))
|
|
71
|
-
}
|
|
72
|
-
} else {
|
|
73
|
-
result.push(Buffer.from(name), Buffer.from(value))
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
return result
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
async function connectH2 (client, socket) {
|
|
81
|
-
client[kSocket] = socket
|
|
82
|
-
|
|
83
|
-
const session = http2.connect(client[kUrl], {
|
|
84
|
-
createConnection: () => socket,
|
|
85
|
-
peerMaxConcurrentStreams: client[kMaxConcurrentStreams],
|
|
86
|
-
settings: {
|
|
87
|
-
// TODO(metcoder95): add support for PUSH
|
|
88
|
-
enablePush: false
|
|
89
|
-
}
|
|
90
|
-
})
|
|
91
|
-
|
|
92
|
-
session[kOpenStreams] = 0
|
|
93
|
-
session[kClient] = client
|
|
94
|
-
session[kSocket] = socket
|
|
95
|
-
session[kHTTP2Session] = null
|
|
96
|
-
|
|
97
|
-
util.addListener(session, 'error', onHttp2SessionError)
|
|
98
|
-
util.addListener(session, 'frameError', onHttp2FrameError)
|
|
99
|
-
util.addListener(session, 'end', onHttp2SessionEnd)
|
|
100
|
-
util.addListener(session, 'goaway', onHttp2SessionGoAway)
|
|
101
|
-
util.addListener(session, 'close', onHttp2SessionClose)
|
|
102
|
-
|
|
103
|
-
session.unref()
|
|
104
|
-
|
|
105
|
-
client[kHTTP2Session] = session
|
|
106
|
-
socket[kHTTP2Session] = session
|
|
107
|
-
|
|
108
|
-
util.addListener(socket, 'error', onHttp2SocketError)
|
|
109
|
-
util.addListener(socket, 'end', onHttp2SocketEnd)
|
|
110
|
-
util.addListener(socket, 'close', onHttp2SocketClose)
|
|
111
|
-
|
|
112
|
-
socket[kClosed] = false
|
|
113
|
-
socket.on('close', onSocketClose)
|
|
114
|
-
|
|
115
|
-
return {
|
|
116
|
-
version: 'h2',
|
|
117
|
-
defaultPipelining: Infinity,
|
|
118
|
-
write (request) {
|
|
119
|
-
return writeH2(client, request)
|
|
120
|
-
},
|
|
121
|
-
resume () {
|
|
122
|
-
resumeH2(client)
|
|
123
|
-
},
|
|
124
|
-
destroy (err, callback) {
|
|
125
|
-
if (socket[kClosed]) {
|
|
126
|
-
queueMicrotask(callback)
|
|
127
|
-
} else {
|
|
128
|
-
socket.destroy(err).on('close', callback)
|
|
129
|
-
}
|
|
130
|
-
},
|
|
131
|
-
get destroyed () {
|
|
132
|
-
return socket.destroyed
|
|
133
|
-
},
|
|
134
|
-
busy () {
|
|
135
|
-
return false
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
function resumeH2 (client) {
|
|
141
|
-
const socket = client[kSocket]
|
|
142
|
-
|
|
143
|
-
if (socket?.destroyed === false) {
|
|
144
|
-
if (client[kSize] === 0 || client[kMaxConcurrentStreams] === 0) {
|
|
145
|
-
socket.unref()
|
|
146
|
-
client[kHTTP2Session].unref()
|
|
147
|
-
} else {
|
|
148
|
-
socket.ref()
|
|
149
|
-
client[kHTTP2Session].ref()
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
function onHttp2SessionError (err) {
|
|
155
|
-
assert(err.code !== 'ERR_TLS_CERT_ALTNAME_INVALID')
|
|
156
|
-
|
|
157
|
-
this[kSocket][kError] = err
|
|
158
|
-
this[kClient][kOnError](err)
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
function onHttp2FrameError (type, code, id) {
|
|
162
|
-
if (id === 0) {
|
|
163
|
-
const err = new InformationalError(`HTTP/2: "frameError" received - type ${type}, code ${code}`)
|
|
164
|
-
this[kSocket][kError] = err
|
|
165
|
-
this[kClient][kOnError](err)
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
function onHttp2SessionEnd () {
|
|
170
|
-
const err = new SocketError('other side closed', util.getSocketInfo(this[kSocket]))
|
|
171
|
-
this.destroy(err)
|
|
172
|
-
util.destroy(this[kSocket], err)
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
/**
|
|
176
|
-
* This is the root cause of #3011
|
|
177
|
-
* We need to handle GOAWAY frames properly, and trigger the session close
|
|
178
|
-
* along with the socket right away
|
|
179
|
-
*
|
|
180
|
-
* @this {import('http2').ClientHttp2Session}
|
|
181
|
-
* @param {number} errorCode
|
|
182
|
-
*/
|
|
183
|
-
function onHttp2SessionGoAway (errorCode) {
|
|
184
|
-
// TODO(mcollina): Verify if GOAWAY implements the spec correctly:
|
|
185
|
-
// https://datatracker.ietf.org/doc/html/rfc7540#section-6.8
|
|
186
|
-
// Specifically, we do not verify the "valid" stream id.
|
|
187
|
-
|
|
188
|
-
const err = this[kError] || new SocketError(`HTTP/2: "GOAWAY" frame received with code ${errorCode}`, util.getSocketInfo(this[kSocket]))
|
|
189
|
-
const client = this[kClient]
|
|
190
|
-
|
|
191
|
-
client[kSocket] = null
|
|
192
|
-
client[kHTTPContext] = null
|
|
193
|
-
|
|
194
|
-
// this is an HTTP2 session
|
|
195
|
-
this.close()
|
|
196
|
-
this[kHTTP2Session] = null
|
|
197
|
-
|
|
198
|
-
util.destroy(this[kSocket], err)
|
|
199
|
-
|
|
200
|
-
// Fail head of pipeline.
|
|
201
|
-
if (client[kRunningIdx] < client[kQueue].length) {
|
|
202
|
-
const request = client[kQueue][client[kRunningIdx]]
|
|
203
|
-
client[kQueue][client[kRunningIdx]++] = null
|
|
204
|
-
util.errorRequest(client, request, err)
|
|
205
|
-
client[kPendingIdx] = client[kRunningIdx]
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
assert(client[kRunning] === 0)
|
|
209
|
-
|
|
210
|
-
client.emit('disconnect', client[kUrl], [client], err)
|
|
211
|
-
client.emit('connectionError', client[kUrl], [client], err)
|
|
212
|
-
|
|
213
|
-
client[kResume]()
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
function onHttp2SessionClose () {
|
|
217
|
-
const { [kClient]: client } = this
|
|
218
|
-
const { [kSocket]: socket } = client
|
|
219
|
-
|
|
220
|
-
const err = this[kSocket][kError] || this[kError] || new SocketError('closed', util.getSocketInfo(socket))
|
|
221
|
-
|
|
222
|
-
client[kSocket] = null
|
|
223
|
-
client[kHTTPContext] = null
|
|
224
|
-
|
|
225
|
-
if (client.destroyed) {
|
|
226
|
-
assert(client[kPending] === 0)
|
|
227
|
-
|
|
228
|
-
// Fail entire queue.
|
|
229
|
-
const requests = client[kQueue].splice(client[kRunningIdx])
|
|
230
|
-
for (let i = 0; i < requests.length; i++) {
|
|
231
|
-
const request = requests[i]
|
|
232
|
-
util.errorRequest(client, request, err)
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
function onHttp2SocketClose () {
|
|
238
|
-
const err = this[kError] || new SocketError('closed', util.getSocketInfo(this))
|
|
239
|
-
|
|
240
|
-
const client = this[kHTTP2Session][kClient]
|
|
241
|
-
|
|
242
|
-
client[kSocket] = null
|
|
243
|
-
client[kHTTPContext] = null
|
|
244
|
-
|
|
245
|
-
if (this[kHTTP2Session] !== null) {
|
|
246
|
-
this[kHTTP2Session].destroy(err)
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
client[kPendingIdx] = client[kRunningIdx]
|
|
250
|
-
|
|
251
|
-
assert(client[kRunning] === 0)
|
|
252
|
-
|
|
253
|
-
client.emit('disconnect', client[kUrl], [client], err)
|
|
254
|
-
|
|
255
|
-
client[kResume]()
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
function onHttp2SocketError (err) {
|
|
259
|
-
assert(err.code !== 'ERR_TLS_CERT_ALTNAME_INVALID')
|
|
260
|
-
|
|
261
|
-
this[kError] = err
|
|
262
|
-
|
|
263
|
-
this[kClient][kOnError](err)
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
function onHttp2SocketEnd () {
|
|
267
|
-
util.destroy(this, new SocketError('other side closed', util.getSocketInfo(this)))
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
function onSocketClose () {
|
|
271
|
-
this[kClosed] = true
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
// https://www.rfc-editor.org/rfc/rfc7230#section-3.3.2
|
|
275
|
-
function shouldSendContentLength (method) {
|
|
276
|
-
return method !== 'GET' && method !== 'HEAD' && method !== 'OPTIONS' && method !== 'TRACE' && method !== 'CONNECT'
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
function writeH2 (client, request) {
|
|
280
|
-
const requestTimeout = request.bodyTimeout ?? client[kBodyTimeout]
|
|
281
|
-
const session = client[kHTTP2Session]
|
|
282
|
-
const { method, path, host, upgrade, expectContinue, signal, headers: reqHeaders } = request
|
|
283
|
-
let { body } = request
|
|
284
|
-
|
|
285
|
-
if (upgrade) {
|
|
286
|
-
util.errorRequest(client, request, new Error('Upgrade not supported for H2'))
|
|
287
|
-
return false
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
const headers = {}
|
|
291
|
-
for (let n = 0; n < reqHeaders.length; n += 2) {
|
|
292
|
-
const key = reqHeaders[n + 0]
|
|
293
|
-
const val = reqHeaders[n + 1]
|
|
294
|
-
|
|
295
|
-
if (Array.isArray(val)) {
|
|
296
|
-
for (let i = 0; i < val.length; i++) {
|
|
297
|
-
if (headers[key]) {
|
|
298
|
-
headers[key] += `, ${val[i]}`
|
|
299
|
-
} else {
|
|
300
|
-
headers[key] = val[i]
|
|
301
|
-
}
|
|
302
|
-
}
|
|
303
|
-
} else if (headers[key]) {
|
|
304
|
-
headers[key] += `, ${val}`
|
|
305
|
-
} else {
|
|
306
|
-
headers[key] = val
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
/** @type {import('node:http2').ClientHttp2Stream} */
|
|
311
|
-
let stream = null
|
|
312
|
-
|
|
313
|
-
const { hostname, port } = client[kUrl]
|
|
314
|
-
|
|
315
|
-
headers[HTTP2_HEADER_AUTHORITY] = host || `${hostname}${port ? `:${port}` : ''}`
|
|
316
|
-
headers[HTTP2_HEADER_METHOD] = method
|
|
317
|
-
|
|
318
|
-
const abort = (err) => {
|
|
319
|
-
if (request.aborted || request.completed) {
|
|
320
|
-
return
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
err = err || new RequestAbortedError()
|
|
324
|
-
|
|
325
|
-
util.errorRequest(client, request, err)
|
|
326
|
-
|
|
327
|
-
if (stream != null) {
|
|
328
|
-
// Some chunks might still come after abort,
|
|
329
|
-
// let's ignore them
|
|
330
|
-
stream.removeAllListeners('data')
|
|
331
|
-
|
|
332
|
-
// On Abort, we close the stream to send RST_STREAM frame
|
|
333
|
-
stream.close()
|
|
334
|
-
|
|
335
|
-
// We move the running index to the next request
|
|
336
|
-
client[kOnError](err)
|
|
337
|
-
client[kResume]()
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
// We do not destroy the socket as we can continue using the session
|
|
341
|
-
// the stream gets destroyed and the session remains to create new streams
|
|
342
|
-
util.destroy(body, err)
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
try {
|
|
346
|
-
// We are already connected, streams are pending.
|
|
347
|
-
// We can call on connect, and wait for abort
|
|
348
|
-
request.onConnect(abort)
|
|
349
|
-
} catch (err) {
|
|
350
|
-
util.errorRequest(client, request, err)
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
if (request.aborted) {
|
|
354
|
-
return false
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
if (method === 'CONNECT') {
|
|
358
|
-
session.ref()
|
|
359
|
-
// We are already connected, streams are pending, first request
|
|
360
|
-
// will create a new stream. We trigger a request to create the stream and wait until
|
|
361
|
-
// `ready` event is triggered
|
|
362
|
-
// We disabled endStream to allow the user to write to the stream
|
|
363
|
-
stream = session.request(headers, { endStream: false, signal })
|
|
364
|
-
|
|
365
|
-
if (!stream.pending) {
|
|
366
|
-
request.onUpgrade(null, null, stream)
|
|
367
|
-
++session[kOpenStreams]
|
|
368
|
-
client[kQueue][client[kRunningIdx]++] = null
|
|
369
|
-
} else {
|
|
370
|
-
stream.once('ready', () => {
|
|
371
|
-
request.onUpgrade(null, null, stream)
|
|
372
|
-
++session[kOpenStreams]
|
|
373
|
-
client[kQueue][client[kRunningIdx]++] = null
|
|
374
|
-
})
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
stream.once('close', () => {
|
|
378
|
-
session[kOpenStreams] -= 1
|
|
379
|
-
if (session[kOpenStreams] === 0) session.unref()
|
|
380
|
-
})
|
|
381
|
-
stream.setTimeout(requestTimeout)
|
|
382
|
-
|
|
383
|
-
return true
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
// https://tools.ietf.org/html/rfc7540#section-8.3
|
|
387
|
-
// :path and :scheme headers must be omitted when sending CONNECT
|
|
388
|
-
|
|
389
|
-
headers[HTTP2_HEADER_PATH] = path
|
|
390
|
-
headers[HTTP2_HEADER_SCHEME] = 'https'
|
|
391
|
-
|
|
392
|
-
// https://tools.ietf.org/html/rfc7231#section-4.3.1
|
|
393
|
-
// https://tools.ietf.org/html/rfc7231#section-4.3.2
|
|
394
|
-
// https://tools.ietf.org/html/rfc7231#section-4.3.5
|
|
395
|
-
|
|
396
|
-
// Sending a payload body on a request that does not
|
|
397
|
-
// expect it can cause undefined behavior on some
|
|
398
|
-
// servers and corrupt connection state. Do not
|
|
399
|
-
// re-use the connection for further requests.
|
|
400
|
-
|
|
401
|
-
const expectsPayload = (
|
|
402
|
-
method === 'PUT' ||
|
|
403
|
-
method === 'POST' ||
|
|
404
|
-
method === 'PATCH'
|
|
405
|
-
)
|
|
406
|
-
|
|
407
|
-
if (body && typeof body.read === 'function') {
|
|
408
|
-
// Try to read EOF in order to get length.
|
|
409
|
-
body.read(0)
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
let contentLength = util.bodyLength(body)
|
|
413
|
-
|
|
414
|
-
if (util.isFormDataLike(body)) {
|
|
415
|
-
extractBody ??= require('../web/fetch/body.js').extractBody
|
|
416
|
-
|
|
417
|
-
const [bodyStream, contentType] = extractBody(body)
|
|
418
|
-
headers['content-type'] = contentType
|
|
419
|
-
|
|
420
|
-
body = bodyStream.stream
|
|
421
|
-
contentLength = bodyStream.length
|
|
422
|
-
}
|
|
423
|
-
|
|
424
|
-
if (contentLength == null) {
|
|
425
|
-
contentLength = request.contentLength
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
if (contentLength === 0 || !expectsPayload) {
|
|
429
|
-
// https://tools.ietf.org/html/rfc7230#section-3.3.2
|
|
430
|
-
// A user agent SHOULD NOT send a Content-Length header field when
|
|
431
|
-
// the request message does not contain a payload body and the method
|
|
432
|
-
// semantics do not anticipate such a body.
|
|
433
|
-
|
|
434
|
-
contentLength = null
|
|
435
|
-
}
|
|
436
|
-
|
|
437
|
-
// https://github.com/nodejs/undici/issues/2046
|
|
438
|
-
// A user agent may send a Content-Length header with 0 value, this should be allowed.
|
|
439
|
-
if (shouldSendContentLength(method) && contentLength > 0 && request.contentLength != null && request.contentLength !== contentLength) {
|
|
440
|
-
if (client[kStrictContentLength]) {
|
|
441
|
-
util.errorRequest(client, request, new RequestContentLengthMismatchError())
|
|
442
|
-
return false
|
|
443
|
-
}
|
|
444
|
-
|
|
445
|
-
process.emitWarning(new RequestContentLengthMismatchError())
|
|
446
|
-
}
|
|
447
|
-
|
|
448
|
-
if (contentLength != null) {
|
|
449
|
-
assert(body, 'no body must not have content length')
|
|
450
|
-
headers[HTTP2_HEADER_CONTENT_LENGTH] = `${contentLength}`
|
|
451
|
-
}
|
|
452
|
-
|
|
453
|
-
session.ref()
|
|
454
|
-
|
|
455
|
-
if (channels.sendHeaders.hasSubscribers) {
|
|
456
|
-
let header = ''
|
|
457
|
-
for (const key in headers) {
|
|
458
|
-
header += `${key}: ${headers[key]}\r\n`
|
|
459
|
-
}
|
|
460
|
-
channels.sendHeaders.publish({ request, headers: header, socket: session[kSocket] })
|
|
461
|
-
}
|
|
462
|
-
|
|
463
|
-
// TODO(metcoder95): add support for sending trailers
|
|
464
|
-
const shouldEndStream = method === 'GET' || method === 'HEAD' || body === null
|
|
465
|
-
if (expectContinue) {
|
|
466
|
-
headers[HTTP2_HEADER_EXPECT] = '100-continue'
|
|
467
|
-
stream = session.request(headers, { endStream: shouldEndStream, signal })
|
|
468
|
-
|
|
469
|
-
stream.once('continue', writeBodyH2)
|
|
470
|
-
} else {
|
|
471
|
-
stream = session.request(headers, {
|
|
472
|
-
endStream: shouldEndStream,
|
|
473
|
-
signal
|
|
474
|
-
})
|
|
475
|
-
|
|
476
|
-
writeBodyH2()
|
|
477
|
-
}
|
|
478
|
-
|
|
479
|
-
// Increment counter as we have new streams open
|
|
480
|
-
++session[kOpenStreams]
|
|
481
|
-
stream.setTimeout(requestTimeout)
|
|
482
|
-
|
|
483
|
-
stream.once('response', headers => {
|
|
484
|
-
const { [HTTP2_HEADER_STATUS]: statusCode, ...realHeaders } = headers
|
|
485
|
-
request.onResponseStarted()
|
|
486
|
-
|
|
487
|
-
// Due to the stream nature, it is possible we face a race condition
|
|
488
|
-
// where the stream has been assigned, but the request has been aborted
|
|
489
|
-
// the request remains in-flight and headers hasn't been received yet
|
|
490
|
-
// for those scenarios, best effort is to destroy the stream immediately
|
|
491
|
-
// as there's no value to keep it open.
|
|
492
|
-
if (request.aborted) {
|
|
493
|
-
stream.removeAllListeners('data')
|
|
494
|
-
return
|
|
495
|
-
}
|
|
496
|
-
|
|
497
|
-
if (request.onHeaders(Number(statusCode), parseH2Headers(realHeaders), stream.resume.bind(stream), '') === false) {
|
|
498
|
-
stream.pause()
|
|
499
|
-
}
|
|
500
|
-
})
|
|
501
|
-
|
|
502
|
-
stream.on('data', (chunk) => {
|
|
503
|
-
if (request.onData(chunk) === false) {
|
|
504
|
-
stream.pause()
|
|
505
|
-
}
|
|
506
|
-
})
|
|
507
|
-
|
|
508
|
-
stream.once('end', (err) => {
|
|
509
|
-
stream.removeAllListeners('data')
|
|
510
|
-
// When state is null, it means we haven't consumed body and the stream still do not have
|
|
511
|
-
// a state.
|
|
512
|
-
// Present specially when using pipeline or stream
|
|
513
|
-
if (stream.state?.state == null || stream.state.state < 6) {
|
|
514
|
-
// Do not complete the request if it was aborted
|
|
515
|
-
// Not prone to happen for as safety net to avoid race conditions with 'trailers'
|
|
516
|
-
if (!request.aborted && !request.completed) {
|
|
517
|
-
request.onComplete({})
|
|
518
|
-
}
|
|
519
|
-
|
|
520
|
-
client[kQueue][client[kRunningIdx]++] = null
|
|
521
|
-
client[kResume]()
|
|
522
|
-
} else {
|
|
523
|
-
// Stream is closed or half-closed-remote (6), decrement counter and cleanup
|
|
524
|
-
// It does not have sense to continue working with the stream as we do not
|
|
525
|
-
// have yet RST_STREAM support on client-side
|
|
526
|
-
--session[kOpenStreams]
|
|
527
|
-
if (session[kOpenStreams] === 0) {
|
|
528
|
-
session.unref()
|
|
529
|
-
}
|
|
530
|
-
|
|
531
|
-
abort(err ?? new InformationalError('HTTP/2: stream half-closed (remote)'))
|
|
532
|
-
client[kQueue][client[kRunningIdx]++] = null
|
|
533
|
-
client[kPendingIdx] = client[kRunningIdx]
|
|
534
|
-
client[kResume]()
|
|
535
|
-
}
|
|
536
|
-
})
|
|
537
|
-
|
|
538
|
-
stream.once('close', () => {
|
|
539
|
-
stream.removeAllListeners('data')
|
|
540
|
-
session[kOpenStreams] -= 1
|
|
541
|
-
if (session[kOpenStreams] === 0) {
|
|
542
|
-
session.unref()
|
|
543
|
-
}
|
|
544
|
-
})
|
|
545
|
-
|
|
546
|
-
stream.once('error', function (err) {
|
|
547
|
-
stream.removeAllListeners('data')
|
|
548
|
-
abort(err)
|
|
549
|
-
})
|
|
550
|
-
|
|
551
|
-
stream.once('frameError', (type, code) => {
|
|
552
|
-
stream.removeAllListeners('data')
|
|
553
|
-
abort(new InformationalError(`HTTP/2: "frameError" received - type ${type}, code ${code}`))
|
|
554
|
-
})
|
|
555
|
-
|
|
556
|
-
stream.on('aborted', () => {
|
|
557
|
-
stream.removeAllListeners('data')
|
|
558
|
-
})
|
|
559
|
-
|
|
560
|
-
stream.on('timeout', () => {
|
|
561
|
-
const err = new InformationalError(`HTTP/2: "stream timeout after ${requestTimeout}"`)
|
|
562
|
-
stream.removeAllListeners('data')
|
|
563
|
-
session[kOpenStreams] -= 1
|
|
564
|
-
|
|
565
|
-
if (session[kOpenStreams] === 0) {
|
|
566
|
-
session.unref()
|
|
567
|
-
}
|
|
568
|
-
|
|
569
|
-
abort(err)
|
|
570
|
-
})
|
|
571
|
-
|
|
572
|
-
stream.once('trailers', trailers => {
|
|
573
|
-
if (request.aborted || request.completed) {
|
|
574
|
-
return
|
|
575
|
-
}
|
|
576
|
-
|
|
577
|
-
request.onComplete(trailers)
|
|
578
|
-
})
|
|
579
|
-
|
|
580
|
-
return true
|
|
581
|
-
|
|
582
|
-
function writeBodyH2 () {
|
|
583
|
-
/* istanbul ignore else: assertion */
|
|
584
|
-
if (!body || contentLength === 0) {
|
|
585
|
-
writeBuffer(
|
|
586
|
-
abort,
|
|
587
|
-
stream,
|
|
588
|
-
null,
|
|
589
|
-
client,
|
|
590
|
-
request,
|
|
591
|
-
client[kSocket],
|
|
592
|
-
contentLength,
|
|
593
|
-
expectsPayload
|
|
594
|
-
)
|
|
595
|
-
} else if (util.isBuffer(body)) {
|
|
596
|
-
writeBuffer(
|
|
597
|
-
abort,
|
|
598
|
-
stream,
|
|
599
|
-
body,
|
|
600
|
-
client,
|
|
601
|
-
request,
|
|
602
|
-
client[kSocket],
|
|
603
|
-
contentLength,
|
|
604
|
-
expectsPayload
|
|
605
|
-
)
|
|
606
|
-
} else if (util.isBlobLike(body)) {
|
|
607
|
-
if (typeof body.stream === 'function') {
|
|
608
|
-
writeIterable(
|
|
609
|
-
abort,
|
|
610
|
-
stream,
|
|
611
|
-
body.stream(),
|
|
612
|
-
client,
|
|
613
|
-
request,
|
|
614
|
-
client[kSocket],
|
|
615
|
-
contentLength,
|
|
616
|
-
expectsPayload
|
|
617
|
-
)
|
|
618
|
-
} else {
|
|
619
|
-
writeBlob(
|
|
620
|
-
abort,
|
|
621
|
-
stream,
|
|
622
|
-
body,
|
|
623
|
-
client,
|
|
624
|
-
request,
|
|
625
|
-
client[kSocket],
|
|
626
|
-
contentLength,
|
|
627
|
-
expectsPayload
|
|
628
|
-
)
|
|
629
|
-
}
|
|
630
|
-
} else if (util.isStream(body)) {
|
|
631
|
-
writeStream(
|
|
632
|
-
abort,
|
|
633
|
-
client[kSocket],
|
|
634
|
-
expectsPayload,
|
|
635
|
-
stream,
|
|
636
|
-
body,
|
|
637
|
-
client,
|
|
638
|
-
request,
|
|
639
|
-
contentLength
|
|
640
|
-
)
|
|
641
|
-
} else if (util.isIterable(body)) {
|
|
642
|
-
writeIterable(
|
|
643
|
-
abort,
|
|
644
|
-
stream,
|
|
645
|
-
body,
|
|
646
|
-
client,
|
|
647
|
-
request,
|
|
648
|
-
client[kSocket],
|
|
649
|
-
contentLength,
|
|
650
|
-
expectsPayload
|
|
651
|
-
)
|
|
652
|
-
} else {
|
|
653
|
-
assert(false)
|
|
654
|
-
}
|
|
655
|
-
}
|
|
656
|
-
}
|
|
657
|
-
|
|
658
|
-
function writeBuffer (abort, h2stream, body, client, request, socket, contentLength, expectsPayload) {
|
|
659
|
-
try {
|
|
660
|
-
if (body != null && util.isBuffer(body)) {
|
|
661
|
-
assert(contentLength === body.byteLength, 'buffer body must have content length')
|
|
662
|
-
h2stream.cork()
|
|
663
|
-
h2stream.write(body)
|
|
664
|
-
h2stream.uncork()
|
|
665
|
-
h2stream.end()
|
|
666
|
-
|
|
667
|
-
request.onBodySent(body)
|
|
668
|
-
}
|
|
669
|
-
|
|
670
|
-
if (!expectsPayload) {
|
|
671
|
-
socket[kReset] = true
|
|
672
|
-
}
|
|
673
|
-
|
|
674
|
-
request.onRequestSent()
|
|
675
|
-
client[kResume]()
|
|
676
|
-
} catch (error) {
|
|
677
|
-
abort(error)
|
|
678
|
-
}
|
|
679
|
-
}
|
|
680
|
-
|
|
681
|
-
function writeStream (abort, socket, expectsPayload, h2stream, body, client, request, contentLength) {
|
|
682
|
-
assert(contentLength !== 0 || client[kRunning] === 0, 'stream body cannot be pipelined')
|
|
683
|
-
|
|
684
|
-
// For HTTP/2, is enough to pipe the stream
|
|
685
|
-
const pipe = pipeline(
|
|
686
|
-
body,
|
|
687
|
-
h2stream,
|
|
688
|
-
(err) => {
|
|
689
|
-
if (err) {
|
|
690
|
-
util.destroy(pipe, err)
|
|
691
|
-
abort(err)
|
|
692
|
-
} else {
|
|
693
|
-
util.removeAllListeners(pipe)
|
|
694
|
-
request.onRequestSent()
|
|
695
|
-
|
|
696
|
-
if (!expectsPayload) {
|
|
697
|
-
socket[kReset] = true
|
|
698
|
-
}
|
|
699
|
-
|
|
700
|
-
client[kResume]()
|
|
701
|
-
}
|
|
702
|
-
}
|
|
703
|
-
)
|
|
704
|
-
|
|
705
|
-
util.addListener(pipe, 'data', onPipeData)
|
|
706
|
-
|
|
707
|
-
function onPipeData (chunk) {
|
|
708
|
-
request.onBodySent(chunk)
|
|
709
|
-
}
|
|
710
|
-
}
|
|
711
|
-
|
|
712
|
-
async function writeBlob (abort, h2stream, body, client, request, socket, contentLength, expectsPayload) {
|
|
713
|
-
assert(contentLength === body.size, 'blob body must have content length')
|
|
714
|
-
|
|
715
|
-
try {
|
|
716
|
-
if (contentLength != null && contentLength !== body.size) {
|
|
717
|
-
throw new RequestContentLengthMismatchError()
|
|
718
|
-
}
|
|
719
|
-
|
|
720
|
-
const buffer = Buffer.from(await body.arrayBuffer())
|
|
721
|
-
|
|
722
|
-
h2stream.cork()
|
|
723
|
-
h2stream.write(buffer)
|
|
724
|
-
h2stream.uncork()
|
|
725
|
-
h2stream.end()
|
|
726
|
-
|
|
727
|
-
request.onBodySent(buffer)
|
|
728
|
-
request.onRequestSent()
|
|
729
|
-
|
|
730
|
-
if (!expectsPayload) {
|
|
731
|
-
socket[kReset] = true
|
|
732
|
-
}
|
|
733
|
-
|
|
734
|
-
client[kResume]()
|
|
735
|
-
} catch (err) {
|
|
736
|
-
abort(err)
|
|
737
|
-
}
|
|
738
|
-
}
|
|
739
|
-
|
|
740
|
-
async function writeIterable (abort, h2stream, body, client, request, socket, contentLength, expectsPayload) {
|
|
741
|
-
assert(contentLength !== 0 || client[kRunning] === 0, 'iterator body cannot be pipelined')
|
|
742
|
-
|
|
743
|
-
let callback = null
|
|
744
|
-
function onDrain () {
|
|
745
|
-
if (callback) {
|
|
746
|
-
const cb = callback
|
|
747
|
-
callback = null
|
|
748
|
-
cb()
|
|
749
|
-
}
|
|
750
|
-
}
|
|
751
|
-
|
|
752
|
-
const waitForDrain = () => new Promise((resolve, reject) => {
|
|
753
|
-
assert(callback === null)
|
|
754
|
-
|
|
755
|
-
if (socket[kError]) {
|
|
756
|
-
reject(socket[kError])
|
|
757
|
-
} else {
|
|
758
|
-
callback = resolve
|
|
759
|
-
}
|
|
760
|
-
})
|
|
761
|
-
|
|
762
|
-
h2stream
|
|
763
|
-
.on('close', onDrain)
|
|
764
|
-
.on('drain', onDrain)
|
|
765
|
-
|
|
766
|
-
try {
|
|
767
|
-
// It's up to the user to somehow abort the async iterable.
|
|
768
|
-
for await (const chunk of body) {
|
|
769
|
-
if (socket[kError]) {
|
|
770
|
-
throw socket[kError]
|
|
771
|
-
}
|
|
772
|
-
|
|
773
|
-
const res = h2stream.write(chunk)
|
|
774
|
-
request.onBodySent(chunk)
|
|
775
|
-
if (!res) {
|
|
776
|
-
await waitForDrain()
|
|
777
|
-
}
|
|
778
|
-
}
|
|
779
|
-
|
|
780
|
-
h2stream.end()
|
|
781
|
-
|
|
782
|
-
request.onRequestSent()
|
|
783
|
-
|
|
784
|
-
if (!expectsPayload) {
|
|
785
|
-
socket[kReset] = true
|
|
786
|
-
}
|
|
787
|
-
|
|
788
|
-
client[kResume]()
|
|
789
|
-
} catch (err) {
|
|
790
|
-
abort(err)
|
|
791
|
-
} finally {
|
|
792
|
-
h2stream
|
|
793
|
-
.off('close', onDrain)
|
|
794
|
-
.off('drain', onDrain)
|
|
795
|
-
}
|
|
796
|
-
}
|
|
797
|
-
|
|
798
|
-
module.exports = connectH2
|