@openclaw/discord 2026.6.33 → 2026.6.35
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-CjnGBhM3.js → api-1GXlSrYP.js} +42 -21
- package/dist/api.js +14 -14
- package/dist/{approval-handler.runtime-BWPQrzpP.js → approval-handler.runtime-Dv4p7REU.js} +3 -3
- package/dist/{audit-BwJ_2OjL.js → audit-DEVi9nIs.js} +3 -3
- package/dist/{channel-Ddnonoy4.js → channel-CQIRiosn.js} +15 -15
- package/dist/{channel-actions-CwmIqnYN.js → channel-actions-JziPEcBU.js} +2 -2
- package/dist/{channel-actions.runtime-DvpTfaJ4.js → channel-actions.runtime-D7L47LY3.js} +5 -5
- package/dist/channel-plugin-api.js +1 -1
- package/dist/{channel.setup-glZ5Y98a.js → channel.setup-oMeR19Cc.js} +2 -2
- package/dist/{components-j6lTZBsT.js → components-_s5UPJqU.js} +1 -1
- package/dist/{conversation-identity-36FFBwm5.js → conversation-identity-B0k94-bz.js} +2 -2
- package/dist/{directory-config-BYMFzL29.js → directory-config-CD1svkyN.js} +1 -1
- package/dist/directory-contract-api.js +1 -1
- package/dist/{directory-live-9JtJCiu8.js → directory-live-DBTsSRxl.js} +5 -5
- package/dist/{handle-action.guild-admin-xxGYrp-I.js → handle-action.guild-admin-CYIFMxh-.js} +2 -2
- package/dist/index.js +1 -1
- package/dist/{manager.runtime-BK6cf2Zu.js → manager.runtime-BZVdGX2d.js} +17 -9
- package/dist/{message-handler-BqpJIavO.js → message-handler-DZd9Bpq8.js} +7 -6
- package/dist/{message-handler.preflight-C90MxCcv.js → message-handler.preflight-Axv9J9EO.js} +12 -11
- package/dist/{message-handler.process-CeQ7Bd_3.js → message-handler.process-CG0zFS-Z.js} +10 -10
- package/dist/{message-utils-CJeAoISH.js → message-utils-Dbuw27gd.js} +1 -1
- package/dist/{outbound-adapter-Dxs6iKEq.js → outbound-adapter-CKC_kmUN.js} +6 -6
- package/dist/pluralkit-CfTReLl3.js +40 -0
- package/dist/{probe-esE_Oqdm.js → probe-DcgZIpyF.js} +3 -2
- package/dist/{probe.runtime-C3Atgpvr.js → probe.runtime-CVwM9L5E.js} +1 -1
- package/dist/{provider-C7376XFH.js → provider-CwwSXIIj.js} +102 -37
- package/dist/{provider-session.runtime-CCdqogGf.js → provider-session.runtime-reBWkqHZ.js} +3 -3
- package/dist/provider.runtime-BsmTLYS_.js +2 -0
- package/dist/{resolve-allowlist-common-3gB2Gpmm.js → resolve-allowlist-common-D7bZqAw3.js} +3 -3
- package/dist/{resolve-channels-B3gQf8QL.js → resolve-channels--oE-RnO6.js} +6 -6
- package/dist/{resolve-users-BO10y5fJ.js → resolve-users-QXo8CXBU.js} +5 -5
- package/dist/{runtime-CFlR3L9X.js → runtime-CF7ramAs.js} +7 -7
- 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-CzF8MUl_.js +6 -0
- package/dist/runtime-api.monitor.js +5 -5
- package/dist/runtime-api.send.js +5 -5
- package/dist/runtime-api.threads.js +3 -3
- package/dist/{send-JHxfT4Pk.js → send-Bb295iHT.js} +5 -5
- package/dist/{send.components-CN35E2Ck.js → send.components-COkDUO3B.js} +4 -4
- package/dist/{send.outbound-B-cA1Esv.js → send.outbound-B_sk0hNe.js} +3 -3
- package/dist/{send.receipt-CGecJDin.js → send.receipt-Cli6_9Sn.js} +19 -7
- package/dist/{send.shared-vcbfThdy.js → send.shared-BCG7MWnP.js} +2 -2
- package/dist/session-binding-contract-api.js +1 -1
- package/dist/setup-plugin-api.js +1 -1
- package/dist/{subagent-hooks-20wXhVzZ.js → subagent-hooks-CtqoWK4x.js} +2 -2
- package/dist/subagent-hooks-api.js +1 -1
- package/dist/{system-events-DR27TE7p.js → system-events-BxGNk_wE.js} +1 -1
- package/dist/{target-resolver-CDi1gI90.js → target-resolver-BcoK6b0g.js} +2 -2
- package/dist/targets-Q-ZoP7K4.js +3 -0
- package/dist/{thread-bindings-DU4T6nDo.js → thread-bindings-DJ_HT6GJ.js} +4 -4
- package/dist/{thread-bindings.discord-api-CYkr-3Gj.js → thread-bindings.discord-api-OPyjvgyz.js} +4 -4
- package/dist/{thread-bindings.manager-BqWs1UE2.js → thread-bindings.manager-Cd2HAVw_.js} +3 -3
- package/dist/{transcripts-source-D-lBI5ZD.js → transcripts-source-CPf5gURy.js} +1 -1
- package/dist/transcripts-source-api.js +1 -1
- package/dist/{typing-xr05bL-r.js → typing-DY0cwLdg.js} +1 -1
- package/node_modules/undici/README.md +8 -2
- package/node_modules/undici/docs/docs/api/Agent.md +248 -44
- package/node_modules/undici/docs/docs/api/BalancedPool.md +246 -48
- package/node_modules/undici/docs/docs/api/CacheStorage.md +171 -13
- package/node_modules/undici/docs/docs/api/CacheStore.md +294 -98
- package/node_modules/undici/docs/docs/api/Client.md +386 -179
- package/node_modules/undici/docs/docs/api/ClientStats.md +80 -14
- package/node_modules/undici/docs/docs/api/Connector.md +118 -36
- package/node_modules/undici/docs/docs/api/ContentType.md +65 -25
- package/node_modules/undici/docs/docs/api/Cookies.md +122 -71
- package/node_modules/undici/docs/docs/api/Debug.md +34 -18
- package/node_modules/undici/docs/docs/api/DiagnosticsChannel.md +364 -164
- package/node_modules/undici/docs/docs/api/Dispatcher.md +485 -1102
- package/node_modules/undici/docs/docs/api/EnvHttpProxyAgent.md +102 -87
- package/node_modules/undici/docs/docs/api/Errors.md +503 -40
- package/node_modules/undici/docs/docs/api/EventSource.md +298 -32
- package/node_modules/undici/docs/docs/api/Fetch.md +680 -31
- package/node_modules/undici/docs/docs/api/GlobalInstallation.md +78 -98
- package/node_modules/undici/docs/docs/api/H2CClient.md +298 -176
- package/node_modules/undici/docs/docs/api/Interceptors.md +418 -0
- package/node_modules/undici/docs/docs/api/MockAgent.md +333 -314
- package/node_modules/undici/docs/docs/api/MockCallHistory.md +272 -98
- package/node_modules/undici/docs/docs/api/MockCallHistoryLog.md +189 -26
- package/node_modules/undici/docs/docs/api/MockClient.md +151 -33
- package/node_modules/undici/docs/docs/api/MockErrors.md +56 -5
- package/node_modules/undici/docs/docs/api/MockPool.md +321 -258
- package/node_modules/undici/docs/docs/api/Pool.md +235 -43
- package/node_modules/undici/docs/docs/api/PoolStats.md +119 -13
- package/node_modules/undici/docs/docs/api/ProxyAgent.md +179 -160
- package/node_modules/undici/docs/docs/api/RedirectHandler.md +238 -63
- package/node_modules/undici/docs/docs/api/RetryAgent.md +113 -26
- package/node_modules/undici/docs/docs/api/RetryHandler.md +161 -77
- package/node_modules/undici/docs/docs/api/RoundRobinPool.md +166 -72
- package/node_modules/undici/docs/docs/api/SnapshotAgent.md +264 -542
- package/node_modules/undici/docs/docs/api/Socks5ProxyAgent.md +177 -196
- package/node_modules/undici/docs/docs/api/Util.md +68 -11
- package/node_modules/undici/docs/docs/api/WebSocket.md +475 -80
- package/node_modules/undici/docs/docs/api/api-lifecycle.md +100 -32
- package/node_modules/undici/docs/docs/best-practices/client-certificate.md +2 -0
- package/node_modules/undici/docs/docs/best-practices/crawling.md +3 -1
- package/node_modules/undici/docs/docs/best-practices/migrating-from-v7-to-v8.md +6 -4
- package/node_modules/undici/docs/docs/best-practices/mocking-request.md +9 -7
- package/node_modules/undici/docs/docs/best-practices/proxy.md +3 -1
- package/node_modules/undici/docs/docs/best-practices/undici-vs-builtin-fetch.md +10 -8
- package/node_modules/undici/docs/docs/best-practices/writing-tests.md +2 -0
- package/node_modules/undici/docs/docs/{GettingStarted.md → getting-started.md} +22 -19
- package/node_modules/undici/docs/docs/index.md +784 -0
- package/node_modules/undici/docs/docs/site.json +125 -0
- package/node_modules/undici/docs/docs/type-map.json +79 -0
- package/node_modules/undici/lib/api/api-request.js +7 -1
- package/node_modules/undici/lib/api/readable.js +42 -7
- package/node_modules/undici/lib/cache/memory-cache-store.js +56 -11
- package/node_modules/undici/lib/cache/sqlite-cache-store.js +7 -1
- package/node_modules/undici/lib/core/connect.js +16 -2
- package/node_modules/undici/lib/core/errors.js +20 -0
- package/node_modules/undici/lib/core/request.js +14 -3
- package/node_modules/undici/lib/core/symbols.js +3 -0
- package/node_modules/undici/lib/core/util.js +30 -2
- package/node_modules/undici/lib/dispatcher/agent.js +10 -5
- package/node_modules/undici/lib/dispatcher/balanced-pool.js +7 -4
- package/node_modules/undici/lib/dispatcher/client-h1.js +74 -9
- package/node_modules/undici/lib/dispatcher/client-h2.js +483 -151
- package/node_modules/undici/lib/dispatcher/client.js +76 -30
- package/node_modules/undici/lib/dispatcher/dispatcher-base.js +13 -1
- package/node_modules/undici/lib/dispatcher/dispatcher.js +15 -1
- package/node_modules/undici/lib/dispatcher/dispatcher1-wrapper.js +3 -0
- package/node_modules/undici/lib/dispatcher/env-http-proxy-agent.js +37 -8
- package/node_modules/undici/lib/dispatcher/proxy-agent.js +58 -7
- package/node_modules/undici/lib/dispatcher/retry-agent.js +3 -0
- package/node_modules/undici/lib/dispatcher/round-robin-pool.js +1 -1
- package/node_modules/undici/lib/dispatcher/socks5-proxy-agent.js +106 -22
- package/node_modules/undici/lib/global.js +36 -16
- package/node_modules/undici/lib/handler/cache-handler.js +297 -65
- package/node_modules/undici/lib/handler/cache-revalidation-handler.js +13 -3
- package/node_modules/undici/lib/handler/decorator-handler.js +7 -1
- package/node_modules/undici/lib/handler/deduplication-handler.js +12 -6
- package/node_modules/undici/lib/handler/redirect-handler.js +26 -5
- package/node_modules/undici/lib/handler/retry-handler.js +238 -51
- package/node_modules/undici/lib/interceptor/cache.js +221 -58
- package/node_modules/undici/lib/interceptor/decompress.js +124 -15
- package/node_modules/undici/lib/interceptor/deduplicate.js +5 -4
- package/node_modules/undici/lib/interceptor/dns.js +7 -0
- package/node_modules/undici/lib/interceptor/dump.js +10 -23
- package/node_modules/undici/lib/mock/mock-agent.js +13 -1
- package/node_modules/undici/lib/mock/mock-interceptor.js +25 -7
- package/node_modules/undici/lib/mock/mock-utils.js +246 -27
- package/node_modules/undici/lib/util/cache.js +415 -71
- package/node_modules/undici/lib/util/date.js +23 -6
- package/node_modules/undici/lib/web/cookies/parse.js +150 -146
- package/node_modules/undici/lib/web/cookies/util.js +79 -9
- package/node_modules/undici/lib/web/eventsource/eventsource-stream.js +28 -1
- package/node_modules/undici/lib/web/eventsource/eventsource.js +13 -3
- package/node_modules/undici/lib/web/eventsource/util.js +1 -1
- package/node_modules/undici/lib/web/fetch/body.js +2 -1
- package/node_modules/undici/lib/web/fetch/constants.js +1 -1
- package/node_modules/undici/lib/web/fetch/index.js +17 -2
- package/node_modules/undici/lib/web/fetch/request.js +2 -3
- package/node_modules/undici/lib/web/fetch/response.js +1 -3
- package/node_modules/undici/lib/web/fetch/util.js +10 -2
- package/node_modules/undici/lib/web/webidl/index.js +3 -3
- package/node_modules/undici/lib/web/websocket/connection.js +1 -1
- package/node_modules/undici/lib/web/websocket/permessage-deflate.js +5 -0
- package/node_modules/undici/lib/web/websocket/stream/websocketstream.js +8 -10
- package/node_modules/undici/lib/web/websocket/websocket.js +22 -0
- package/node_modules/undici/package.json +4 -4
- package/node_modules/undici/types/client.d.ts +53 -3
- package/node_modules/undici/types/cookies.d.ts +1 -1
- package/node_modules/undici/types/dispatcher.d.ts +3 -3
- package/node_modules/undici/types/errors.d.ts +10 -0
- package/node_modules/undici/types/handlers.d.ts +2 -0
- package/node_modules/undici/types/interceptors.d.ts +2 -0
- package/node_modules/undici/types/mock-agent.d.ts +11 -10
- package/node_modules/undici/types/mock-interceptor.d.ts +5 -1
- package/node_modules/undici/types/proxy-agent.d.ts +7 -0
- package/node_modules/undici/types/socks5-proxy-agent.d.ts +2 -0
- package/npm-shrinkwrap.json +7 -7
- package/package.json +6 -5
- package/dist/pluralkit-DI6RYaVj.js +0 -24
- package/dist/provider.runtime-D1m66kDS.js +0 -2
- package/dist/runtime-api.monitor-4oc58TSk.js +0 -6
- package/dist/targets-C6yd3y8R.js +0 -3
|
@@ -6,8 +6,18 @@ const util = require('../core/util')
|
|
|
6
6
|
const CacheHandler = require('../handler/cache-handler')
|
|
7
7
|
const MemoryCacheStore = require('../cache/memory-cache-store')
|
|
8
8
|
const CacheRevalidationHandler = require('../handler/cache-revalidation-handler')
|
|
9
|
-
const {
|
|
9
|
+
const {
|
|
10
|
+
assertCacheStore,
|
|
11
|
+
assertCacheMethods,
|
|
12
|
+
getInterceptorOrigin,
|
|
13
|
+
makeCacheKey,
|
|
14
|
+
normalizeHeaders,
|
|
15
|
+
parseCacheControlHeader,
|
|
16
|
+
isInvalidOrWildcardVaryHeader,
|
|
17
|
+
parseVaryHeader
|
|
18
|
+
} = require('../util/cache.js')
|
|
10
19
|
const { AbortError } = require('../core/errors.js')
|
|
20
|
+
const { parseHttpDate } = require('../util/date.js')
|
|
11
21
|
|
|
12
22
|
/**
|
|
13
23
|
* @param {(string | RegExp)[] | undefined} origins
|
|
@@ -28,6 +38,44 @@ function assertCacheOrigins (origins, name) {
|
|
|
28
38
|
|
|
29
39
|
const nop = () => {}
|
|
30
40
|
|
|
41
|
+
function trimOWS (value) {
|
|
42
|
+
return value.replace(/^[\t ]+|[\t ]+$/g, '')
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function arrayIncludes (array, value) {
|
|
46
|
+
for (let i = 0; i < array.length; i++) {
|
|
47
|
+
if (array[i] === value) {
|
|
48
|
+
return true
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return false
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function hasPragmaNoCache (headers) {
|
|
56
|
+
const pragma = headers?.pragma
|
|
57
|
+
if (!pragma) {
|
|
58
|
+
return false
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const values = Array.isArray(pragma) ? pragma : [pragma]
|
|
62
|
+
for (let i = 0; i < values.length; i++) {
|
|
63
|
+
const value = values[i]
|
|
64
|
+
if (typeof value !== 'string') {
|
|
65
|
+
continue
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const directives = value.split(',')
|
|
69
|
+
for (let j = 0; j < directives.length; j++) {
|
|
70
|
+
if (trimOWS(directives[j]).toLowerCase() === 'no-cache') {
|
|
71
|
+
return true
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return false
|
|
77
|
+
}
|
|
78
|
+
|
|
31
79
|
/**
|
|
32
80
|
* @typedef {(options: import('../../types/dispatcher.d.ts').default.DispatchOptions, handler: import('../../types/dispatcher.d.ts').default.DispatchHandler) => void} DispatchFn
|
|
33
81
|
*/
|
|
@@ -57,16 +105,114 @@ function needsRevalidation (result, cacheControlDirectives, { headers = {} }) {
|
|
|
57
105
|
return false
|
|
58
106
|
}
|
|
59
107
|
|
|
108
|
+
/**
|
|
109
|
+
* @param {import('../../types/cache-interceptor.d.ts').default.GetResult} result
|
|
110
|
+
* @param {import('../../types/cache-interceptor.d.ts').default.CacheOptions['type']} cacheType
|
|
111
|
+
* @returns {boolean}
|
|
112
|
+
*/
|
|
113
|
+
function staleResponseRequiresRevalidation (result, cacheType) {
|
|
114
|
+
return result.cacheControlDirectives?.['must-revalidate'] === true ||
|
|
115
|
+
(cacheType === 'shared' && (
|
|
116
|
+
result.cacheControlDirectives?.['proxy-revalidate'] === true ||
|
|
117
|
+
// https://www.rfc-editor.org/rfc/rfc9111.html#section-5.2.2.10
|
|
118
|
+
// s-maxage implies proxy-revalidate for shared caches.
|
|
119
|
+
result.cacheControlDirectives?.['s-maxage'] !== undefined
|
|
120
|
+
))
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* @param {import('../../types/cache-interceptor.d.ts').default.CacheOptions['type']} cacheType
|
|
125
|
+
* @param {import('../../types/header.d.ts').IncomingHttpHeaders} headers
|
|
126
|
+
* @returns {boolean}
|
|
127
|
+
*/
|
|
128
|
+
function revalidationResponseDisallowsCachedReuse (cacheType, headers) {
|
|
129
|
+
if (
|
|
130
|
+
(headers.vary && isInvalidOrWildcardVaryHeader(headers.vary)) ||
|
|
131
|
+
(cacheType === 'shared' && Object.hasOwn(headers, 'set-cookie'))
|
|
132
|
+
) {
|
|
133
|
+
return true
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const cacheControl = headers['cache-control']
|
|
137
|
+
if (!cacheControl) {
|
|
138
|
+
return false
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const cacheControlDirectives = parseCacheControlHeader(cacheControl)
|
|
142
|
+
return cacheControlDirectives['no-store'] === true ||
|
|
143
|
+
(cacheType === 'shared' && cacheControlDirectives.private === true)
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function revalidationResponseUpdatesCacheControl (headers) {
|
|
147
|
+
return headers['cache-control'] !== undefined
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* @param {import('../../types/cache-interceptor.d.ts').default.GetResult} result
|
|
152
|
+
* @param {Record<string, string | string[] | null> | undefined} varyDirectives
|
|
153
|
+
* @returns {boolean}
|
|
154
|
+
*/
|
|
155
|
+
function revalidationResponseAddsVary (result, varyDirectives) {
|
|
156
|
+
if (!varyDirectives) {
|
|
157
|
+
return false
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
for (const key in varyDirectives) {
|
|
161
|
+
if (result.vary == null || !Object.hasOwn(result.vary, key)) {
|
|
162
|
+
return true
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
return false
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
function deleteCachedValue (store, cacheKey) {
|
|
170
|
+
try {
|
|
171
|
+
store.delete(cacheKey)?.catch?.(nop)
|
|
172
|
+
} catch {
|
|
173
|
+
// Fail silently
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
function getUsableLastModified (headers) {
|
|
178
|
+
const lastModified = headers?.['last-modified']
|
|
179
|
+
if (typeof lastModified === 'string' && parseHttpDate(lastModified)) {
|
|
180
|
+
return lastModified
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
function makeRevalidationHeaders (opts, result) {
|
|
185
|
+
const headers = {
|
|
186
|
+
...opts.headers,
|
|
187
|
+
'if-modified-since': getUsableLastModified(result.headers) ?? new Date(result.cachedAt).toUTCString()
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
if (result.etag) {
|
|
191
|
+
headers['if-none-match'] = result.etag
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
if (result.vary) {
|
|
195
|
+
for (const key in result.vary) {
|
|
196
|
+
if (result.vary[key] != null) {
|
|
197
|
+
headers[key] = result.vary[key]
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
return headers
|
|
203
|
+
}
|
|
204
|
+
|
|
60
205
|
/**
|
|
61
206
|
* @param {import('../../types/cache-interceptor.d.ts').default.GetResult} result
|
|
62
207
|
* @param {import('../../types/cache-interceptor.d.ts').default.CacheControlDirectives | undefined} cacheControlDirectives
|
|
208
|
+
* @param {import('../../types/cache-interceptor.d.ts').default.CacheOptions['type']} cacheType
|
|
63
209
|
* @returns {boolean}
|
|
64
210
|
*/
|
|
65
|
-
function isStale (result, cacheControlDirectives) {
|
|
211
|
+
function isStale (result, cacheControlDirectives, cacheType) {
|
|
66
212
|
const now = Date.now()
|
|
67
213
|
if (now > result.staleAt) {
|
|
68
214
|
// Response is stale
|
|
69
|
-
if (cacheControlDirectives?.['max-stale']) {
|
|
215
|
+
if (!staleResponseRequiresRevalidation(result, cacheType) && cacheControlDirectives?.['max-stale']) {
|
|
70
216
|
// There's a threshold where we can serve stale responses, let's see if
|
|
71
217
|
// we're in it
|
|
72
218
|
// https://www.rfc-editor.org/rfc/rfc9111.html#name-max-stale
|
|
@@ -93,11 +239,12 @@ function isStale (result, cacheControlDirectives) {
|
|
|
93
239
|
/**
|
|
94
240
|
* Check if we're within the stale-while-revalidate window for a stale response
|
|
95
241
|
* @param {import('../../types/cache-interceptor.d.ts').default.GetResult} result
|
|
242
|
+
* @param {import('../../types/cache-interceptor.d.ts').default.CacheOptions['type']} cacheType
|
|
96
243
|
* @returns {boolean}
|
|
97
244
|
*/
|
|
98
|
-
function withinStaleWhileRevalidateWindow (result) {
|
|
245
|
+
function withinStaleWhileRevalidateWindow (result, cacheType) {
|
|
99
246
|
const staleWhileRevalidate = result.cacheControlDirectives?.['stale-while-revalidate']
|
|
100
|
-
if (!staleWhileRevalidate) {
|
|
247
|
+
if (!staleWhileRevalidate || staleResponseRequiresRevalidation(result, cacheType)) {
|
|
101
248
|
return false
|
|
102
249
|
}
|
|
103
250
|
|
|
@@ -273,6 +420,17 @@ function handleResult (
|
|
|
273
420
|
return handleUncachedResponse(dispatch, globalOpts, cacheKey, handler, opts, reqCacheControl)
|
|
274
421
|
}
|
|
275
422
|
|
|
423
|
+
// Shared stores may outlive the Undici version that wrote them. Do not
|
|
424
|
+
// re-serve a Set-Cookie header from an existing shared-cache entry.
|
|
425
|
+
if (globalOpts.type === 'shared' && Object.hasOwn(result.headers, 'set-cookie')) {
|
|
426
|
+
if (util.isStream(result.body)) {
|
|
427
|
+
result.body.on('error', nop).destroy()
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
deleteCachedValue(globalOpts.store, cacheKey)
|
|
431
|
+
return handleUncachedResponse(dispatch, globalOpts, cacheKey, handler, opts, reqCacheControl)
|
|
432
|
+
}
|
|
433
|
+
|
|
276
434
|
const now = Date.now()
|
|
277
435
|
if (now > result.deleteAt) {
|
|
278
436
|
// Response is expired, cache store shouldn't have given this to us
|
|
@@ -280,14 +438,10 @@ function handleResult (
|
|
|
280
438
|
}
|
|
281
439
|
|
|
282
440
|
const age = Math.round((now - result.cachedAt) / 1000)
|
|
283
|
-
|
|
284
|
-
// Response is considered expired for this specific request
|
|
285
|
-
// https://www.rfc-editor.org/rfc/rfc9111.html#section-5.2.1.1
|
|
286
|
-
return dispatch(opts, handler)
|
|
287
|
-
}
|
|
441
|
+
const requestMaxAgeExpired = reqCacheControl?.['max-age'] !== undefined && age >= reqCacheControl['max-age']
|
|
288
442
|
|
|
289
|
-
const stale = isStale(result, reqCacheControl)
|
|
290
|
-
const revalidate = needsRevalidation(result, reqCacheControl, opts)
|
|
443
|
+
const stale = requestMaxAgeExpired || isStale(result, reqCacheControl, globalOpts.type)
|
|
444
|
+
const revalidate = requestMaxAgeExpired || needsRevalidation(result, reqCacheControl, opts)
|
|
291
445
|
|
|
292
446
|
// Check if the response is stale
|
|
293
447
|
if (stale || revalidate) {
|
|
@@ -299,28 +453,13 @@ function handleResult (
|
|
|
299
453
|
|
|
300
454
|
// RFC 5861: If we're within stale-while-revalidate window, serve stale immediately
|
|
301
455
|
// and revalidate in background, unless immediate revalidation is necessary
|
|
302
|
-
if (!revalidate && withinStaleWhileRevalidateWindow(result)) {
|
|
456
|
+
if (!revalidate && withinStaleWhileRevalidateWindow(result, globalOpts.type)) {
|
|
303
457
|
// Serve stale response immediately
|
|
304
458
|
sendCachedValue(handler, opts, result, age, null, true)
|
|
305
459
|
|
|
306
460
|
// Start background revalidation (fire-and-forget)
|
|
307
461
|
queueMicrotask(() => {
|
|
308
|
-
const headers =
|
|
309
|
-
...opts.headers,
|
|
310
|
-
'if-modified-since': new Date(result.cachedAt).toUTCString()
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
if (result.etag) {
|
|
314
|
-
headers['if-none-match'] = result.etag
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
if (result.vary) {
|
|
318
|
-
for (const key in result.vary) {
|
|
319
|
-
if (result.vary[key] != null) {
|
|
320
|
-
headers[key] = result.vary[key]
|
|
321
|
-
}
|
|
322
|
-
}
|
|
323
|
-
}
|
|
462
|
+
const headers = makeRevalidationHeaders(opts, result)
|
|
324
463
|
|
|
325
464
|
// Background revalidation - update cache if we get new data
|
|
326
465
|
dispatch(
|
|
@@ -344,28 +483,15 @@ function handleResult (
|
|
|
344
483
|
}
|
|
345
484
|
|
|
346
485
|
let withinStaleIfErrorThreshold = false
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
const headers = {
|
|
353
|
-
...opts.headers,
|
|
354
|
-
'if-modified-since': new Date(result.cachedAt).toUTCString()
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
if (result.etag) {
|
|
358
|
-
headers['if-none-match'] = result.etag
|
|
359
|
-
}
|
|
360
|
-
|
|
361
|
-
if (result.vary) {
|
|
362
|
-
for (const key in result.vary) {
|
|
363
|
-
if (result.vary[key] != null) {
|
|
364
|
-
headers[key] = result.vary[key]
|
|
365
|
-
}
|
|
486
|
+
if (!staleResponseRequiresRevalidation(result, globalOpts.type)) {
|
|
487
|
+
const staleIfErrorExpiry = result.cacheControlDirectives['stale-if-error'] ?? reqCacheControl?.['stale-if-error']
|
|
488
|
+
if (staleIfErrorExpiry) {
|
|
489
|
+
withinStaleIfErrorThreshold = now < (result.staleAt + (staleIfErrorExpiry * 1000))
|
|
366
490
|
}
|
|
367
491
|
}
|
|
368
492
|
|
|
493
|
+
const headers = makeRevalidationHeaders(opts, result)
|
|
494
|
+
|
|
369
495
|
// We need to revalidate the response
|
|
370
496
|
return dispatch(
|
|
371
497
|
{
|
|
@@ -373,8 +499,30 @@ function handleResult (
|
|
|
373
499
|
headers
|
|
374
500
|
},
|
|
375
501
|
new CacheRevalidationHandler(
|
|
376
|
-
(success, context) => {
|
|
502
|
+
(success, context, statusCode, headers) => {
|
|
377
503
|
if (success) {
|
|
504
|
+
if (statusCode === 304) {
|
|
505
|
+
if (revalidationResponseDisallowsCachedReuse(globalOpts.type, headers)) {
|
|
506
|
+
if (util.isStream(result.body)) {
|
|
507
|
+
result.body.on('error', nop).destroy()
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
deleteCachedValue(globalOpts.store, cacheKey)
|
|
511
|
+
return dispatch(opts, new CacheHandler(globalOpts, cacheKey, handler))
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
if (revalidationResponseUpdatesCacheControl(headers)) {
|
|
515
|
+
deleteCachedValue(globalOpts.store, cacheKey)
|
|
516
|
+
} else if (revalidationResponseAddsVary(result, headers.vary ? parseVaryHeader(headers.vary, opts.headers) : undefined)) {
|
|
517
|
+
if (util.isStream(result.body)) {
|
|
518
|
+
result.body.on('error', nop).destroy()
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
deleteCachedValue(globalOpts.store, cacheKey)
|
|
522
|
+
return dispatch(opts, new CacheHandler(globalOpts, cacheKey, handler))
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
|
|
378
526
|
// TODO: successful revalidation should be considered fresh (not give stale warning).
|
|
379
527
|
sendCachedValue(handler, opts, result, age, context, stale)
|
|
380
528
|
} else if (util.isStream(result.body)) {
|
|
@@ -431,28 +579,36 @@ module.exports = (opts = {}) => {
|
|
|
431
579
|
type
|
|
432
580
|
}
|
|
433
581
|
|
|
434
|
-
const safeMethodsToNotCache =
|
|
582
|
+
const safeMethodsToNotCache = []
|
|
583
|
+
for (let i = 0; i < util.safeHTTPMethods.length; i++) {
|
|
584
|
+
const method = util.safeHTTPMethods[i]
|
|
585
|
+
if (!arrayIncludes(methods, method)) {
|
|
586
|
+
safeMethodsToNotCache.push(method)
|
|
587
|
+
}
|
|
588
|
+
}
|
|
435
589
|
|
|
436
|
-
return dispatch => {
|
|
590
|
+
return (dispatch, interceptorOrigin) => {
|
|
437
591
|
return (opts, handler) => {
|
|
438
|
-
|
|
439
|
-
|
|
592
|
+
const requestOrigin = getInterceptorOrigin(opts, interceptorOrigin)
|
|
593
|
+
if (!requestOrigin || arrayIncludes(safeMethodsToNotCache, opts.method)) {
|
|
594
|
+
// We cannot safely cache without an authoritative origin, or this is
|
|
595
|
+
// not a method we want to cache.
|
|
440
596
|
return dispatch(opts, handler)
|
|
441
597
|
}
|
|
442
598
|
|
|
443
599
|
// Check if origin is in whitelist
|
|
444
600
|
if (origins !== undefined) {
|
|
445
|
-
const
|
|
601
|
+
const normalizedRequestOrigin = requestOrigin.toString().toLowerCase()
|
|
446
602
|
let isAllowed = false
|
|
447
603
|
|
|
448
604
|
for (let i = 0; i < origins.length; i++) {
|
|
449
605
|
const allowed = origins[i]
|
|
450
606
|
if (typeof allowed === 'string') {
|
|
451
|
-
if (allowed.toLowerCase() ===
|
|
607
|
+
if (allowed.toLowerCase() === normalizedRequestOrigin) {
|
|
452
608
|
isAllowed = true
|
|
453
609
|
break
|
|
454
610
|
}
|
|
455
|
-
} else if (allowed.test(
|
|
611
|
+
} else if (allowed.test(normalizedRequestOrigin)) {
|
|
456
612
|
isAllowed = true
|
|
457
613
|
break
|
|
458
614
|
}
|
|
@@ -470,7 +626,9 @@ module.exports = (opts = {}) => {
|
|
|
470
626
|
|
|
471
627
|
const reqCacheControl = opts.headers?.['cache-control']
|
|
472
628
|
? parseCacheControlHeader(opts.headers['cache-control'])
|
|
473
|
-
:
|
|
629
|
+
: hasPragmaNoCache(opts.headers)
|
|
630
|
+
? { 'no-cache': true }
|
|
631
|
+
: undefined
|
|
474
632
|
|
|
475
633
|
if (reqCacheControl?.['no-store']) {
|
|
476
634
|
return dispatch(opts, handler)
|
|
@@ -479,7 +637,12 @@ module.exports = (opts = {}) => {
|
|
|
479
637
|
/**
|
|
480
638
|
* @type {import('../../types/cache-interceptor.d.ts').default.CacheKey}
|
|
481
639
|
*/
|
|
482
|
-
const cacheKey = makeCacheKey(opts)
|
|
640
|
+
const cacheKey = makeCacheKey(opts, requestOrigin)
|
|
641
|
+
|
|
642
|
+
if (!arrayIncludes(util.safeHTTPMethods, opts.method)) {
|
|
643
|
+
return dispatch(opts, new CacheHandler(globalOpts, cacheKey, handler))
|
|
644
|
+
}
|
|
645
|
+
|
|
483
646
|
const result = store.get(cacheKey)
|
|
484
647
|
|
|
485
648
|
if (result && typeof result.then === 'function') {
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
const { createInflate, createGunzip, createBrotliDecompress, createZstdDecompress } = require('node:zlib')
|
|
4
|
-
const { pipeline } = require('node:stream')
|
|
4
|
+
const { pipeline, Transform: TransformStream } = require('node:stream')
|
|
5
|
+
const { InvalidArgumentError, ResponseExceededMaxSizeError } = require('../core/errors')
|
|
5
6
|
const DecoratorHandler = require('../handler/decorator-handler')
|
|
6
7
|
|
|
7
8
|
/** @typedef {import('node:stream').Transform} Transform */
|
|
@@ -20,6 +21,31 @@ const supportedEncodings = {
|
|
|
20
21
|
}
|
|
21
22
|
|
|
22
23
|
const defaultSkipStatusCodes = /** @type {const} */ ([204, 304])
|
|
24
|
+
const defaultMaxSize = 64 * 1024 * 1024
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Limits the output of one stage in a decompression chain.
|
|
28
|
+
* @param {number} maxSize - Maximum output size in bytes
|
|
29
|
+
* @returns {Transform}
|
|
30
|
+
*/
|
|
31
|
+
function createMaxSizeLimiter (maxSize) {
|
|
32
|
+
let size = 0
|
|
33
|
+
|
|
34
|
+
return new TransformStream({
|
|
35
|
+
transform (chunk, _encoding, callback) {
|
|
36
|
+
const decompressedSize = size + chunk.length
|
|
37
|
+
if (decompressedSize > maxSize) {
|
|
38
|
+
callback(new ResponseExceededMaxSizeError(
|
|
39
|
+
`Decompressed response size (${decompressedSize}) exceeded maxSize (${maxSize})`
|
|
40
|
+
))
|
|
41
|
+
return
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
size = decompressedSize
|
|
45
|
+
callback(null, chunk)
|
|
46
|
+
}
|
|
47
|
+
})
|
|
48
|
+
}
|
|
23
49
|
|
|
24
50
|
let warningEmitted = /** @type {boolean} */ (false)
|
|
25
51
|
|
|
@@ -27,20 +53,36 @@ let warningEmitted = /** @type {boolean} */ (false)
|
|
|
27
53
|
* @typedef {Object} DecompressHandlerOptions
|
|
28
54
|
* @property {number[]|Readonly<number[]>} [skipStatusCodes=[204, 304]] - List of status codes to skip decompression for
|
|
29
55
|
* @property {boolean} [skipErrorResponses] - Whether to skip decompression for error responses (status codes >= 400)
|
|
56
|
+
* @property {number} [maxSize=67108864] - Maximum decompressed response size in bytes
|
|
30
57
|
*/
|
|
31
58
|
|
|
32
59
|
class DecompressHandler extends DecoratorHandler {
|
|
33
60
|
/** @type {Transform[]} */
|
|
34
61
|
#decompressors = []
|
|
62
|
+
/** @type {Record<string, string | string[]> | undefined} */
|
|
63
|
+
#trailers
|
|
35
64
|
/** @type {Readonly<number[]>} */
|
|
36
65
|
#skipStatusCodes
|
|
37
66
|
/** @type {boolean} */
|
|
38
67
|
#skipErrorResponses
|
|
68
|
+
/** @type {number} */
|
|
69
|
+
#maxSize
|
|
70
|
+
/** @type {number} */
|
|
71
|
+
#decompressedSize = 0
|
|
72
|
+
/** @type {boolean} */
|
|
73
|
+
#terminated = false
|
|
74
|
+
/** @type {boolean} */
|
|
75
|
+
#inputEnded = false
|
|
76
|
+
|
|
77
|
+
constructor (handler, { skipStatusCodes = defaultSkipStatusCodes, skipErrorResponses = true, maxSize = defaultMaxSize } = {}) {
|
|
78
|
+
if (!Number.isSafeInteger(maxSize) || maxSize < 1) {
|
|
79
|
+
throw new InvalidArgumentError('maxSize must be a positive integer')
|
|
80
|
+
}
|
|
39
81
|
|
|
40
|
-
constructor (handler, { skipStatusCodes = defaultSkipStatusCodes, skipErrorResponses = true } = {}) {
|
|
41
82
|
super(handler)
|
|
42
83
|
this.#skipStatusCodes = skipStatusCodes
|
|
43
84
|
this.#skipErrorResponses = skipErrorResponses
|
|
85
|
+
this.#maxSize = maxSize
|
|
44
86
|
}
|
|
45
87
|
|
|
46
88
|
/**
|
|
@@ -60,7 +102,7 @@ class DecompressHandler extends DecoratorHandler {
|
|
|
60
102
|
* Creates a chain of decompressors for multiple content encodings
|
|
61
103
|
*
|
|
62
104
|
* @param {string} encodings - Comma-separated list of content encodings
|
|
63
|
-
* @returns {Array<
|
|
105
|
+
* @returns {Array<Transform>} - Array of decompressor and limiting streams
|
|
64
106
|
* @throws {Error} - If the number of content-encodings exceeds the maximum allowed
|
|
65
107
|
*/
|
|
66
108
|
#createDecompressionChain (encodings) {
|
|
@@ -88,7 +130,40 @@ class DecompressHandler extends DecoratorHandler {
|
|
|
88
130
|
decompressors.push(supportedEncodings[encoding]())
|
|
89
131
|
}
|
|
90
132
|
|
|
91
|
-
|
|
133
|
+
if (decompressors.length < 2) {
|
|
134
|
+
return decompressors
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/** @type {Transform[]} */
|
|
138
|
+
const streams = []
|
|
139
|
+
for (let i = 0; i < decompressors.length; i++) {
|
|
140
|
+
streams.push(decompressors[i])
|
|
141
|
+
if (i < decompressors.length - 1) {
|
|
142
|
+
streams.push(createMaxSizeLimiter(this.#maxSize))
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
return streams
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Stops decompression and reports an error.
|
|
151
|
+
* @param {Controller} controller - The controller to coordinate with
|
|
152
|
+
* @param {Error} error - The decompression error
|
|
153
|
+
* @returns {void}
|
|
154
|
+
*/
|
|
155
|
+
#fail (controller, error) {
|
|
156
|
+
if (this.#terminated) {
|
|
157
|
+
return
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
if (this.#inputEnded) {
|
|
161
|
+
// The request is already marked complete once the compressed input ends,
|
|
162
|
+
// so controller.abort() can no longer propagate decoder flush errors.
|
|
163
|
+
this.onResponseError(controller, error)
|
|
164
|
+
} else {
|
|
165
|
+
controller.abort(error)
|
|
166
|
+
}
|
|
92
167
|
}
|
|
93
168
|
|
|
94
169
|
/**
|
|
@@ -99,8 +174,21 @@ class DecompressHandler extends DecoratorHandler {
|
|
|
99
174
|
*/
|
|
100
175
|
#setupDecompressorEvents (decompressor, controller) {
|
|
101
176
|
decompressor.on('readable', () => {
|
|
177
|
+
if (this.#terminated) {
|
|
178
|
+
return
|
|
179
|
+
}
|
|
180
|
+
|
|
102
181
|
let chunk
|
|
103
182
|
while ((chunk = decompressor.read()) !== null) {
|
|
183
|
+
const decompressedSize = this.#decompressedSize + chunk.length
|
|
184
|
+
if (decompressedSize > this.#maxSize) {
|
|
185
|
+
this.#fail(controller, new ResponseExceededMaxSizeError(
|
|
186
|
+
`Decompressed response size (${decompressedSize}) exceeded maxSize (${this.#maxSize})`
|
|
187
|
+
))
|
|
188
|
+
return
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
this.#decompressedSize = decompressedSize
|
|
104
192
|
const result = super.onResponseData(controller, chunk)
|
|
105
193
|
if (result === false) {
|
|
106
194
|
break
|
|
@@ -109,7 +197,7 @@ class DecompressHandler extends DecoratorHandler {
|
|
|
109
197
|
})
|
|
110
198
|
|
|
111
199
|
decompressor.on('error', (error) => {
|
|
112
|
-
|
|
200
|
+
this.#fail(controller, error)
|
|
113
201
|
})
|
|
114
202
|
}
|
|
115
203
|
|
|
@@ -123,7 +211,13 @@ class DecompressHandler extends DecoratorHandler {
|
|
|
123
211
|
this.#setupDecompressorEvents(decompressor, controller)
|
|
124
212
|
|
|
125
213
|
decompressor.on('end', () => {
|
|
126
|
-
|
|
214
|
+
if (this.#terminated) {
|
|
215
|
+
return
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
this.#terminated = true
|
|
219
|
+
this.#cleanupDecompressors()
|
|
220
|
+
super.onResponseEnd(controller, this.#trailers)
|
|
127
221
|
})
|
|
128
222
|
}
|
|
129
223
|
|
|
@@ -137,11 +231,18 @@ class DecompressHandler extends DecoratorHandler {
|
|
|
137
231
|
this.#setupDecompressorEvents(lastDecompressor, controller)
|
|
138
232
|
|
|
139
233
|
pipeline(this.#decompressors, (err) => {
|
|
234
|
+
if (this.#terminated) {
|
|
235
|
+
return
|
|
236
|
+
}
|
|
237
|
+
|
|
140
238
|
if (err) {
|
|
141
|
-
|
|
239
|
+
this.#fail(controller, err)
|
|
142
240
|
return
|
|
143
241
|
}
|
|
144
|
-
|
|
242
|
+
|
|
243
|
+
this.#terminated = true
|
|
244
|
+
this.#cleanupDecompressors()
|
|
245
|
+
super.onResponseEnd(controller, this.#trailers)
|
|
145
246
|
})
|
|
146
247
|
}
|
|
147
248
|
|
|
@@ -196,7 +297,7 @@ class DecompressHandler extends DecoratorHandler {
|
|
|
196
297
|
|
|
197
298
|
filteredHeaders.push(rawHeaders[i], rawHeaders[i + 1])
|
|
198
299
|
}
|
|
199
|
-
|
|
300
|
+
rawHeaders.splice(0, rawHeaders.length, ...filteredHeaders)
|
|
200
301
|
} else if (typeof rawHeaders === 'object') {
|
|
201
302
|
for (const name of Object.keys(rawHeaders)) {
|
|
202
303
|
const lowerName = name.toLowerCase()
|
|
@@ -236,8 +337,9 @@ class DecompressHandler extends DecoratorHandler {
|
|
|
236
337
|
*/
|
|
237
338
|
onResponseEnd (controller, trailers) {
|
|
238
339
|
if (this.#decompressors.length > 0) {
|
|
340
|
+
this.#inputEnded = true
|
|
341
|
+
this.#trailers = trailers
|
|
239
342
|
this.#decompressors[0].end()
|
|
240
|
-
this.#cleanupDecompressors()
|
|
241
343
|
return
|
|
242
344
|
}
|
|
243
345
|
super.onResponseEnd(controller, trailers)
|
|
@@ -249,12 +351,15 @@ class DecompressHandler extends DecoratorHandler {
|
|
|
249
351
|
* @returns {void}
|
|
250
352
|
*/
|
|
251
353
|
onResponseError (controller, err) {
|
|
252
|
-
if (this.#
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
354
|
+
if (this.#terminated) {
|
|
355
|
+
return
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
this.#terminated = true
|
|
359
|
+
for (const decompressor of this.#decompressors) {
|
|
360
|
+
decompressor.destroy()
|
|
257
361
|
}
|
|
362
|
+
this.#cleanupDecompressors()
|
|
258
363
|
super.onResponseError(controller, err)
|
|
259
364
|
}
|
|
260
365
|
}
|
|
@@ -276,6 +381,10 @@ function createDecompressInterceptor (options = {}) {
|
|
|
276
381
|
|
|
277
382
|
return (dispatch) => {
|
|
278
383
|
return (opts, handler) => {
|
|
384
|
+
if (opts.method === 'HEAD') {
|
|
385
|
+
return dispatch(opts, handler)
|
|
386
|
+
}
|
|
387
|
+
|
|
279
388
|
const decompressHandler = new DecompressHandler(handler, options)
|
|
280
389
|
return dispatch(opts, decompressHandler)
|
|
281
390
|
}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
const diagnosticsChannel = require('node:diagnostics_channel')
|
|
4
4
|
const util = require('../core/util')
|
|
5
5
|
const DeduplicationHandler = require('../handler/deduplication-handler')
|
|
6
|
-
const { normalizeHeaders, makeCacheKey, makeDeduplicationKey } = require('../util/cache.js')
|
|
6
|
+
const { getInterceptorOrigin, normalizeHeaders, makeCacheKey, makeDeduplicationKey } = require('../util/cache.js')
|
|
7
7
|
|
|
8
8
|
const pendingRequestsChannel = diagnosticsChannel.channel('undici:request:pending-requests')
|
|
9
9
|
|
|
@@ -57,9 +57,10 @@ module.exports = (opts = {}) => {
|
|
|
57
57
|
*/
|
|
58
58
|
const pendingRequests = new Map()
|
|
59
59
|
|
|
60
|
-
return dispatch => {
|
|
60
|
+
return (dispatch, interceptorOrigin) => {
|
|
61
61
|
return (opts, handler) => {
|
|
62
|
-
|
|
62
|
+
const requestOrigin = getInterceptorOrigin(opts, interceptorOrigin)
|
|
63
|
+
if (!requestOrigin || opts.upgrade || methods.includes(opts.method) === false) {
|
|
63
64
|
return dispatch(opts, handler)
|
|
64
65
|
}
|
|
65
66
|
|
|
@@ -77,7 +78,7 @@ module.exports = (opts = {}) => {
|
|
|
77
78
|
}
|
|
78
79
|
}
|
|
79
80
|
|
|
80
|
-
const cacheKey = makeCacheKey(opts)
|
|
81
|
+
const cacheKey = makeCacheKey(opts, requestOrigin)
|
|
81
82
|
const dedupeKey = makeDeduplicationKey(cacheKey, excludeHeaderNamesSet)
|
|
82
83
|
|
|
83
84
|
// Check if there's already a pending request for this key
|