@openclaw/discord 2026.6.8 → 2026.6.9
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/dist/action-runtime-api.js +1 -1
- package/dist/{api-BmXlcjYW.js → api-4GFMoWu0.js} +4 -1
- package/dist/api.js +15 -15
- package/dist/{approval-handler.runtime-B3gyUd-L.js → approval-handler.runtime-20qhf0uH.js} +3 -3
- package/dist/{audit-BlfewK04.js → audit-CCffO6o7.js} +3 -3
- package/dist/{channel-actions-BnPHwCZ_.js → channel-actions-DDT9kJXw.js} +12 -6
- package/dist/{channel-actions.runtime-DX5iW6ut.js → channel-actions.runtime-CfMUtfAv.js} +5 -5
- package/dist/{channel-b0hY1EJw.js → channel-fEBKaO2Q.js} +28 -20
- package/dist/channel-plugin-api.js +1 -1
- package/dist/{channel.setup-By5cfELZ.js → channel.setup-DRJiHe7I.js} +2 -3
- package/dist/{components-D-CYw0-b.js → components-CXEorOhu.js} +1 -1
- package/dist/{conversation-identity-CKzQAqFF.js → conversation-identity-BvlP-djn.js} +2 -2
- package/dist/{directory-config-Bu7FYOsl.js → directory-config-Bg8bulWB.js} +1 -1
- package/dist/directory-contract-api.js +1 -1
- package/dist/{directory-live-LjENjK6L.js → directory-live-BAJw6kS2.js} +2 -2
- package/dist/{handle-action.guild-admin-BS2qnhXF.js → handle-action.guild-admin-RxnJFLgU.js} +14 -9
- package/dist/index.js +1 -1
- package/dist/{manager.runtime-BU1vkOeO.js → manager.runtime-Bh5X0o8P.js} +12 -4
- package/dist/{message-handler-CQVkXHMN.js → message-handler-Dg3DRD0e.js} +6 -6
- package/dist/{message-handler.preflight-DAnLOeDA.js → message-handler.preflight-CcexCYuy.js} +10 -10
- package/dist/{message-handler.process-Dp5NQT05.js → message-handler.process-CN8bVDxj.js} +37 -45
- package/dist/{message-utils-Bx993JLN.js → message-utils-ConlUKCU.js} +1 -1
- package/dist/{outbound-adapter-CmN7ao1t.js → outbound-adapter-XuMiR77A.js} +6 -6
- package/dist/{pluralkit-SYmlmerw.js → pluralkit-o6s-EP9g.js} +4 -2
- package/dist/{probe-2MdGjUAf.js → probe-CxnDikWm.js} +5 -2
- package/dist/{probe.runtime-J927koKG.js → probe.runtime-DLFkSDVB.js} +1 -1
- package/dist/{provider-DrScDA1p.js → provider-4VG5CvC-.js} +98 -69
- package/dist/{provider-session.runtime-DXTzSYOJ.js → provider-session.runtime-ChdHgGCo.js} +3 -3
- package/dist/provider.runtime-B4QuZl_o.js +2 -0
- package/dist/{resolve-allowlist-common-B3p7cT8F.js → resolve-allowlist-common-BDpBb8dF.js} +1 -1
- package/dist/{resolve-channels-Rautpk8n.js → resolve-channels-DpM2v0Am.js} +3 -3
- package/dist/{resolve-users-Bw7vvtsi.js → resolve-users-Dl6np4pH.js} +3 -3
- package/dist/{runtime-C80YEJ7Z.js → runtime-CkdyyjTb.js} +24 -10
- package/dist/runtime-api.actions.js +2 -2
- package/dist/runtime-api.js +19 -19
- package/dist/runtime-api.lookup.js +5 -5
- package/dist/runtime-api.monitor-9pShEBWs.js +6 -0
- package/dist/runtime-api.monitor.js +4 -4
- package/dist/runtime-api.send.js +5 -5
- package/dist/runtime-api.threads.js +3 -3
- package/dist/{send-zGsXF-up.js → send-CIhsDMqs.js} +8 -5
- package/dist/{send.components-ktzrUTkt.js → send.components-DxoGyTkn.js} +4 -4
- package/dist/{send.outbound-C8oC51um.js → send.outbound-DaUyYuZa.js} +53 -10
- package/dist/{send.receipt-DsQWEQ2O.js → send.receipt-De_2iEWU.js} +2 -24
- package/dist/{send.shared-Dvo2ZCVG.js → send.shared-gtgBGDuV.js} +13 -5
- package/dist/session-binding-contract-api.js +1 -1
- package/dist/setup-plugin-api.js +1 -1
- package/dist/{subagent-hooks-kjrWDeDg.js → subagent-hooks-DPCipg2M.js} +2 -2
- package/dist/subagent-hooks-api.js +1 -1
- package/dist/{system-events-CvU3Aduf.js → system-events-4vmuyaBF.js} +1 -1
- package/dist/{target-resolver-DMPTzuo7.js → target-resolver-CVrOhQyC.js} +2 -2
- package/dist/targets-CRGgRKs7.js +3 -0
- package/dist/{thread-bindings-DO32M2kW.js → thread-bindings-D2SBj6F8.js} +4 -4
- package/dist/{thread-bindings.discord-api-304M1PMr.js → thread-bindings.discord-api-C7STOVXm.js} +4 -4
- package/dist/{thread-bindings.manager-C9YT7wF2.js → thread-bindings.manager-CN4MIGoJ.js} +3 -3
- package/dist/{transcripts-source-Chy2OrO_.js → transcripts-source-39NBdNeE.js} +1 -1
- package/dist/transcripts-source-api.js +1 -1
- package/dist/{typing-BaivbXIG.js → typing-CxIYS3vQ.js} +1 -1
- package/node_modules/undici/README.md +59 -18
- package/node_modules/undici/docs/docs/GettingStarted.md +278 -0
- package/node_modules/undici/docs/docs/api/Agent.md +3 -0
- package/node_modules/undici/docs/docs/api/BalancedPool.md +1 -1
- package/node_modules/undici/docs/docs/api/Client.md +44 -5
- package/node_modules/undici/docs/docs/api/Connector.md +1 -0
- package/node_modules/undici/docs/docs/api/Cookies.md +28 -1
- package/node_modules/undici/docs/docs/api/Dispatcher.md +22 -5
- package/node_modules/undici/docs/docs/api/EnvHttpProxyAgent.md +6 -9
- package/node_modules/undici/docs/docs/api/Errors.md +12 -0
- package/node_modules/undici/docs/docs/api/EventSource.md +50 -3
- package/node_modules/undici/docs/docs/api/Fetch.md +5 -3
- package/node_modules/undici/docs/docs/api/H2CClient.md +3 -3
- package/node_modules/undici/docs/docs/api/MockAgent.md +1 -1
- package/node_modules/undici/docs/docs/api/MockCallHistory.md +1 -1
- package/node_modules/undici/docs/docs/api/Pool.md +4 -1
- package/node_modules/undici/docs/docs/api/RedirectHandler.md +4 -1
- package/node_modules/undici/docs/docs/api/RetryAgent.md +3 -3
- package/node_modules/undici/docs/docs/api/RetryHandler.md +6 -6
- package/node_modules/undici/docs/docs/api/RoundRobinPool.md +1 -1
- package/node_modules/undici/docs/docs/api/SnapshotAgent.md +3 -3
- package/node_modules/undici/docs/docs/api/Socks5ProxyAgent.md +1 -0
- package/node_modules/undici/docs/docs/api/api-lifecycle.md +4 -4
- package/node_modules/undici/lib/core/connect.js +29 -4
- package/node_modules/undici/lib/core/util.js +8 -6
- package/node_modules/undici/lib/dispatcher/client-h1.js +69 -2
- package/node_modules/undici/lib/dispatcher/client-h2.js +160 -37
- package/node_modules/undici/lib/dispatcher/client.js +36 -7
- package/node_modules/undici/lib/dispatcher/dispatcher-base.js +1 -0
- package/node_modules/undici/lib/dispatcher/proxy-agent.js +2 -1
- package/node_modules/undici/lib/dispatcher/socks5-proxy-agent.js +4 -2
- package/node_modules/undici/lib/handler/redirect-handler.js +36 -11
- package/node_modules/undici/lib/interceptor/dns.js +4 -0
- package/node_modules/undici/lib/interceptor/redirect.js +3 -3
- package/node_modules/undici/lib/mock/mock-call-history.js +1 -1
- package/node_modules/undici/lib/mock/snapshot-agent.js +9 -1
- package/node_modules/undici/lib/util/cache.js +8 -2
- package/node_modules/undici/lib/web/cookies/parse.js +17 -25
- package/node_modules/undici/lib/web/eventsource/eventsource.js +7 -18
- package/node_modules/undici/lib/web/eventsource/util.js +32 -1
- package/node_modules/undici/lib/web/fetch/body.js +43 -0
- package/node_modules/undici/lib/web/fetch/index.js +17 -3
- package/node_modules/undici/lib/web/fetch/request.js +33 -3
- package/node_modules/undici/lib/web/websocket/receiver.js +20 -3
- package/node_modules/undici/lib/web/websocket/stream/websocketstream.js +8 -1
- package/node_modules/undici/lib/web/websocket/websocket.js +3 -1
- package/node_modules/undici/package.json +1 -1
- package/node_modules/undici/types/client.d.ts +5 -0
- package/node_modules/undici/types/connector.d.ts +1 -0
- package/node_modules/undici/types/fetch.d.ts +5 -1
- package/node_modules/undici/types/interceptors.d.ts +1 -1
- package/npm-shrinkwrap.json +7 -7
- package/package.json +5 -5
- package/dist/provider.runtime-nb-6cRoy.js +0 -2
- package/dist/runtime-api.monitor-D8KNDAd5.js +0 -6
- package/dist/targets-CKaNidbk.js +0 -3
|
@@ -57,6 +57,9 @@ const constants = require('../llhttp/constants.js')
|
|
|
57
57
|
const EMPTY_BUF = Buffer.alloc(0)
|
|
58
58
|
const FastBuffer = Buffer[Symbol.species]
|
|
59
59
|
const removeAllListeners = util.removeAllListeners
|
|
60
|
+
const kIdleSocketValidation = Symbol('kIdleSocketValidation')
|
|
61
|
+
const kIdleSocketValidationTimeout = Symbol('kIdleSocketValidationTimeout')
|
|
62
|
+
const kSocketUsed = Symbol('kSocketUsed')
|
|
60
63
|
|
|
61
64
|
let extractBody
|
|
62
65
|
|
|
@@ -371,7 +374,6 @@ class Parser {
|
|
|
371
374
|
finish () {
|
|
372
375
|
assert(currentParser === null)
|
|
373
376
|
assert(this.ptr != null)
|
|
374
|
-
assert(!this.paused)
|
|
375
377
|
|
|
376
378
|
const { llhttp } = this
|
|
377
379
|
|
|
@@ -450,6 +452,11 @@ class Parser {
|
|
|
450
452
|
return -1
|
|
451
453
|
}
|
|
452
454
|
|
|
455
|
+
if (client[kRunning] === 0) {
|
|
456
|
+
util.destroy(socket, new SocketError('bad response', util.getSocketInfo(socket)))
|
|
457
|
+
return -1
|
|
458
|
+
}
|
|
459
|
+
|
|
453
460
|
const request = client[kQueue][client[kRunningIdx]]
|
|
454
461
|
if (!request) {
|
|
455
462
|
return -1
|
|
@@ -585,6 +592,11 @@ class Parser {
|
|
|
585
592
|
return -1
|
|
586
593
|
}
|
|
587
594
|
|
|
595
|
+
if (client[kRunning] === 0) {
|
|
596
|
+
util.destroy(socket, new SocketError('bad response', util.getSocketInfo(socket)))
|
|
597
|
+
return -1
|
|
598
|
+
}
|
|
599
|
+
|
|
588
600
|
const request = client[kQueue][client[kRunningIdx]]
|
|
589
601
|
|
|
590
602
|
if (!request) {
|
|
@@ -763,6 +775,7 @@ class Parser {
|
|
|
763
775
|
request.onResponseEnd(headers)
|
|
764
776
|
|
|
765
777
|
client[kQueue][client[kRunningIdx]++] = null
|
|
778
|
+
socket[kSocketUsed] = client[kPending] === 0
|
|
766
779
|
|
|
767
780
|
if (socket[kWriting]) {
|
|
768
781
|
assert(client[kRunning] === 0)
|
|
@@ -839,6 +852,9 @@ function connectH1 (client, socket) {
|
|
|
839
852
|
socket[kWriting] = false
|
|
840
853
|
socket[kReset] = false
|
|
841
854
|
socket[kBlocking] = false
|
|
855
|
+
socket[kIdleSocketValidation] = 0
|
|
856
|
+
socket[kIdleSocketValidationTimeout] = null
|
|
857
|
+
socket[kSocketUsed] = false
|
|
842
858
|
socket[kParser] = new Parser(client, socket, llhttpInstance)
|
|
843
859
|
|
|
844
860
|
util.addListener(socket, 'error', onHttpSocketError)
|
|
@@ -881,7 +897,7 @@ function connectH1 (client, socket) {
|
|
|
881
897
|
* @returns {boolean}
|
|
882
898
|
*/
|
|
883
899
|
busy (request) {
|
|
884
|
-
if (socket[kWriting] || socket[kReset] || socket[kBlocking]) {
|
|
900
|
+
if (socket[kWriting] || socket[kReset] || socket[kBlocking] || socket[kIdleSocketValidation] === 1) {
|
|
885
901
|
return true
|
|
886
902
|
}
|
|
887
903
|
|
|
@@ -961,6 +977,8 @@ function onHttpSocketEnd () {
|
|
|
961
977
|
function onHttpSocketClose () {
|
|
962
978
|
const parser = this[kParser]
|
|
963
979
|
|
|
980
|
+
clearIdleSocketValidation(this)
|
|
981
|
+
|
|
964
982
|
if (parser) {
|
|
965
983
|
if (!this[kError] && parser.statusCode && !parser.shouldKeepAlive) {
|
|
966
984
|
this[kError] = parser.finish() || this[kError]
|
|
@@ -1007,6 +1025,28 @@ function onSocketClose () {
|
|
|
1007
1025
|
this[kClosed] = true
|
|
1008
1026
|
}
|
|
1009
1027
|
|
|
1028
|
+
function clearIdleSocketValidation (socket) {
|
|
1029
|
+
if (socket[kIdleSocketValidationTimeout]) {
|
|
1030
|
+
clearTimeout(socket[kIdleSocketValidationTimeout])
|
|
1031
|
+
socket[kIdleSocketValidationTimeout] = null
|
|
1032
|
+
}
|
|
1033
|
+
|
|
1034
|
+
socket[kIdleSocketValidation] = 0
|
|
1035
|
+
}
|
|
1036
|
+
|
|
1037
|
+
function scheduleIdleSocketValidation (client, socket) {
|
|
1038
|
+
socket[kIdleSocketValidation] = 1
|
|
1039
|
+
socket[kIdleSocketValidationTimeout] = setTimeout(() => {
|
|
1040
|
+
socket[kIdleSocketValidationTimeout] = null
|
|
1041
|
+
socket[kIdleSocketValidation] = 2
|
|
1042
|
+
|
|
1043
|
+
if (client[kSocket] === socket && !socket.destroyed) {
|
|
1044
|
+
client[kResume]()
|
|
1045
|
+
}
|
|
1046
|
+
}, 0)
|
|
1047
|
+
socket[kIdleSocketValidationTimeout].unref?.()
|
|
1048
|
+
}
|
|
1049
|
+
|
|
1010
1050
|
/**
|
|
1011
1051
|
* @param {import('./client.js')} client
|
|
1012
1052
|
*/
|
|
@@ -1024,6 +1064,32 @@ function resumeH1 (client) {
|
|
|
1024
1064
|
socket[kNoRef] = false
|
|
1025
1065
|
}
|
|
1026
1066
|
|
|
1067
|
+
if (client[kRunning] === 0 && client[kPending] > 0 && socket[kSocketUsed]) {
|
|
1068
|
+
if (socket[kIdleSocketValidation] === 0) {
|
|
1069
|
+
scheduleIdleSocketValidation(client, socket)
|
|
1070
|
+
socket[kParser].readMore()
|
|
1071
|
+
if (socket.destroyed) {
|
|
1072
|
+
return
|
|
1073
|
+
}
|
|
1074
|
+
return
|
|
1075
|
+
}
|
|
1076
|
+
|
|
1077
|
+
if (socket[kIdleSocketValidation] === 1) {
|
|
1078
|
+
socket[kParser].readMore()
|
|
1079
|
+
if (socket.destroyed) {
|
|
1080
|
+
return
|
|
1081
|
+
}
|
|
1082
|
+
return
|
|
1083
|
+
}
|
|
1084
|
+
}
|
|
1085
|
+
|
|
1086
|
+
if (client[kRunning] === 0) {
|
|
1087
|
+
socket[kParser].readMore()
|
|
1088
|
+
if (socket.destroyed) {
|
|
1089
|
+
return
|
|
1090
|
+
}
|
|
1091
|
+
}
|
|
1092
|
+
|
|
1027
1093
|
if (client[kSize] === 0) {
|
|
1028
1094
|
if (socket[kParser].timeoutType !== TIMEOUT_KEEP_ALIVE) {
|
|
1029
1095
|
socket[kParser].setTimeout(client[kKeepAliveTimeoutValue], TIMEOUT_KEEP_ALIVE)
|
|
@@ -1122,6 +1188,7 @@ function writeH1 (client, request) {
|
|
|
1122
1188
|
}
|
|
1123
1189
|
|
|
1124
1190
|
const socket = client[kSocket]
|
|
1191
|
+
clearIdleSocketValidation(socket)
|
|
1125
1192
|
|
|
1126
1193
|
/**
|
|
1127
1194
|
* @param {Error} [err]
|
|
@@ -8,7 +8,9 @@ const {
|
|
|
8
8
|
RequestAbortedError,
|
|
9
9
|
SocketError,
|
|
10
10
|
InformationalError,
|
|
11
|
-
InvalidArgumentError
|
|
11
|
+
InvalidArgumentError,
|
|
12
|
+
HeadersTimeoutError,
|
|
13
|
+
BodyTimeoutError
|
|
12
14
|
} = require('../core/errors.js')
|
|
13
15
|
const {
|
|
14
16
|
kUrl,
|
|
@@ -33,6 +35,8 @@ const {
|
|
|
33
35
|
kSize,
|
|
34
36
|
kHTTPContext,
|
|
35
37
|
kClosed,
|
|
38
|
+
kKeepAliveDefaultTimeout,
|
|
39
|
+
kHeadersTimeout,
|
|
36
40
|
kBodyTimeout,
|
|
37
41
|
kEnableConnectProtocol,
|
|
38
42
|
kRemoteSettings,
|
|
@@ -81,6 +85,29 @@ function getGoAwayError (session, errorCode) {
|
|
|
81
85
|
: new SocketError(`HTTP/2: "GOAWAY" frame received with code ${errorCode}`, util.getSocketInfo(session[kSocket])))
|
|
82
86
|
}
|
|
83
87
|
|
|
88
|
+
function resetHttp2Session (session, err) {
|
|
89
|
+
const client = session[kClient]
|
|
90
|
+
const socket = session[kSocket]
|
|
91
|
+
|
|
92
|
+
if (client[kHTTP2Session] === session) {
|
|
93
|
+
client[kSocket] = null
|
|
94
|
+
client[kHTTPContext] = null
|
|
95
|
+
client[kHTTP2Session] = null
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if (socket != null && socket[kError] == null) {
|
|
99
|
+
socket[kError] = err
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (!session.closed && !session.destroyed) {
|
|
103
|
+
try {
|
|
104
|
+
session.destroy(err)
|
|
105
|
+
} catch {}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
util.destroy(socket, err)
|
|
109
|
+
}
|
|
110
|
+
|
|
84
111
|
function getGoAwayPendingIdx (client, lastStreamID) {
|
|
85
112
|
const maxAcceptedStreamID = Number.isInteger(lastStreamID) ? lastStreamID : Number.MAX_SAFE_INTEGER
|
|
86
113
|
|
|
@@ -122,6 +149,25 @@ function clearRequestStream (request) {
|
|
|
122
149
|
cleanup?.(stream)
|
|
123
150
|
}
|
|
124
151
|
|
|
152
|
+
function requeueUnsentRequest (client, request) {
|
|
153
|
+
client[kQueue].splice(client[kPendingIdx] + 1, 0, request)
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function completeRequest (client, request, resetPendingIdx = false) {
|
|
157
|
+
const index = client[kQueue].indexOf(request, client[kRunningIdx])
|
|
158
|
+
|
|
159
|
+
if (index === -1 || index >= client[kPendingIdx]) {
|
|
160
|
+
return
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
client[kQueue].splice(index, 1)
|
|
164
|
+
client[kPendingIdx]--
|
|
165
|
+
|
|
166
|
+
if (resetPendingIdx && client[kPendingIdx] < client[kRunningIdx]) {
|
|
167
|
+
client[kPendingIdx] = client[kRunningIdx]
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
125
171
|
function canRetryRequestAfterGoAway (request) {
|
|
126
172
|
const { body } = request
|
|
127
173
|
|
|
@@ -161,6 +207,7 @@ function connectH2 (client, socket) {
|
|
|
161
207
|
session[kClient] = client
|
|
162
208
|
session[kSocket] = socket
|
|
163
209
|
session[kHTTP2SessionState] = {
|
|
210
|
+
idleTimeout: null,
|
|
164
211
|
ping: {
|
|
165
212
|
interval: client[kPingInterval] === 0 ? null : setInterval(onHttp2SendPing, client[kPingInterval], session).unref()
|
|
166
213
|
}
|
|
@@ -249,10 +296,10 @@ function connectH2 (client, socket) {
|
|
|
249
296
|
if (client[kRunning] > 0) {
|
|
250
297
|
// We are already processing requests
|
|
251
298
|
|
|
252
|
-
//
|
|
253
|
-
//
|
|
254
|
-
//
|
|
255
|
-
|
|
299
|
+
// Unlike HTTP/1.1 pipelining, HTTP/2 multiplexes requests on
|
|
300
|
+
// independent streams, so non-idempotent requests can be dispatched
|
|
301
|
+
// concurrently. Retry eligibility is handled by stream/session error
|
|
302
|
+
// handling instead of by serializing all non-idempotent requests.
|
|
256
303
|
// Don't dispatch an upgrade until all preceding requests have completed.
|
|
257
304
|
// Possibly, we do not have remote settings confirmed yet.
|
|
258
305
|
if ((request.upgrade === 'websocket' || request.method === 'CONNECT') && session[kRemoteSettings] === false) return true
|
|
@@ -278,16 +325,66 @@ function connectH2 (client, socket) {
|
|
|
278
325
|
|
|
279
326
|
function resumeH2 (client) {
|
|
280
327
|
const socket = client[kSocket]
|
|
328
|
+
const session = client[kHTTP2Session]
|
|
281
329
|
|
|
282
330
|
if (socket?.destroyed === false) {
|
|
283
331
|
if (client[kSize] === 0 || client[kMaxConcurrentStreams] === 0) {
|
|
284
332
|
socket.unref()
|
|
285
|
-
|
|
333
|
+
session.unref()
|
|
286
334
|
} else {
|
|
287
335
|
socket.ref()
|
|
288
|
-
|
|
336
|
+
session.ref()
|
|
289
337
|
}
|
|
338
|
+
|
|
339
|
+
if (client[kSize] === 0 && session[kOpenStreams] === 0) {
|
|
340
|
+
setHttp2IdleTimeout(session)
|
|
341
|
+
} else {
|
|
342
|
+
clearHttp2IdleTimeout(session)
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
function clearHttp2IdleTimeout (session) {
|
|
348
|
+
const state = session[kHTTP2SessionState]
|
|
349
|
+
|
|
350
|
+
if (state?.idleTimeout != null) {
|
|
351
|
+
clearTimeout(state.idleTimeout)
|
|
352
|
+
state.idleTimeout = null
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
function setHttp2IdleTimeout (session) {
|
|
357
|
+
const client = session[kClient]
|
|
358
|
+
|
|
359
|
+
if (client[kHTTP2Session] !== session || session.closed || session.destroyed) {
|
|
360
|
+
return
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
if (session[kOpenStreams] !== 0 || client[kSize] !== 0) {
|
|
364
|
+
clearHttp2IdleTimeout(session)
|
|
365
|
+
return
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
const state = session[kHTTP2SessionState]
|
|
369
|
+
if (state.idleTimeout == null) {
|
|
370
|
+
state.idleTimeout = setTimeout(onHttp2SessionIdleTimeout, client[kKeepAliveDefaultTimeout], session).unref()
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
function onHttp2SessionIdleTimeout (session) {
|
|
375
|
+
const client = session[kClient]
|
|
376
|
+
const socket = session[kSocket]
|
|
377
|
+
const state = session[kHTTP2SessionState]
|
|
378
|
+
|
|
379
|
+
state.idleTimeout = null
|
|
380
|
+
|
|
381
|
+
if (client[kHTTP2Session] !== session || session[kOpenStreams] !== 0 || client[kSize] !== 0 || session.closed || session.destroyed) {
|
|
382
|
+
return
|
|
290
383
|
}
|
|
384
|
+
|
|
385
|
+
const err = new InformationalError('socket idle timeout')
|
|
386
|
+
socket[kError] = err
|
|
387
|
+
util.destroy(socket, err)
|
|
291
388
|
}
|
|
292
389
|
|
|
293
390
|
function applyConnectionWindowSize (connectionWindowSize) {
|
|
@@ -415,6 +512,8 @@ function onHttp2SessionGoAway (errorCode, lastStreamID) {
|
|
|
415
512
|
client[kHTTP2Session] = null
|
|
416
513
|
}
|
|
417
514
|
|
|
515
|
+
clearHttp2IdleTimeout(this)
|
|
516
|
+
|
|
418
517
|
if (!this.closed && !this.destroyed) {
|
|
419
518
|
this.close()
|
|
420
519
|
}
|
|
@@ -437,6 +536,8 @@ function onHttp2SessionClose () {
|
|
|
437
536
|
client[kHTTP2Session] = null
|
|
438
537
|
}
|
|
439
538
|
|
|
539
|
+
clearHttp2IdleTimeout(this)
|
|
540
|
+
|
|
440
541
|
if (state.ping.interval != null) {
|
|
441
542
|
clearInterval(state.ping.interval)
|
|
442
543
|
state.ping.interval = null
|
|
@@ -449,7 +550,9 @@ function onHttp2SessionClose () {
|
|
|
449
550
|
const requests = client[kQueue].splice(client[kRunningIdx])
|
|
450
551
|
for (let i = 0; i < requests.length; i++) {
|
|
451
552
|
const request = requests[i]
|
|
452
|
-
|
|
553
|
+
if (request != null) {
|
|
554
|
+
util.errorRequest(client, request, err)
|
|
555
|
+
}
|
|
453
556
|
}
|
|
454
557
|
}
|
|
455
558
|
}
|
|
@@ -512,6 +615,7 @@ function closeStreamSession (stream) {
|
|
|
512
615
|
session[kOpenStreams] -= 1
|
|
513
616
|
if (session[kOpenStreams] === 0) {
|
|
514
617
|
session.unref()
|
|
618
|
+
setHttp2IdleTimeout(session)
|
|
515
619
|
}
|
|
516
620
|
}
|
|
517
621
|
|
|
@@ -526,6 +630,19 @@ function onUpgradeStreamClose () {
|
|
|
526
630
|
}
|
|
527
631
|
|
|
528
632
|
function onRequestStreamClose () {
|
|
633
|
+
const state = this[kRequestStreamState]
|
|
634
|
+
|
|
635
|
+
if (state) {
|
|
636
|
+
// Release the stream first so request references are cleared,
|
|
637
|
+
// then complete the response with trailers if available.
|
|
638
|
+
releaseRequestStream(this)
|
|
639
|
+
|
|
640
|
+
if (state.pendingEnd && !state.request.aborted && !state.request.completed) {
|
|
641
|
+
state.request.onResponseEnd(state.trailers || {})
|
|
642
|
+
state.finalizeRequest()
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
|
|
529
646
|
this.off('data', onData)
|
|
530
647
|
this.off('error', noop)
|
|
531
648
|
closeStreamSession(this)
|
|
@@ -629,7 +746,7 @@ function onUpgradeStreamEnd () {
|
|
|
629
746
|
|
|
630
747
|
function onUpgradeStreamTimeout () {
|
|
631
748
|
const state = this[kRequestStreamState]
|
|
632
|
-
failUpgradeStream(state, new InformationalError(`HTTP/2: "stream timeout after ${state.
|
|
749
|
+
failUpgradeStream(state, new InformationalError(`HTTP/2: "stream timeout after ${state.headersTimeout}"`))
|
|
633
750
|
}
|
|
634
751
|
|
|
635
752
|
function onUpgradeResponse (headers, _flags) {
|
|
@@ -654,7 +771,7 @@ function onUpgradeResponse (headers, _flags) {
|
|
|
654
771
|
}
|
|
655
772
|
|
|
656
773
|
function setupUpgradeStream (stream, state) {
|
|
657
|
-
const { request,
|
|
774
|
+
const { request, headersTimeout, session } = state
|
|
658
775
|
|
|
659
776
|
stream[kHTTP2Stream] = true
|
|
660
777
|
stream[kHTTP2Session] = session
|
|
@@ -668,12 +785,14 @@ function setupUpgradeStream (stream, state) {
|
|
|
668
785
|
stream.on('timeout', onUpgradeStreamTimeout)
|
|
669
786
|
stream.once('close', onUpgradeStreamClose)
|
|
670
787
|
|
|
788
|
+
clearHttp2IdleTimeout(session)
|
|
671
789
|
++session[kOpenStreams]
|
|
672
|
-
stream.setTimeout(
|
|
790
|
+
stream.setTimeout(headersTimeout)
|
|
673
791
|
}
|
|
674
792
|
|
|
675
793
|
function writeH2 (client, request) {
|
|
676
|
-
const
|
|
794
|
+
const headersTimeout = request.headersTimeout ?? client[kHeadersTimeout]
|
|
795
|
+
const bodyTimeout = request.bodyTimeout ?? client[kBodyTimeout]
|
|
677
796
|
const session = client[kHTTP2Session]
|
|
678
797
|
const { method, path, host, upgrade, expectContinue, signal, protocol, headers: reqHeaders } = request
|
|
679
798
|
let { body } = request
|
|
@@ -698,11 +817,7 @@ function writeH2 (client, request) {
|
|
|
698
817
|
}
|
|
699
818
|
|
|
700
819
|
requestFinalized = true
|
|
701
|
-
client
|
|
702
|
-
|
|
703
|
-
if (resetPendingIdx) {
|
|
704
|
-
client[kPendingIdx] = client[kRunningIdx]
|
|
705
|
-
}
|
|
820
|
+
completeRequest(client, request, resetPendingIdx)
|
|
706
821
|
|
|
707
822
|
client[kResume]()
|
|
708
823
|
}
|
|
@@ -736,8 +851,14 @@ function writeH2 (client, request) {
|
|
|
736
851
|
try {
|
|
737
852
|
return session.request(headers, options)
|
|
738
853
|
} catch (err) {
|
|
739
|
-
if (err?.code
|
|
740
|
-
|
|
854
|
+
if (err?.code === 'ERR_HTTP2_INVALID_SESSION') {
|
|
855
|
+
const wrappedErr = new SocketError(err.message, util.getSocketInfo(session[kSocket]))
|
|
856
|
+
wrappedErr.cause = err
|
|
857
|
+
session[kError] = wrappedErr
|
|
858
|
+
resetHttp2Session(session, wrappedErr)
|
|
859
|
+
requeueUnsentRequest(client, request)
|
|
860
|
+
|
|
861
|
+
return null
|
|
741
862
|
}
|
|
742
863
|
|
|
743
864
|
const wrappedErr = new InformationalError(err.message, { cause: err })
|
|
@@ -771,7 +892,8 @@ function writeH2 (client, request) {
|
|
|
771
892
|
abort,
|
|
772
893
|
finalizeRequest,
|
|
773
894
|
request,
|
|
774
|
-
|
|
895
|
+
headersTimeout,
|
|
896
|
+
bodyTimeout,
|
|
775
897
|
responseReceived: false,
|
|
776
898
|
session,
|
|
777
899
|
stream: null
|
|
@@ -912,7 +1034,8 @@ function writeH2 (client, request) {
|
|
|
912
1034
|
expectsPayload,
|
|
913
1035
|
finalizeRequest,
|
|
914
1036
|
request,
|
|
915
|
-
|
|
1037
|
+
headersTimeout,
|
|
1038
|
+
bodyTimeout,
|
|
916
1039
|
responseReceived: false,
|
|
917
1040
|
session,
|
|
918
1041
|
stream: null
|
|
@@ -929,11 +1052,11 @@ function writeH2 (client, request) {
|
|
|
929
1052
|
stream[kHTTP2Stream] = true
|
|
930
1053
|
stream[kRequestStreamState] = state
|
|
931
1054
|
state.stream = stream
|
|
932
|
-
bindRequestToStream(request, stream, null)
|
|
933
1055
|
|
|
934
1056
|
// Increment counter as we have new streams open
|
|
1057
|
+
clearHttp2IdleTimeout(session)
|
|
935
1058
|
++session[kOpenStreams]
|
|
936
|
-
stream.setTimeout(
|
|
1059
|
+
stream.setTimeout(headersTimeout)
|
|
937
1060
|
|
|
938
1061
|
stream[kHTTP2Session] = session
|
|
939
1062
|
stream.once('close', onRequestStreamClose)
|
|
@@ -1017,6 +1140,7 @@ function onResponse (headers) {
|
|
|
1017
1140
|
delete headers[HTTP2_HEADER_STATUS]
|
|
1018
1141
|
request.onResponseStarted()
|
|
1019
1142
|
state.responseReceived = true
|
|
1143
|
+
stream.setTimeout(state.bodyTimeout)
|
|
1020
1144
|
|
|
1021
1145
|
// Due to the stream nature, it is possible we face a race condition
|
|
1022
1146
|
// where the stream has been assigned, but the request has been aborted
|
|
@@ -1042,14 +1166,14 @@ function onEnd () {
|
|
|
1042
1166
|
|
|
1043
1167
|
stream.off('end', onEnd)
|
|
1044
1168
|
|
|
1045
|
-
|
|
1046
|
-
//
|
|
1169
|
+
// If we received a response, this is a normal completion.
|
|
1170
|
+
// Defer actual completion to onRequestStreamClose so that
|
|
1171
|
+
// onTrailers (which may fire after 'end' on Windows) can
|
|
1172
|
+
// store trailers first.
|
|
1047
1173
|
if (state.responseReceived) {
|
|
1048
1174
|
if (!request.aborted && !request.completed) {
|
|
1049
|
-
|
|
1175
|
+
state.pendingEnd = true
|
|
1050
1176
|
}
|
|
1051
|
-
|
|
1052
|
-
state.finalizeRequest()
|
|
1053
1177
|
} else {
|
|
1054
1178
|
// Stream ended without receiving a response - this is an error
|
|
1055
1179
|
// (e.g., server destroyed the stream before sending headers)
|
|
@@ -1062,8 +1186,6 @@ function onError (err) {
|
|
|
1062
1186
|
const state = stream[kRequestStreamState]
|
|
1063
1187
|
|
|
1064
1188
|
stream.off('error', onError)
|
|
1065
|
-
|
|
1066
|
-
releaseRequestStream(stream)
|
|
1067
1189
|
state.abort(err)
|
|
1068
1190
|
}
|
|
1069
1191
|
|
|
@@ -1072,8 +1194,6 @@ function onFrameError (type, code) {
|
|
|
1072
1194
|
const state = stream[kRequestStreamState]
|
|
1073
1195
|
|
|
1074
1196
|
stream.off('frameError', onFrameError)
|
|
1075
|
-
|
|
1076
|
-
releaseRequestStream(stream)
|
|
1077
1197
|
state.abort(new InformationalError(`HTTP/2: "frameError" received - type ${type}, code ${code}`))
|
|
1078
1198
|
}
|
|
1079
1199
|
|
|
@@ -1085,9 +1205,12 @@ function onTimeout () {
|
|
|
1085
1205
|
const stream = this
|
|
1086
1206
|
const state = stream[kRequestStreamState]
|
|
1087
1207
|
|
|
1088
|
-
|
|
1208
|
+
// Remove self so timeout doesn't fire again after we handle it
|
|
1209
|
+
stream.off('timeout', onTimeout)
|
|
1089
1210
|
|
|
1090
|
-
const err =
|
|
1211
|
+
const err = state.responseReceived
|
|
1212
|
+
? new BodyTimeoutError(`HTTP/2: "stream timeout after ${state.bodyTimeout}"`)
|
|
1213
|
+
: new HeadersTimeoutError(`HTTP/2: "headers timeout after ${state.headersTimeout}"`)
|
|
1091
1214
|
state.abort(err)
|
|
1092
1215
|
}
|
|
1093
1216
|
|
|
@@ -1097,14 +1220,14 @@ function onTrailers (trailers) {
|
|
|
1097
1220
|
const { request } = state
|
|
1098
1221
|
|
|
1099
1222
|
stream.off('trailers', onTrailers)
|
|
1223
|
+
stream.off('data', onData)
|
|
1100
1224
|
|
|
1101
1225
|
if (request.aborted || request.completed) {
|
|
1102
1226
|
return
|
|
1103
1227
|
}
|
|
1104
1228
|
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
state.finalizeRequest()
|
|
1229
|
+
// Store trailers for onRequestStreamClose to use when completing
|
|
1230
|
+
state.trailers = trailers
|
|
1108
1231
|
}
|
|
1109
1232
|
|
|
1110
1233
|
function writeBodyH2 () {
|
|
@@ -76,6 +76,18 @@ function getPipelining (client) {
|
|
|
76
76
|
return client[kPipelining] ?? client[kHTTPContext]?.defaultPipelining ?? 1
|
|
77
77
|
}
|
|
78
78
|
|
|
79
|
+
// Protocol-aware dispatch ceiling. h1 RFC7230 pipelining is unrelated to h2
|
|
80
|
+
// stream multiplexing — over h2 the ceiling is the (server-confirmed)
|
|
81
|
+
// maxConcurrentStreams. Before a context is attached we use the h1
|
|
82
|
+
// pipelining factor; once h2 attaches the queued requests can drain in
|
|
83
|
+
// one batch up to maxConcurrentStreams.
|
|
84
|
+
function getMaxConcurrent (client) {
|
|
85
|
+
if (client[kHTTPContext]?.version === 'h2') {
|
|
86
|
+
return client[kMaxConcurrentStreams]
|
|
87
|
+
}
|
|
88
|
+
return getPipelining(client)
|
|
89
|
+
}
|
|
90
|
+
|
|
79
91
|
/**
|
|
80
92
|
* @type {import('../../types/client.js').default}
|
|
81
93
|
*/
|
|
@@ -326,10 +338,17 @@ class Client extends DispatcherBase {
|
|
|
326
338
|
}
|
|
327
339
|
|
|
328
340
|
get [kBusy] () {
|
|
341
|
+
// The `kPending > 0` check below is the gate Pool uses to decide whether
|
|
342
|
+
// to spin up an additional Client. For h1 that fan-out is correct —
|
|
343
|
+
// each socket only handles one pipelined request at a time. Once an h2
|
|
344
|
+
// context is attached we want concurrent dispatches to multiplex onto
|
|
345
|
+
// the shared session, so suppress that signal in the h2 case.
|
|
346
|
+
const allowsMux = this[kHTTPContext]?.version === 'h2'
|
|
347
|
+
|
|
329
348
|
return Boolean(
|
|
330
349
|
this[kHTTPContext]?.busy(null) ||
|
|
331
|
-
(this[kSize] >= (
|
|
332
|
-
this[kPending] > 0
|
|
350
|
+
(this[kSize] >= (getMaxConcurrent(this) || 1)) ||
|
|
351
|
+
(this[kPending] > 0 && !allowsMux)
|
|
333
352
|
)
|
|
334
353
|
}
|
|
335
354
|
|
|
@@ -376,7 +395,9 @@ class Client extends DispatcherBase {
|
|
|
376
395
|
const requests = this[kQueue].splice(this[kPendingIdx])
|
|
377
396
|
for (let i = 0; i < requests.length; i++) {
|
|
378
397
|
const request = requests[i]
|
|
379
|
-
|
|
398
|
+
if (request != null) {
|
|
399
|
+
util.errorRequest(this, request, err)
|
|
400
|
+
}
|
|
380
401
|
}
|
|
381
402
|
|
|
382
403
|
const callback = () => {
|
|
@@ -415,7 +436,9 @@ function onError (client, err) {
|
|
|
415
436
|
|
|
416
437
|
for (let i = 0; i < requests.length; i++) {
|
|
417
438
|
const request = requests[i]
|
|
418
|
-
|
|
439
|
+
if (request != null) {
|
|
440
|
+
util.errorRequest(client, request, err)
|
|
441
|
+
}
|
|
419
442
|
}
|
|
420
443
|
assert(client[kSize] === 0)
|
|
421
444
|
}
|
|
@@ -549,9 +572,15 @@ function handleConnectError (client, err, { host, hostname, protocol, port }) {
|
|
|
549
572
|
}
|
|
550
573
|
|
|
551
574
|
if (err.code === 'ERR_TLS_CERT_ALTNAME_INVALID') {
|
|
552
|
-
|
|
575
|
+
const running = client[kQueue].splice(client[kRunningIdx], client[kRunning])
|
|
576
|
+
client[kPendingIdx] = client[kRunningIdx]
|
|
577
|
+
|
|
578
|
+
for (let i = 0; i < running.length; i++) {
|
|
579
|
+
util.errorRequest(client, running[i], err)
|
|
580
|
+
}
|
|
581
|
+
|
|
553
582
|
while (client[kPending] > 0 && client[kQueue][client[kPendingIdx]].servername === client[kServerName]) {
|
|
554
|
-
const request = client[kQueue]
|
|
583
|
+
const request = client[kQueue].splice(client[kPendingIdx], 1)[0]
|
|
555
584
|
util.errorRequest(client, request, err)
|
|
556
585
|
}
|
|
557
586
|
} else {
|
|
@@ -616,7 +645,7 @@ function _resume (client, sync) {
|
|
|
616
645
|
return
|
|
617
646
|
}
|
|
618
647
|
|
|
619
|
-
if (client[kRunning] >= (
|
|
648
|
+
if (client[kRunning] >= (getMaxConcurrent(client) || 1)) {
|
|
620
649
|
return
|
|
621
650
|
}
|
|
622
651
|
|
|
@@ -147,7 +147,8 @@ class ProxyAgent extends DispatcherBase {
|
|
|
147
147
|
factory: agentFactory,
|
|
148
148
|
username: opts.username || username,
|
|
149
149
|
password: opts.password || password,
|
|
150
|
-
proxyTls: opts.proxyTls
|
|
150
|
+
proxyTls: opts.proxyTls,
|
|
151
|
+
requestTls: opts.requestTls
|
|
151
152
|
})
|
|
152
153
|
}
|
|
153
154
|
|
|
@@ -19,6 +19,7 @@ const kProxyAuth = Symbol('proxy auth')
|
|
|
19
19
|
const kProxyProtocol = Symbol('proxy protocol')
|
|
20
20
|
const kPools = Symbol('pools')
|
|
21
21
|
const kConnector = Symbol('connector')
|
|
22
|
+
const kRequestTls = Symbol('request tls settings')
|
|
22
23
|
|
|
23
24
|
// Static flag to ensure warning is only emitted once per process
|
|
24
25
|
let experimentalWarningEmitted = false
|
|
@@ -53,6 +54,7 @@ class Socks5ProxyAgent extends DispatcherBase {
|
|
|
53
54
|
this[kProxyUrl] = url
|
|
54
55
|
this[kProxyHeaders] = options.headers || {}
|
|
55
56
|
this[kProxyProtocol] = options.proxyTls ? 'https:' : 'http:'
|
|
57
|
+
this[kRequestTls] = options.requestTls
|
|
56
58
|
|
|
57
59
|
// Extract auth from URL or options
|
|
58
60
|
this[kProxyAuth] = {
|
|
@@ -205,9 +207,9 @@ class Socks5ProxyAgent extends DispatcherBase {
|
|
|
205
207
|
}
|
|
206
208
|
debug('upgrading to TLS')
|
|
207
209
|
finalSocket = tls.connect({
|
|
210
|
+
...this[kRequestTls],
|
|
208
211
|
socket,
|
|
209
|
-
servername: targetHost
|
|
210
|
-
...connectOpts.tls || {}
|
|
212
|
+
servername: this[kRequestTls]?.servername || targetHost
|
|
211
213
|
})
|
|
212
214
|
|
|
213
215
|
const tlsReady = Promise.withResolvers()
|