@nocobase/plugin-idp-oauth 2.1.0-alpha.17 → 2.1.0-alpha.19
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/build.config.ts +1 -1
- package/dist/externalVersion.js +6 -4
- package/dist/node_modules/light-my-request/package.json +1 -1
- package/dist/node_modules/undici/LICENSE +21 -0
- package/dist/node_modules/undici/README.md +741 -0
- package/dist/node_modules/undici/docs/docs/api/Agent.md +84 -0
- package/dist/node_modules/undici/docs/docs/api/BalancedPool.md +99 -0
- package/dist/node_modules/undici/docs/docs/api/CacheStorage.md +30 -0
- package/dist/node_modules/undici/docs/docs/api/CacheStore.md +164 -0
- package/dist/node_modules/undici/docs/docs/api/Client.md +285 -0
- package/dist/node_modules/undici/docs/docs/api/ClientStats.md +27 -0
- package/dist/node_modules/undici/docs/docs/api/Connector.md +115 -0
- package/dist/node_modules/undici/docs/docs/api/ContentType.md +57 -0
- package/dist/node_modules/undici/docs/docs/api/Cookies.md +101 -0
- package/dist/node_modules/undici/docs/docs/api/Debug.md +62 -0
- package/dist/node_modules/undici/docs/docs/api/DiagnosticsChannel.md +315 -0
- package/dist/node_modules/undici/docs/docs/api/Dispatcher.md +1392 -0
- package/dist/node_modules/undici/docs/docs/api/EnvHttpProxyAgent.md +159 -0
- package/dist/node_modules/undici/docs/docs/api/Errors.md +49 -0
- package/dist/node_modules/undici/docs/docs/api/EventSource.md +45 -0
- package/dist/node_modules/undici/docs/docs/api/Fetch.md +60 -0
- package/dist/node_modules/undici/docs/docs/api/GlobalInstallation.md +139 -0
- package/dist/node_modules/undici/docs/docs/api/H2CClient.md +263 -0
- package/dist/node_modules/undici/docs/docs/api/MockAgent.md +603 -0
- package/dist/node_modules/undici/docs/docs/api/MockCallHistory.md +197 -0
- package/dist/node_modules/undici/docs/docs/api/MockCallHistoryLog.md +43 -0
- package/dist/node_modules/undici/docs/docs/api/MockClient.md +81 -0
- package/dist/node_modules/undici/docs/docs/api/MockErrors.md +12 -0
- package/dist/node_modules/undici/docs/docs/api/MockPool.md +555 -0
- package/dist/node_modules/undici/docs/docs/api/Pool.md +84 -0
- package/dist/node_modules/undici/docs/docs/api/PoolStats.md +35 -0
- package/dist/node_modules/undici/docs/docs/api/ProxyAgent.md +229 -0
- package/dist/node_modules/undici/docs/docs/api/RedirectHandler.md +93 -0
- package/dist/node_modules/undici/docs/docs/api/RetryAgent.md +50 -0
- package/dist/node_modules/undici/docs/docs/api/RetryHandler.md +118 -0
- package/dist/node_modules/undici/docs/docs/api/RoundRobinPool.md +145 -0
- package/dist/node_modules/undici/docs/docs/api/SnapshotAgent.md +616 -0
- package/dist/node_modules/undici/docs/docs/api/Socks5ProxyAgent.md +274 -0
- package/dist/node_modules/undici/docs/docs/api/Util.md +25 -0
- package/dist/node_modules/undici/docs/docs/api/WebSocket.md +141 -0
- package/dist/node_modules/undici/docs/docs/api/api-lifecycle.md +91 -0
- package/dist/node_modules/undici/docs/docs/best-practices/client-certificate.md +64 -0
- package/dist/node_modules/undici/docs/docs/best-practices/crawling.md +58 -0
- package/dist/node_modules/undici/docs/docs/best-practices/mocking-request.md +190 -0
- package/dist/node_modules/undici/docs/docs/best-practices/proxy.md +127 -0
- package/dist/node_modules/undici/docs/docs/best-practices/undici-vs-builtin-fetch.md +224 -0
- package/dist/node_modules/undici/docs/docs/best-practices/writing-tests.md +63 -0
- package/dist/node_modules/undici/index-fetch.js +65 -0
- package/dist/node_modules/undici/index.d.ts +3 -0
- package/dist/node_modules/undici/index.js +234 -0
- package/dist/node_modules/undici/lib/api/abort-signal.js +59 -0
- package/dist/node_modules/undici/lib/api/api-connect.js +110 -0
- package/dist/node_modules/undici/lib/api/api-pipeline.js +252 -0
- package/dist/node_modules/undici/lib/api/api-request.js +214 -0
- package/dist/node_modules/undici/lib/api/api-stream.js +209 -0
- package/dist/node_modules/undici/lib/api/api-upgrade.js +111 -0
- package/dist/node_modules/undici/lib/api/index.js +7 -0
- package/dist/node_modules/undici/lib/api/readable.js +580 -0
- package/dist/node_modules/undici/lib/cache/memory-cache-store.js +234 -0
- package/dist/node_modules/undici/lib/cache/sqlite-cache-store.js +461 -0
- package/dist/node_modules/undici/lib/core/connect.js +137 -0
- package/dist/node_modules/undici/lib/core/constants.js +143 -0
- package/dist/node_modules/undici/lib/core/diagnostics.js +227 -0
- package/dist/node_modules/undici/lib/core/errors.js +477 -0
- package/dist/node_modules/undici/lib/core/request.js +438 -0
- package/dist/node_modules/undici/lib/core/socks5-client.js +407 -0
- package/dist/node_modules/undici/lib/core/socks5-utils.js +203 -0
- package/dist/node_modules/undici/lib/core/symbols.js +75 -0
- package/dist/node_modules/undici/lib/core/tree.js +160 -0
- package/dist/node_modules/undici/lib/core/util.js +992 -0
- package/dist/node_modules/undici/lib/dispatcher/agent.js +158 -0
- package/dist/node_modules/undici/lib/dispatcher/balanced-pool.js +219 -0
- package/dist/node_modules/undici/lib/dispatcher/client-h1.js +1610 -0
- package/dist/node_modules/undici/lib/dispatcher/client-h2.js +995 -0
- package/dist/node_modules/undici/lib/dispatcher/client.js +659 -0
- package/dist/node_modules/undici/lib/dispatcher/dispatcher-base.js +165 -0
- package/dist/node_modules/undici/lib/dispatcher/dispatcher.js +48 -0
- package/dist/node_modules/undici/lib/dispatcher/env-http-proxy-agent.js +146 -0
- package/dist/node_modules/undici/lib/dispatcher/fixed-queue.js +135 -0
- package/dist/node_modules/undici/lib/dispatcher/h2c-client.js +51 -0
- package/dist/node_modules/undici/lib/dispatcher/pool-base.js +214 -0
- package/dist/node_modules/undici/lib/dispatcher/pool.js +118 -0
- package/dist/node_modules/undici/lib/dispatcher/proxy-agent.js +318 -0
- package/dist/node_modules/undici/lib/dispatcher/retry-agent.js +35 -0
- package/dist/node_modules/undici/lib/dispatcher/round-robin-pool.js +137 -0
- package/dist/node_modules/undici/lib/dispatcher/socks5-proxy-agent.js +249 -0
- package/dist/node_modules/undici/lib/encoding/index.js +33 -0
- package/dist/node_modules/undici/lib/global.js +50 -0
- package/dist/node_modules/undici/lib/handler/cache-handler.js +578 -0
- package/dist/node_modules/undici/lib/handler/cache-revalidation-handler.js +124 -0
- package/dist/node_modules/undici/lib/handler/decorator-handler.js +67 -0
- package/dist/node_modules/undici/lib/handler/deduplication-handler.js +460 -0
- package/dist/node_modules/undici/lib/handler/redirect-handler.js +238 -0
- package/dist/node_modules/undici/lib/handler/retry-handler.js +394 -0
- package/dist/node_modules/undici/lib/handler/unwrap-handler.js +100 -0
- package/dist/node_modules/undici/lib/handler/wrap-handler.js +105 -0
- package/dist/node_modules/undici/lib/interceptor/cache.js +495 -0
- package/dist/node_modules/undici/lib/interceptor/decompress.js +259 -0
- package/dist/node_modules/undici/lib/interceptor/deduplicate.js +117 -0
- package/dist/node_modules/undici/lib/interceptor/dns.js +571 -0
- package/dist/node_modules/undici/lib/interceptor/dump.js +112 -0
- package/dist/node_modules/undici/lib/interceptor/redirect.js +21 -0
- package/dist/node_modules/undici/lib/interceptor/response-error.js +95 -0
- package/dist/node_modules/undici/lib/interceptor/retry.js +19 -0
- package/dist/node_modules/undici/lib/llhttp/.gitkeep +0 -0
- package/dist/node_modules/undici/lib/llhttp/constants.d.ts +195 -0
- package/dist/node_modules/undici/lib/llhttp/constants.js +531 -0
- package/dist/node_modules/undici/lib/llhttp/llhttp-wasm.js +15 -0
- package/dist/node_modules/undici/lib/llhttp/llhttp_simd-wasm.js +15 -0
- package/dist/node_modules/undici/lib/llhttp/utils.d.ts +2 -0
- package/dist/node_modules/undici/lib/llhttp/utils.js +12 -0
- package/dist/node_modules/undici/lib/mock/mock-agent.js +232 -0
- package/dist/node_modules/undici/lib/mock/mock-call-history.js +248 -0
- package/dist/node_modules/undici/lib/mock/mock-client.js +68 -0
- package/dist/node_modules/undici/lib/mock/mock-errors.js +29 -0
- package/dist/node_modules/undici/lib/mock/mock-interceptor.js +209 -0
- package/dist/node_modules/undici/lib/mock/mock-pool.js +68 -0
- package/dist/node_modules/undici/lib/mock/mock-symbols.js +32 -0
- package/dist/node_modules/undici/lib/mock/mock-utils.js +486 -0
- package/dist/node_modules/undici/lib/mock/pending-interceptors-formatter.js +43 -0
- package/dist/node_modules/undici/lib/mock/snapshot-agent.js +353 -0
- package/dist/node_modules/undici/lib/mock/snapshot-recorder.js +588 -0
- package/dist/node_modules/undici/lib/mock/snapshot-utils.js +158 -0
- package/dist/node_modules/undici/lib/util/cache.js +407 -0
- package/dist/node_modules/undici/lib/util/date.js +653 -0
- package/dist/node_modules/undici/lib/util/promise.js +28 -0
- package/dist/node_modules/undici/lib/util/runtime-features.js +124 -0
- package/dist/node_modules/undici/lib/util/stats.js +32 -0
- package/dist/node_modules/undici/lib/util/timers.js +425 -0
- package/dist/node_modules/undici/lib/web/cache/cache.js +864 -0
- package/dist/node_modules/undici/lib/web/cache/cachestorage.js +152 -0
- package/dist/node_modules/undici/lib/web/cache/util.js +45 -0
- package/dist/node_modules/undici/lib/web/cookies/constants.js +12 -0
- package/dist/node_modules/undici/lib/web/cookies/index.js +199 -0
- package/dist/node_modules/undici/lib/web/cookies/parse.js +322 -0
- package/dist/node_modules/undici/lib/web/cookies/util.js +282 -0
- package/dist/node_modules/undici/lib/web/eventsource/eventsource-stream.js +399 -0
- package/dist/node_modules/undici/lib/web/eventsource/eventsource.js +501 -0
- package/dist/node_modules/undici/lib/web/eventsource/util.js +29 -0
- package/dist/node_modules/undici/lib/web/fetch/LICENSE +21 -0
- package/dist/node_modules/undici/lib/web/fetch/body.js +509 -0
- package/dist/node_modules/undici/lib/web/fetch/constants.js +131 -0
- package/dist/node_modules/undici/lib/web/fetch/data-url.js +596 -0
- package/dist/node_modules/undici/lib/web/fetch/formdata-parser.js +575 -0
- package/dist/node_modules/undici/lib/web/fetch/formdata.js +259 -0
- package/dist/node_modules/undici/lib/web/fetch/global.js +40 -0
- package/dist/node_modules/undici/lib/web/fetch/headers.js +719 -0
- package/dist/node_modules/undici/lib/web/fetch/index.js +2397 -0
- package/dist/node_modules/undici/lib/web/fetch/request.js +1115 -0
- package/dist/node_modules/undici/lib/web/fetch/response.js +641 -0
- package/dist/node_modules/undici/lib/web/fetch/util.js +1520 -0
- package/dist/node_modules/undici/lib/web/infra/index.js +229 -0
- package/dist/node_modules/undici/lib/web/subresource-integrity/Readme.md +9 -0
- package/dist/node_modules/undici/lib/web/subresource-integrity/subresource-integrity.js +307 -0
- package/dist/node_modules/undici/lib/web/webidl/index.js +1006 -0
- package/dist/node_modules/undici/lib/web/websocket/connection.js +329 -0
- package/dist/node_modules/undici/lib/web/websocket/constants.js +126 -0
- package/dist/node_modules/undici/lib/web/websocket/events.js +331 -0
- package/dist/node_modules/undici/lib/web/websocket/frame.js +133 -0
- package/dist/node_modules/undici/lib/web/websocket/permessage-deflate.js +118 -0
- package/dist/node_modules/undici/lib/web/websocket/receiver.js +450 -0
- package/dist/node_modules/undici/lib/web/websocket/sender.js +109 -0
- package/dist/node_modules/undici/lib/web/websocket/stream/websocketerror.js +104 -0
- package/dist/node_modules/undici/lib/web/websocket/stream/websocketstream.js +497 -0
- package/dist/node_modules/undici/lib/web/websocket/util.js +347 -0
- package/dist/node_modules/undici/lib/web/websocket/websocket.js +751 -0
- package/dist/node_modules/undici/package.json +152 -0
- package/dist/node_modules/undici/scripts/strip-comments.js +10 -0
- package/dist/node_modules/undici/types/README.md +6 -0
- package/dist/node_modules/undici/types/agent.d.ts +32 -0
- package/dist/node_modules/undici/types/api.d.ts +43 -0
- package/dist/node_modules/undici/types/balanced-pool.d.ts +30 -0
- package/dist/node_modules/undici/types/cache-interceptor.d.ts +179 -0
- package/dist/node_modules/undici/types/cache.d.ts +36 -0
- package/dist/node_modules/undici/types/client-stats.d.ts +15 -0
- package/dist/node_modules/undici/types/client.d.ts +123 -0
- package/dist/node_modules/undici/types/connector.d.ts +36 -0
- package/dist/node_modules/undici/types/content-type.d.ts +21 -0
- package/dist/node_modules/undici/types/cookies.d.ts +30 -0
- package/dist/node_modules/undici/types/diagnostics-channel.d.ts +74 -0
- package/dist/node_modules/undici/types/dispatcher.d.ts +273 -0
- package/dist/node_modules/undici/types/env-http-proxy-agent.d.ts +22 -0
- package/dist/node_modules/undici/types/errors.d.ts +177 -0
- package/dist/node_modules/undici/types/eventsource.d.ts +66 -0
- package/dist/node_modules/undici/types/fetch.d.ts +231 -0
- package/dist/node_modules/undici/types/formdata.d.ts +114 -0
- package/dist/node_modules/undici/types/global-dispatcher.d.ts +9 -0
- package/dist/node_modules/undici/types/global-origin.d.ts +7 -0
- package/dist/node_modules/undici/types/h2c-client.d.ts +73 -0
- package/dist/node_modules/undici/types/handlers.d.ts +14 -0
- package/dist/node_modules/undici/types/header.d.ts +160 -0
- package/dist/node_modules/undici/types/index.d.ts +91 -0
- package/dist/node_modules/undici/types/interceptors.d.ts +80 -0
- package/dist/node_modules/undici/types/mock-agent.d.ts +68 -0
- package/dist/node_modules/undici/types/mock-call-history.d.ts +111 -0
- package/dist/node_modules/undici/types/mock-client.d.ts +27 -0
- package/dist/node_modules/undici/types/mock-errors.d.ts +12 -0
- package/dist/node_modules/undici/types/mock-interceptor.d.ts +94 -0
- package/dist/node_modules/undici/types/mock-pool.d.ts +27 -0
- package/dist/node_modules/undici/types/patch.d.ts +29 -0
- package/dist/node_modules/undici/types/pool-stats.d.ts +19 -0
- package/dist/node_modules/undici/types/pool.d.ts +41 -0
- package/dist/node_modules/undici/types/proxy-agent.d.ts +29 -0
- package/dist/node_modules/undici/types/readable.d.ts +68 -0
- package/dist/node_modules/undici/types/retry-agent.d.ts +8 -0
- package/dist/node_modules/undici/types/retry-handler.d.ts +125 -0
- package/dist/node_modules/undici/types/round-robin-pool.d.ts +41 -0
- package/dist/node_modules/undici/types/snapshot-agent.d.ts +109 -0
- package/dist/node_modules/undici/types/socks5-proxy-agent.d.ts +25 -0
- package/dist/node_modules/undici/types/util.d.ts +18 -0
- package/dist/node_modules/undici/types/utility.d.ts +7 -0
- package/dist/node_modules/undici/types/webidl.d.ts +347 -0
- package/dist/node_modules/undici/types/websocket.d.ts +188 -0
- package/dist/server/collections/oidcStates.d.ts +10 -0
- package/dist/server/collections/oidcStates.js +96 -0
- package/dist/server/db-adapter.d.ts +25 -0
- package/dist/server/db-adapter.js +156 -0
- package/dist/server/service.js +11 -10
- package/package.json +2 -2
- package/dist/server/cache-adapter.d.ts +0 -33
- package/dist/server/cache-adapter.js +0 -159
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { parseHeaders } = require('../core/util')
|
|
4
|
+
const { InvalidArgumentError } = require('../core/errors')
|
|
5
|
+
|
|
6
|
+
const kResume = Symbol('resume')
|
|
7
|
+
|
|
8
|
+
class UnwrapController {
|
|
9
|
+
#paused = false
|
|
10
|
+
#reason = null
|
|
11
|
+
#aborted = false
|
|
12
|
+
#abort
|
|
13
|
+
|
|
14
|
+
[kResume] = null
|
|
15
|
+
|
|
16
|
+
constructor (abort) {
|
|
17
|
+
this.#abort = abort
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
pause () {
|
|
21
|
+
this.#paused = true
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
resume () {
|
|
25
|
+
if (this.#paused) {
|
|
26
|
+
this.#paused = false
|
|
27
|
+
this[kResume]?.()
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
abort (reason) {
|
|
32
|
+
if (!this.#aborted) {
|
|
33
|
+
this.#aborted = true
|
|
34
|
+
this.#reason = reason
|
|
35
|
+
this.#abort(reason)
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
get aborted () {
|
|
40
|
+
return this.#aborted
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
get reason () {
|
|
44
|
+
return this.#reason
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
get paused () {
|
|
48
|
+
return this.#paused
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
module.exports = class UnwrapHandler {
|
|
53
|
+
#handler
|
|
54
|
+
#controller
|
|
55
|
+
|
|
56
|
+
constructor (handler) {
|
|
57
|
+
this.#handler = handler
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
static unwrap (handler) {
|
|
61
|
+
// TODO (fix): More checks...
|
|
62
|
+
return !handler.onRequestStart ? handler : new UnwrapHandler(handler)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
onConnect (abort, context) {
|
|
66
|
+
this.#controller = new UnwrapController(abort)
|
|
67
|
+
this.#handler.onRequestStart?.(this.#controller, context)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
onResponseStarted () {
|
|
71
|
+
return this.#handler.onResponseStarted?.()
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
onUpgrade (statusCode, rawHeaders, socket) {
|
|
75
|
+
this.#handler.onRequestUpgrade?.(this.#controller, statusCode, parseHeaders(rawHeaders), socket)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
onHeaders (statusCode, rawHeaders, resume, statusMessage) {
|
|
79
|
+
this.#controller[kResume] = resume
|
|
80
|
+
this.#handler.onResponseStart?.(this.#controller, statusCode, parseHeaders(rawHeaders), statusMessage)
|
|
81
|
+
return !this.#controller.paused
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
onData (data) {
|
|
85
|
+
this.#handler.onResponseData?.(this.#controller, data)
|
|
86
|
+
return !this.#controller.paused
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
onComplete (rawTrailers) {
|
|
90
|
+
this.#handler.onResponseEnd?.(this.#controller, parseHeaders(rawTrailers))
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
onError (err) {
|
|
94
|
+
if (!this.#handler.onResponseError) {
|
|
95
|
+
throw new InvalidArgumentError('invalid onError method')
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
this.#handler.onResponseError?.(this.#controller, err)
|
|
99
|
+
}
|
|
100
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { InvalidArgumentError } = require('../core/errors')
|
|
4
|
+
|
|
5
|
+
module.exports = class WrapHandler {
|
|
6
|
+
#handler
|
|
7
|
+
|
|
8
|
+
constructor (handler) {
|
|
9
|
+
this.#handler = handler
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
static wrap (handler) {
|
|
13
|
+
// TODO (fix): More checks...
|
|
14
|
+
return handler.onRequestStart ? handler : new WrapHandler(handler)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// Unwrap Interface
|
|
18
|
+
|
|
19
|
+
onConnect (abort, context) {
|
|
20
|
+
return this.#handler.onConnect?.(abort, context)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
onResponseStarted () {
|
|
24
|
+
return this.#handler.onResponseStarted?.()
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
onHeaders (statusCode, rawHeaders, resume, statusMessage) {
|
|
28
|
+
return this.#handler.onHeaders?.(statusCode, rawHeaders, resume, statusMessage)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
onUpgrade (statusCode, rawHeaders, socket) {
|
|
32
|
+
return this.#handler.onUpgrade?.(statusCode, rawHeaders, socket)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
onData (data) {
|
|
36
|
+
return this.#handler.onData?.(data)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
onComplete (trailers) {
|
|
40
|
+
return this.#handler.onComplete?.(trailers)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
onError (err) {
|
|
44
|
+
if (!this.#handler.onError) {
|
|
45
|
+
throw err
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return this.#handler.onError?.(err)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Wrap Interface
|
|
52
|
+
|
|
53
|
+
onRequestStart (controller, context) {
|
|
54
|
+
this.#handler.onConnect?.((reason) => controller.abort(reason), context)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
onRequestUpgrade (controller, statusCode, headers, socket) {
|
|
58
|
+
const rawHeaders = []
|
|
59
|
+
for (const [key, val] of Object.entries(headers)) {
|
|
60
|
+
rawHeaders.push(Buffer.from(key, 'latin1'), toRawHeaderValue(val))
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
this.#handler.onUpgrade?.(statusCode, rawHeaders, socket)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
onResponseStart (controller, statusCode, headers, statusMessage) {
|
|
67
|
+
const rawHeaders = []
|
|
68
|
+
for (const [key, val] of Object.entries(headers)) {
|
|
69
|
+
rawHeaders.push(Buffer.from(key, 'latin1'), toRawHeaderValue(val))
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (this.#handler.onHeaders?.(statusCode, rawHeaders, () => controller.resume(), statusMessage) === false) {
|
|
73
|
+
controller.pause()
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
onResponseData (controller, data) {
|
|
78
|
+
if (this.#handler.onData?.(data) === false) {
|
|
79
|
+
controller.pause()
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
onResponseEnd (controller, trailers) {
|
|
84
|
+
const rawTrailers = []
|
|
85
|
+
for (const [key, val] of Object.entries(trailers)) {
|
|
86
|
+
rawTrailers.push(Buffer.from(key, 'latin1'), toRawHeaderValue(val))
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
this.#handler.onComplete?.(rawTrailers)
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
onResponseError (controller, err) {
|
|
93
|
+
if (!this.#handler.onError) {
|
|
94
|
+
throw new InvalidArgumentError('invalid onError method')
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
this.#handler.onError?.(err)
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function toRawHeaderValue (value) {
|
|
102
|
+
return Array.isArray(value)
|
|
103
|
+
? value.map((item) => Buffer.from(item, 'latin1'))
|
|
104
|
+
: Buffer.from(value, 'latin1')
|
|
105
|
+
}
|
|
@@ -0,0 +1,495 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const assert = require('node:assert')
|
|
4
|
+
const { Readable } = require('node:stream')
|
|
5
|
+
const util = require('../core/util')
|
|
6
|
+
const CacheHandler = require('../handler/cache-handler')
|
|
7
|
+
const MemoryCacheStore = require('../cache/memory-cache-store')
|
|
8
|
+
const CacheRevalidationHandler = require('../handler/cache-revalidation-handler')
|
|
9
|
+
const { assertCacheStore, assertCacheMethods, makeCacheKey, normalizeHeaders, parseCacheControlHeader } = require('../util/cache.js')
|
|
10
|
+
const { AbortError } = require('../core/errors.js')
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* @param {(string | RegExp)[] | undefined} origins
|
|
14
|
+
* @param {string} name
|
|
15
|
+
*/
|
|
16
|
+
function assertCacheOrigins (origins, name) {
|
|
17
|
+
if (origins === undefined) return
|
|
18
|
+
if (!Array.isArray(origins)) {
|
|
19
|
+
throw new TypeError(`expected ${name} to be an array or undefined, got ${typeof origins}`)
|
|
20
|
+
}
|
|
21
|
+
for (let i = 0; i < origins.length; i++) {
|
|
22
|
+
const origin = origins[i]
|
|
23
|
+
if (typeof origin !== 'string' && !(origin instanceof RegExp)) {
|
|
24
|
+
throw new TypeError(`expected ${name}[${i}] to be a string or RegExp, got ${typeof origin}`)
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const nop = () => {}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* @typedef {(options: import('../../types/dispatcher.d.ts').default.DispatchOptions, handler: import('../../types/dispatcher.d.ts').default.DispatchHandler) => void} DispatchFn
|
|
33
|
+
*/
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* @param {import('../../types/cache-interceptor.d.ts').default.GetResult} result
|
|
37
|
+
* @param {import('../../types/cache-interceptor.d.ts').default.CacheControlDirectives | undefined} cacheControlDirectives
|
|
38
|
+
* @param {import('../../types/dispatcher.d.ts').default.RequestOptions} opts
|
|
39
|
+
* @returns {boolean}
|
|
40
|
+
*/
|
|
41
|
+
function needsRevalidation (result, cacheControlDirectives, { headers = {} }) {
|
|
42
|
+
// Always revalidate requests with the no-cache request directive.
|
|
43
|
+
if (cacheControlDirectives?.['no-cache']) {
|
|
44
|
+
return true
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Always revalidate requests with unqualified no-cache response directive.
|
|
48
|
+
if (result.cacheControlDirectives?.['no-cache'] && !Array.isArray(result.cacheControlDirectives['no-cache'])) {
|
|
49
|
+
return true
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Always revalidate requests with conditional headers.
|
|
53
|
+
if (headers['if-modified-since'] || headers['if-none-match']) {
|
|
54
|
+
return true
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return false
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* @param {import('../../types/cache-interceptor.d.ts').default.GetResult} result
|
|
62
|
+
* @param {import('../../types/cache-interceptor.d.ts').default.CacheControlDirectives | undefined} cacheControlDirectives
|
|
63
|
+
* @returns {boolean}
|
|
64
|
+
*/
|
|
65
|
+
function isStale (result, cacheControlDirectives) {
|
|
66
|
+
const now = Date.now()
|
|
67
|
+
if (now > result.staleAt) {
|
|
68
|
+
// Response is stale
|
|
69
|
+
if (cacheControlDirectives?.['max-stale']) {
|
|
70
|
+
// There's a threshold where we can serve stale responses, let's see if
|
|
71
|
+
// we're in it
|
|
72
|
+
// https://www.rfc-editor.org/rfc/rfc9111.html#name-max-stale
|
|
73
|
+
const gracePeriod = result.staleAt + (cacheControlDirectives['max-stale'] * 1000)
|
|
74
|
+
return now > gracePeriod
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return true
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (cacheControlDirectives?.['min-fresh']) {
|
|
81
|
+
// https://www.rfc-editor.org/rfc/rfc9111.html#section-5.2.1.3
|
|
82
|
+
|
|
83
|
+
// At this point, staleAt is always > now
|
|
84
|
+
const timeLeftTillStale = result.staleAt - now
|
|
85
|
+
const threshold = cacheControlDirectives['min-fresh'] * 1000
|
|
86
|
+
|
|
87
|
+
return timeLeftTillStale <= threshold
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return false
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Check if we're within the stale-while-revalidate window for a stale response
|
|
95
|
+
* @param {import('../../types/cache-interceptor.d.ts').default.GetResult} result
|
|
96
|
+
* @returns {boolean}
|
|
97
|
+
*/
|
|
98
|
+
function withinStaleWhileRevalidateWindow (result) {
|
|
99
|
+
const staleWhileRevalidate = result.cacheControlDirectives?.['stale-while-revalidate']
|
|
100
|
+
if (!staleWhileRevalidate) {
|
|
101
|
+
return false
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const now = Date.now()
|
|
105
|
+
const staleWhileRevalidateExpiry = result.staleAt + (staleWhileRevalidate * 1000)
|
|
106
|
+
return now <= staleWhileRevalidateExpiry
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* @param {DispatchFn} dispatch
|
|
111
|
+
* @param {import('../../types/cache-interceptor.d.ts').default.CacheHandlerOptions} globalOpts
|
|
112
|
+
* @param {import('../../types/cache-interceptor.d.ts').default.CacheKey} cacheKey
|
|
113
|
+
* @param {import('../../types/dispatcher.d.ts').default.DispatchHandler} handler
|
|
114
|
+
* @param {import('../../types/dispatcher.d.ts').default.RequestOptions} opts
|
|
115
|
+
* @param {import('../../types/cache-interceptor.d.ts').default.CacheControlDirectives | undefined} reqCacheControl
|
|
116
|
+
*/
|
|
117
|
+
function handleUncachedResponse (
|
|
118
|
+
dispatch,
|
|
119
|
+
globalOpts,
|
|
120
|
+
cacheKey,
|
|
121
|
+
handler,
|
|
122
|
+
opts,
|
|
123
|
+
reqCacheControl
|
|
124
|
+
) {
|
|
125
|
+
if (reqCacheControl?.['only-if-cached']) {
|
|
126
|
+
let aborted = false
|
|
127
|
+
try {
|
|
128
|
+
if (typeof handler.onConnect === 'function') {
|
|
129
|
+
handler.onConnect(() => {
|
|
130
|
+
aborted = true
|
|
131
|
+
})
|
|
132
|
+
|
|
133
|
+
if (aborted) {
|
|
134
|
+
return
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
if (typeof handler.onHeaders === 'function') {
|
|
139
|
+
handler.onHeaders(504, [], nop, 'Gateway Timeout')
|
|
140
|
+
if (aborted) {
|
|
141
|
+
return
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
if (typeof handler.onComplete === 'function') {
|
|
146
|
+
handler.onComplete([])
|
|
147
|
+
}
|
|
148
|
+
} catch (err) {
|
|
149
|
+
if (typeof handler.onError === 'function') {
|
|
150
|
+
handler.onError(err)
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
return true
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
return dispatch(opts, new CacheHandler(globalOpts, cacheKey, handler))
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* @param {import('../../types/dispatcher.d.ts').default.DispatchHandler} handler
|
|
162
|
+
* @param {import('../../types/dispatcher.d.ts').default.RequestOptions} opts
|
|
163
|
+
* @param {import('../../types/cache-interceptor.d.ts').default.GetResult} result
|
|
164
|
+
* @param {number} age
|
|
165
|
+
* @param {any} context
|
|
166
|
+
* @param {boolean} isStale
|
|
167
|
+
*/
|
|
168
|
+
function sendCachedValue (handler, opts, result, age, context, isStale) {
|
|
169
|
+
// TODO (perf): Readable.from path can be optimized...
|
|
170
|
+
const stream = util.isStream(result.body)
|
|
171
|
+
? result.body
|
|
172
|
+
: Readable.from(result.body ?? [])
|
|
173
|
+
|
|
174
|
+
assert(!stream.destroyed, 'stream should not be destroyed')
|
|
175
|
+
assert(!stream.readableDidRead, 'stream should not be readableDidRead')
|
|
176
|
+
|
|
177
|
+
const controller = {
|
|
178
|
+
resume () {
|
|
179
|
+
stream.resume()
|
|
180
|
+
},
|
|
181
|
+
pause () {
|
|
182
|
+
stream.pause()
|
|
183
|
+
},
|
|
184
|
+
get paused () {
|
|
185
|
+
return stream.isPaused()
|
|
186
|
+
},
|
|
187
|
+
get aborted () {
|
|
188
|
+
return stream.destroyed
|
|
189
|
+
},
|
|
190
|
+
get reason () {
|
|
191
|
+
return stream.errored
|
|
192
|
+
},
|
|
193
|
+
abort (reason) {
|
|
194
|
+
stream.destroy(reason ?? new AbortError())
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
stream
|
|
199
|
+
.on('error', function (err) {
|
|
200
|
+
if (!this.readableEnded) {
|
|
201
|
+
if (typeof handler.onResponseError === 'function') {
|
|
202
|
+
handler.onResponseError(controller, err)
|
|
203
|
+
} else {
|
|
204
|
+
throw err
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
})
|
|
208
|
+
.on('close', function () {
|
|
209
|
+
if (!this.errored) {
|
|
210
|
+
handler.onResponseEnd?.(controller, {})
|
|
211
|
+
}
|
|
212
|
+
})
|
|
213
|
+
|
|
214
|
+
handler.onRequestStart?.(controller, context)
|
|
215
|
+
|
|
216
|
+
if (stream.destroyed) {
|
|
217
|
+
return
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// Add the age header
|
|
221
|
+
// https://www.rfc-editor.org/rfc/rfc9111.html#name-age
|
|
222
|
+
const headers = { ...result.headers, age: String(age) }
|
|
223
|
+
|
|
224
|
+
if (isStale) {
|
|
225
|
+
// Add warning header
|
|
226
|
+
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Warning
|
|
227
|
+
headers.warning = '110 - "response is stale"'
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
handler.onResponseStart?.(controller, result.statusCode, headers, result.statusMessage)
|
|
231
|
+
|
|
232
|
+
if (opts.method === 'HEAD') {
|
|
233
|
+
stream.destroy()
|
|
234
|
+
} else {
|
|
235
|
+
stream.on('data', function (chunk) {
|
|
236
|
+
handler.onResponseData?.(controller, chunk)
|
|
237
|
+
})
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* @param {DispatchFn} dispatch
|
|
243
|
+
* @param {import('../../types/cache-interceptor.d.ts').default.CacheHandlerOptions} globalOpts
|
|
244
|
+
* @param {import('../../types/cache-interceptor.d.ts').default.CacheKey} cacheKey
|
|
245
|
+
* @param {import('../../types/dispatcher.d.ts').default.DispatchHandler} handler
|
|
246
|
+
* @param {import('../../types/dispatcher.d.ts').default.RequestOptions} opts
|
|
247
|
+
* @param {import('../../types/cache-interceptor.d.ts').default.CacheControlDirectives | undefined} reqCacheControl
|
|
248
|
+
* @param {import('../../types/cache-interceptor.d.ts').default.GetResult | undefined} result
|
|
249
|
+
*/
|
|
250
|
+
function handleResult (
|
|
251
|
+
dispatch,
|
|
252
|
+
globalOpts,
|
|
253
|
+
cacheKey,
|
|
254
|
+
handler,
|
|
255
|
+
opts,
|
|
256
|
+
reqCacheControl,
|
|
257
|
+
result
|
|
258
|
+
) {
|
|
259
|
+
if (!result) {
|
|
260
|
+
return handleUncachedResponse(dispatch, globalOpts, cacheKey, handler, opts, reqCacheControl)
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
const now = Date.now()
|
|
264
|
+
if (now > result.deleteAt) {
|
|
265
|
+
// Response is expired, cache store shouldn't have given this to us
|
|
266
|
+
return dispatch(opts, new CacheHandler(globalOpts, cacheKey, handler))
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
const age = Math.round((now - result.cachedAt) / 1000)
|
|
270
|
+
if (reqCacheControl?.['max-age'] && age >= reqCacheControl['max-age']) {
|
|
271
|
+
// Response is considered expired for this specific request
|
|
272
|
+
// https://www.rfc-editor.org/rfc/rfc9111.html#section-5.2.1.1
|
|
273
|
+
return dispatch(opts, handler)
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
const stale = isStale(result, reqCacheControl)
|
|
277
|
+
const revalidate = needsRevalidation(result, reqCacheControl, opts)
|
|
278
|
+
|
|
279
|
+
// Check if the response is stale
|
|
280
|
+
if (stale || revalidate) {
|
|
281
|
+
if (util.isStream(opts.body) && util.bodyLength(opts.body) !== 0) {
|
|
282
|
+
// If body is a stream we can't revalidate...
|
|
283
|
+
// TODO (fix): This could be less strict...
|
|
284
|
+
return dispatch(opts, new CacheHandler(globalOpts, cacheKey, handler))
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
// RFC 5861: If we're within stale-while-revalidate window, serve stale immediately
|
|
288
|
+
// and revalidate in background, unless immediate revalidation is necessary
|
|
289
|
+
if (!revalidate && withinStaleWhileRevalidateWindow(result)) {
|
|
290
|
+
// Serve stale response immediately
|
|
291
|
+
sendCachedValue(handler, opts, result, age, null, true)
|
|
292
|
+
|
|
293
|
+
// Start background revalidation (fire-and-forget)
|
|
294
|
+
queueMicrotask(() => {
|
|
295
|
+
const headers = {
|
|
296
|
+
...opts.headers,
|
|
297
|
+
'if-modified-since': new Date(result.cachedAt).toUTCString()
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
if (result.etag) {
|
|
301
|
+
headers['if-none-match'] = result.etag
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
if (result.vary) {
|
|
305
|
+
for (const key in result.vary) {
|
|
306
|
+
if (result.vary[key] != null) {
|
|
307
|
+
headers[key] = result.vary[key]
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
// Background revalidation - update cache if we get new data
|
|
313
|
+
dispatch(
|
|
314
|
+
{
|
|
315
|
+
...opts,
|
|
316
|
+
headers
|
|
317
|
+
},
|
|
318
|
+
new CacheHandler(globalOpts, cacheKey, {
|
|
319
|
+
// Silent handler that just updates the cache
|
|
320
|
+
onRequestStart () {},
|
|
321
|
+
onRequestUpgrade () {},
|
|
322
|
+
onResponseStart () {},
|
|
323
|
+
onResponseData () {},
|
|
324
|
+
onResponseEnd () {},
|
|
325
|
+
onResponseError () {}
|
|
326
|
+
})
|
|
327
|
+
)
|
|
328
|
+
})
|
|
329
|
+
|
|
330
|
+
return true
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
let withinStaleIfErrorThreshold = false
|
|
334
|
+
const staleIfErrorExpiry = result.cacheControlDirectives['stale-if-error'] ?? reqCacheControl?.['stale-if-error']
|
|
335
|
+
if (staleIfErrorExpiry) {
|
|
336
|
+
withinStaleIfErrorThreshold = now < (result.staleAt + (staleIfErrorExpiry * 1000))
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
const headers = {
|
|
340
|
+
...opts.headers,
|
|
341
|
+
'if-modified-since': new Date(result.cachedAt).toUTCString()
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
if (result.etag) {
|
|
345
|
+
headers['if-none-match'] = result.etag
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
if (result.vary) {
|
|
349
|
+
for (const key in result.vary) {
|
|
350
|
+
if (result.vary[key] != null) {
|
|
351
|
+
headers[key] = result.vary[key]
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
// We need to revalidate the response
|
|
357
|
+
return dispatch(
|
|
358
|
+
{
|
|
359
|
+
...opts,
|
|
360
|
+
headers
|
|
361
|
+
},
|
|
362
|
+
new CacheRevalidationHandler(
|
|
363
|
+
(success, context) => {
|
|
364
|
+
if (success) {
|
|
365
|
+
// TODO: successful revalidation should be considered fresh (not give stale warning).
|
|
366
|
+
sendCachedValue(handler, opts, result, age, context, stale)
|
|
367
|
+
} else if (util.isStream(result.body)) {
|
|
368
|
+
result.body.on('error', nop).destroy()
|
|
369
|
+
}
|
|
370
|
+
},
|
|
371
|
+
new CacheHandler(globalOpts, cacheKey, handler),
|
|
372
|
+
withinStaleIfErrorThreshold
|
|
373
|
+
)
|
|
374
|
+
)
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
// Dump request body.
|
|
378
|
+
if (util.isStream(opts.body)) {
|
|
379
|
+
opts.body.on('error', nop).destroy()
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
sendCachedValue(handler, opts, result, age, null, false)
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
/**
|
|
386
|
+
* @param {import('../../types/cache-interceptor.d.ts').default.CacheOptions} [opts]
|
|
387
|
+
* @returns {import('../../types/dispatcher.d.ts').default.DispatcherComposeInterceptor}
|
|
388
|
+
*/
|
|
389
|
+
module.exports = (opts = {}) => {
|
|
390
|
+
const {
|
|
391
|
+
store = new MemoryCacheStore(),
|
|
392
|
+
methods = ['GET'],
|
|
393
|
+
cacheByDefault = undefined,
|
|
394
|
+
type = 'shared',
|
|
395
|
+
origins = undefined
|
|
396
|
+
} = opts
|
|
397
|
+
|
|
398
|
+
if (typeof opts !== 'object' || opts === null) {
|
|
399
|
+
throw new TypeError(`expected type of opts to be an Object, got ${opts === null ? 'null' : typeof opts}`)
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
assertCacheStore(store, 'opts.store')
|
|
403
|
+
assertCacheMethods(methods, 'opts.methods')
|
|
404
|
+
assertCacheOrigins(origins, 'opts.origins')
|
|
405
|
+
|
|
406
|
+
if (typeof cacheByDefault !== 'undefined' && typeof cacheByDefault !== 'number') {
|
|
407
|
+
throw new TypeError(`expected opts.cacheByDefault to be number or undefined, got ${typeof cacheByDefault}`)
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
if (typeof type !== 'undefined' && type !== 'shared' && type !== 'private') {
|
|
411
|
+
throw new TypeError(`expected opts.type to be shared, private, or undefined, got ${typeof type}`)
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
const globalOpts = {
|
|
415
|
+
store,
|
|
416
|
+
methods,
|
|
417
|
+
cacheByDefault,
|
|
418
|
+
type
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
const safeMethodsToNotCache = util.safeHTTPMethods.filter(method => methods.includes(method) === false)
|
|
422
|
+
|
|
423
|
+
return dispatch => {
|
|
424
|
+
return (opts, handler) => {
|
|
425
|
+
if (!opts.origin || safeMethodsToNotCache.includes(opts.method)) {
|
|
426
|
+
// Not a method we want to cache or we don't have the origin, skip
|
|
427
|
+
return dispatch(opts, handler)
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
// Check if origin is in whitelist
|
|
431
|
+
if (origins !== undefined) {
|
|
432
|
+
const requestOrigin = opts.origin.toString().toLowerCase()
|
|
433
|
+
let isAllowed = false
|
|
434
|
+
|
|
435
|
+
for (let i = 0; i < origins.length; i++) {
|
|
436
|
+
const allowed = origins[i]
|
|
437
|
+
if (typeof allowed === 'string') {
|
|
438
|
+
if (allowed.toLowerCase() === requestOrigin) {
|
|
439
|
+
isAllowed = true
|
|
440
|
+
break
|
|
441
|
+
}
|
|
442
|
+
} else if (allowed.test(requestOrigin)) {
|
|
443
|
+
isAllowed = true
|
|
444
|
+
break
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
if (!isAllowed) {
|
|
449
|
+
return dispatch(opts, handler)
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
opts = {
|
|
454
|
+
...opts,
|
|
455
|
+
headers: normalizeHeaders(opts)
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
const reqCacheControl = opts.headers?.['cache-control']
|
|
459
|
+
? parseCacheControlHeader(opts.headers['cache-control'])
|
|
460
|
+
: undefined
|
|
461
|
+
|
|
462
|
+
if (reqCacheControl?.['no-store']) {
|
|
463
|
+
return dispatch(opts, handler)
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
/**
|
|
467
|
+
* @type {import('../../types/cache-interceptor.d.ts').default.CacheKey}
|
|
468
|
+
*/
|
|
469
|
+
const cacheKey = makeCacheKey(opts)
|
|
470
|
+
const result = store.get(cacheKey)
|
|
471
|
+
|
|
472
|
+
if (result && typeof result.then === 'function') {
|
|
473
|
+
return result
|
|
474
|
+
.then(result => handleResult(dispatch,
|
|
475
|
+
globalOpts,
|
|
476
|
+
cacheKey,
|
|
477
|
+
handler,
|
|
478
|
+
opts,
|
|
479
|
+
reqCacheControl,
|
|
480
|
+
result
|
|
481
|
+
))
|
|
482
|
+
} else {
|
|
483
|
+
return handleResult(
|
|
484
|
+
dispatch,
|
|
485
|
+
globalOpts,
|
|
486
|
+
cacheKey,
|
|
487
|
+
handler,
|
|
488
|
+
opts,
|
|
489
|
+
reqCacheControl,
|
|
490
|
+
result
|
|
491
|
+
)
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
}
|