@floegence/flowersec-core 0.27.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +91 -22
- package/THIRD_PARTY_NOTICES.md +141 -0
- package/dist/browser/connectSession.d.ts +13 -0
- package/dist/browser/connectSession.js +40 -0
- package/dist/browser/index.d.ts +3 -10
- package/dist/browser/index.js +2 -5
- package/dist/browser/runtimeCapability.d.ts +13 -0
- package/dist/browser/runtimeCapability.js +27 -0
- package/dist/browser/sessionRuntime.d.ts +2 -0
- package/dist/browser/sessionRuntime.js +21 -0
- package/dist/browser/webTransportClient.d.ts +8 -0
- package/dist/browser/webTransportClient.js +55 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +126 -0
- package/dist/cliSpendMarker.d.ts +1 -0
- package/dist/cliSpendMarker.js +22 -0
- package/dist/connectionController.d.ts +54 -0
- package/dist/connectionController.js +438 -0
- package/dist/connector/adapters/webSocketCandidate.d.ts +7 -0
- package/dist/connector/adapters/webSocketCandidate.js +116 -0
- package/dist/connector/adapters/webTransportCandidate.d.ts +5 -0
- package/dist/connector/adapters/webTransportCandidate.js +73 -0
- package/dist/connector/admissionCommit.d.ts +31 -0
- package/dist/connector/admissionCommit.js +239 -0
- package/dist/connector/sessionAcceptor.d.ts +16 -0
- package/dist/connector/sessionAcceptor.js +114 -0
- package/dist/connector/sessionConfig.d.ts +3 -0
- package/dist/connector/sessionConfig.js +30 -0
- package/dist/connector/sessionConnector.d.ts +45 -0
- package/dist/connector/sessionConnector.js +603 -0
- package/dist/defaults.d.ts +7 -7
- package/dist/defaults.js +7 -7
- package/dist/facade.d.ts +12 -27
- package/dist/facade.js +6 -24
- package/dist/node/connectSession.d.ts +21 -0
- package/dist/node/connectSession.js +62 -0
- package/dist/node/index.d.ts +3 -11
- package/dist/node/index.js +2 -8
- package/dist/node/runtimeCapability.d.ts +7 -0
- package/dist/node/runtimeCapability.js +10 -0
- package/dist/node/sessionRuntime.d.ts +2 -0
- package/dist/node/sessionRuntime.js +13 -0
- package/dist/node/webTransportClient.d.ts +9 -0
- package/dist/node/webTransportClient.js +56 -0
- package/dist/node/webTransportServer.d.ts +22 -0
- package/dist/node/webTransportServer.js +100 -0
- package/dist/node/wsFactory.d.ts +3 -1
- package/dist/node/wsFactory.js +4 -3
- package/dist/proxy/controllerGuard.d.ts +4 -4
- package/dist/proxy/controllerGuard.js +83 -177
- package/dist/proxy/disableUpstreamServiceWorkerRegister.d.ts +3 -1
- package/dist/proxy/disableUpstreamServiceWorkerRegister.js +19 -17
- package/dist/proxy/index.d.ts +16 -15
- package/dist/proxy/index.js +8 -14
- package/dist/proxy/integration.d.ts +23 -71
- package/dist/proxy/integration.js +37 -340
- package/dist/proxy/registerServiceWorker.d.ts +1 -10
- package/dist/proxy/registerServiceWorker.js +43 -105
- package/dist/proxy/runtime.d.ts +3 -63
- package/dist/proxy/runtime.js +349 -462
- package/dist/proxy/scope.d.ts +6 -0
- package/dist/proxy/scope.js +131 -0
- package/dist/proxy/serviceWorker.d.ts +5 -16
- package/dist/proxy/serviceWorker.js +230 -617
- package/dist/proxy/stream.d.ts +9 -0
- package/dist/proxy/stream.js +40 -0
- package/dist/proxy/types.d.ts +78 -30
- package/dist/proxy/windowBridge.d.ts +61 -0
- package/dist/proxy/windowBridge.js +344 -0
- package/dist/proxy/wsPatch.d.ts +4 -14
- package/dist/proxy/wsPatch.js +173 -268
- package/dist/public/artifact.d.ts +11 -0
- package/dist/public/artifact.js +44 -0
- package/dist/public/artifactLease.d.ts +10 -0
- package/dist/public/artifactLease.js +48 -0
- package/dist/public/connectError.d.ts +6 -0
- package/dist/public/connectError.js +9 -0
- package/dist/public/contract.d.ts +83 -0
- package/dist/public/contract.js +17 -0
- package/dist/public/streamMetadata.d.ts +10 -0
- package/dist/public/streamMetadata.js +40 -0
- package/dist/rpc/caller.d.ts +1 -1
- package/dist/rpc/client.d.ts +1 -4
- package/dist/rpc/client.js +0 -21
- package/dist/rpc/rpcProxy.d.ts +1 -1
- package/dist/rpc/server.d.ts +1 -1
- package/dist/rpc/validate.d.ts +1 -1
- package/dist/rpc/wire.d.ts +15 -0
- package/dist/runtime/errors.d.ts +6 -0
- package/dist/runtime/errors.js +10 -0
- package/dist/transport/webSocketAdapter.d.ts +24 -0
- package/dist/transport/webSocketAdapter.js +234 -0
- package/dist/transport/webTransportAdapter.d.ts +27 -0
- package/dist/transport/webTransportAdapter.js +519 -0
- package/dist/utils/errors.d.ts +2 -20
- package/dist/utils/errors.js +73 -20
- package/dist/v2/admissionError.d.ts +4 -0
- package/dist/v2/admissionError.js +8 -0
- package/dist/v2/artifact.d.ts +128 -0
- package/dist/v2/artifact.js +1126 -0
- package/dist/v2/artifactLease.d.ts +1 -0
- package/dist/v2/artifactLease.js +7 -0
- package/dist/v2/capability.d.ts +29 -0
- package/dist/v2/capability.js +190 -0
- package/dist/v2/carrier.d.ts +79 -0
- package/dist/v2/carrier.js +405 -0
- package/dist/v2/contract.d.ts +37 -0
- package/dist/v2/contract.js +1 -0
- package/dist/v2/handshake.d.ts +80 -0
- package/dist/v2/handshake.js +470 -0
- package/dist/v2/opaqueArtifact.d.ts +1 -0
- package/dist/v2/opaqueArtifact.js +2 -0
- package/dist/v2/protocol.d.ts +99 -0
- package/dist/v2/protocol.js +739 -0
- package/dist/v2/publicSession.d.ts +1 -0
- package/dist/v2/publicSession.js +179 -0
- package/dist/v2/retryDisposition.d.ts +16 -0
- package/dist/v2/retryDisposition.js +30 -0
- package/dist/v2/session.d.ts +277 -0
- package/dist/v2/session.js +1879 -0
- package/dist/v2/streamLifetimeLedger.d.ts +31 -0
- package/dist/v2/streamLifetimeLedger.js +131 -0
- package/dist/v2/streamMetadata.d.ts +1 -0
- package/dist/v2/streamMetadata.js +7 -0
- package/dist/v2/unreliableMessage.d.ts +43 -0
- package/dist/v2/unreliableMessage.js +252 -0
- package/dist/vendor/tr46.d.ts +10 -0
- package/dist/vendor/tr46.js +501 -0
- package/dist/ws-client/binaryTransport.d.ts +0 -3
- package/dist/ws-client/binaryTransport.js +15 -39
- package/dist/yamux/errors.d.ts +0 -4
- package/dist/yamux/errors.js +0 -9
- package/dist/yamux/session.d.ts +0 -5
- package/dist/yamux/session.js +4 -70
- package/dist/yamux/stream.d.ts +1 -0
- package/dist/yamux/stream.js +4 -0
- package/package.json +29 -81
- package/sbom/cyclonedx.json +2764 -0
- package/sbom/spdx.json +1947 -0
- package/YAMUX_ALIGNMENT.md +0 -127
- package/dist/_examples/flowersec/demo/v1.facade.gen.d.ts +0 -12
- package/dist/_examples/flowersec/demo/v1.facade.gen.js +0 -15
- package/dist/_examples/flowersec/demo/v1.gen.d.ts +0 -16
- package/dist/_examples/flowersec/demo/v1.gen.js +0 -86
- package/dist/_examples/flowersec/demo/v1.rpc.gen.d.ts +0 -11
- package/dist/_examples/flowersec/demo/v1.rpc.gen.js +0 -22
- package/dist/browser/connect.d.ts +0 -13
- package/dist/browser/connect.js +0 -31
- package/dist/browser/reconnectConfig.d.ts +0 -15
- package/dist/browser/reconnectConfig.js +0 -20
- package/dist/client-connect/common.d.ts +0 -26
- package/dist/client-connect/common.js +0 -167
- package/dist/client-connect/connectCore.d.ts +0 -61
- package/dist/client-connect/connectCore.js +0 -572
- package/dist/client-connect/contract.d.ts +0 -8
- package/dist/client-connect/contract.js +0 -51
- package/dist/client-connect/termination.d.ts +0 -6
- package/dist/client-connect/termination.js +0 -7
- package/dist/client-connect/transportSecurity.d.ts +0 -27
- package/dist/client-connect/transportSecurity.js +0 -199
- package/dist/client-connect/tunnelAttachCloseReason.d.ts +0 -3
- package/dist/client-connect/tunnelAttachCloseReason.js +0 -23
- package/dist/client.d.ts +0 -23
- package/dist/connect/artifact.d.ts +0 -36
- package/dist/connect/artifact.js +0 -213
- package/dist/connect/resolveArtifact.d.ts +0 -22
- package/dist/connect/resolveArtifact.js +0 -87
- package/dist/controlplane/channelInit.d.ts +0 -27
- package/dist/controlplane/channelInit.js +0 -116
- package/dist/controlplane/http.d.ts +0 -16
- package/dist/controlplane/http.js +0 -59
- package/dist/controlplane/index.d.ts +0 -6
- package/dist/controlplane/index.js +0 -5
- package/dist/controlplane/issuer.d.ts +0 -18
- package/dist/controlplane/issuer.js +0 -113
- package/dist/controlplane/request.d.ts +0 -51
- package/dist/controlplane/request.js +0 -273
- package/dist/controlplane/token.d.ts +0 -33
- package/dist/controlplane/token.js +0 -119
- package/dist/direct-client/connect.d.ts +0 -9
- package/dist/direct-client/connect.js +0 -90
- package/dist/direct-client/index.d.ts +0 -1
- package/dist/direct-client/index.js +0 -1
- package/dist/e2ee/constants.d.ts +0 -9
- package/dist/e2ee/constants.js +0 -18
- package/dist/e2ee/errors.d.ts +0 -5
- package/dist/e2ee/errors.js +0 -8
- package/dist/e2ee/framing.d.ts +0 -12
- package/dist/e2ee/framing.js +0 -57
- package/dist/e2ee/handshake.d.ts +0 -88
- package/dist/e2ee/handshake.js +0 -353
- package/dist/e2ee/index.d.ts +0 -7
- package/dist/e2ee/index.js +0 -7
- package/dist/e2ee/kdf.d.ts +0 -15
- package/dist/e2ee/kdf.js +0 -39
- package/dist/e2ee/record.d.ts +0 -11
- package/dist/e2ee/record.js +0 -80
- package/dist/e2ee/secureChannel.d.ts +0 -93
- package/dist/e2ee/secureChannel.js +0 -342
- package/dist/e2ee/transcript.d.ts +0 -23
- package/dist/e2ee/transcript.js +0 -31
- package/dist/endpoint/index.d.ts +0 -84
- package/dist/endpoint/index.js +0 -557
- package/dist/endpoint/node.d.ts +0 -9
- package/dist/endpoint/node.js +0 -51
- package/dist/gen/flowersec/controlplane/v1.gen.d.ts +0 -36
- package/dist/gen/flowersec/controlplane/v1.gen.js +0 -135
- package/dist/gen/flowersec/direct/v1.gen.d.ts +0 -21
- package/dist/gen/flowersec/direct/v1.gen.js +0 -101
- package/dist/gen/flowersec/e2ee/v1.gen.d.ts +0 -68
- package/dist/gen/flowersec/e2ee/v1.gen.js +0 -194
- package/dist/gen/flowersec/rpc/v1.gen.d.ts +0 -30
- package/dist/gen/flowersec/rpc/v1.gen.js +0 -107
- package/dist/gen/flowersec/tunnel/v1.gen.d.ts +0 -23
- package/dist/gen/flowersec/tunnel/v1.gen.js +0 -104
- package/dist/index.d.ts +0 -22
- package/dist/index.js +0 -22
- package/dist/node/connect.d.ts +0 -10
- package/dist/node/connect.js +0 -29
- package/dist/node/reconnectConfig.d.ts +0 -16
- package/dist/node/reconnectConfig.js +0 -20
- package/dist/observability/index.d.ts +0 -1
- package/dist/observability/index.js +0 -1
- package/dist/observability/observer.d.ts +0 -52
- package/dist/observability/observer.js +0 -314
- package/dist/proxy/appWindow.d.ts +0 -37
- package/dist/proxy/appWindow.js +0 -273
- package/dist/proxy/bootstrap.d.ts +0 -35
- package/dist/proxy/bootstrap.js +0 -119
- package/dist/proxy/constants.d.ts +0 -7
- package/dist/proxy/constants.js +0 -8
- package/dist/proxy/controllerWindow.d.ts +0 -12
- package/dist/proxy/controllerWindow.js +0 -384
- package/dist/proxy/cookieJar.d.ts +0 -7
- package/dist/proxy/cookieJar.js +0 -136
- package/dist/proxy/headerPolicy.d.ts +0 -14
- package/dist/proxy/headerPolicy.js +0 -134
- package/dist/proxy/portStream.d.ts +0 -5
- package/dist/proxy/portStream.js +0 -256
- package/dist/proxy/preset.d.ts +0 -29
- package/dist/proxy/preset.js +0 -111
- package/dist/proxy/runtimeScope.d.ts +0 -57
- package/dist/proxy/runtimeScope.js +0 -218
- package/dist/proxy/server.d.ts +0 -28
- package/dist/proxy/server.js +0 -833
- package/dist/proxy/windowBridgeProtocol.d.ts +0 -65
- package/dist/proxy/windowBridgeProtocol.js +0 -11
- package/dist/reconnect/artifactControlplane.d.ts +0 -16
- package/dist/reconnect/artifactControlplane.js +0 -35
- package/dist/reconnect/index.d.ts +0 -36
- package/dist/reconnect/index.js +0 -388
- package/dist/rpc-proxy/index.d.ts +0 -1
- package/dist/rpc-proxy/index.js +0 -1
- package/dist/rpc-proxy/rpcProxy.d.ts +0 -1
- package/dist/rpc-proxy/rpcProxy.js +0 -1
- package/dist/streamhello/index.d.ts +0 -1
- package/dist/streamhello/index.js +0 -1
- package/dist/streamhello/streamHello.d.ts +0 -3
- package/dist/streamhello/streamHello.js +0 -13
- package/dist/streamio/index.d.ts +0 -32
- package/dist/streamio/index.js +0 -87
- package/dist/tunnel-client/connect.d.ts +0 -9
- package/dist/tunnel-client/connect.js +0 -147
- package/dist/tunnel-client/index.d.ts +0 -1
- package/dist/tunnel-client/index.js +0 -1
- package/dist/ws/index.d.ts +0 -1
- package/dist/ws/index.js +0 -1
- /package/dist/{client.js → rpc/wire.js} +0 -0
|
@@ -1,384 +0,0 @@
|
|
|
1
|
-
import { PROXY_WINDOW_FETCH_MSG_TYPE, PROXY_WINDOW_STREAM_CHUNK_MSG_TYPE, PROXY_WINDOW_STREAM_CLOSE_MSG_TYPE, PROXY_WINDOW_STREAM_END_MSG_TYPE, PROXY_WINDOW_STREAM_RESET_MSG_TYPE, PROXY_WINDOW_STREAM_WRITE_ACK_MSG_TYPE, PROXY_WINDOW_WS_ERROR_MSG_TYPE, PROXY_WINDOW_WS_BIDIRECTIONAL_ACK_CAPABILITY, PROXY_WINDOW_WS_OPEN_ACK_MSG_TYPE, PROXY_WINDOW_WS_OPEN_MSG_TYPE, } from "./windowBridgeProtocol.js";
|
|
2
|
-
function normalizeOrigins(origins) {
|
|
3
|
-
const out = [];
|
|
4
|
-
const seen = new Set();
|
|
5
|
-
for (const origin of origins) {
|
|
6
|
-
const normalized = String(origin ?? "").trim();
|
|
7
|
-
if (normalized === "" || seen.has(normalized))
|
|
8
|
-
continue;
|
|
9
|
-
seen.add(normalized);
|
|
10
|
-
out.push(normalized);
|
|
11
|
-
}
|
|
12
|
-
return out;
|
|
13
|
-
}
|
|
14
|
-
function cloneChunk(chunk) {
|
|
15
|
-
const out = new Uint8Array(chunk.byteLength);
|
|
16
|
-
out.set(chunk);
|
|
17
|
-
return out.buffer;
|
|
18
|
-
}
|
|
19
|
-
function normalizeCapabilityNonce(value) {
|
|
20
|
-
if (value == null)
|
|
21
|
-
return "";
|
|
22
|
-
const s = String(value);
|
|
23
|
-
if (s === "")
|
|
24
|
-
return "";
|
|
25
|
-
if (s.trim() !== s || /[\s\u0000-\u001f\u007f]/.test(s)) {
|
|
26
|
-
throw new Error("capabilityNonce must not contain whitespace or control characters");
|
|
27
|
-
}
|
|
28
|
-
return s;
|
|
29
|
-
}
|
|
30
|
-
function requireBridgeCapability(expectedSource, capabilityNonce) {
|
|
31
|
-
if (expectedSource == null && capabilityNonce === "") {
|
|
32
|
-
throw new Error("expectedSource or capabilityNonce is required");
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
function hasExpectedCapability(data, capabilityNonce) {
|
|
36
|
-
if (capabilityNonce === "")
|
|
37
|
-
return true;
|
|
38
|
-
if (data == null || typeof data !== "object")
|
|
39
|
-
return false;
|
|
40
|
-
return data.capabilityNonce === capabilityNonce;
|
|
41
|
-
}
|
|
42
|
-
function withTrustedExternalOrigin(req, rawOrigin) {
|
|
43
|
-
let externalOrigin;
|
|
44
|
-
try {
|
|
45
|
-
const url = new URL(rawOrigin);
|
|
46
|
-
if (url.protocol === "http:" || url.protocol === "https:") {
|
|
47
|
-
externalOrigin = url.origin;
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
catch {
|
|
51
|
-
// Opaque and invalid origins must not become upstream authority metadata.
|
|
52
|
-
}
|
|
53
|
-
const sanitized = { ...req };
|
|
54
|
-
delete sanitized.external_origin;
|
|
55
|
-
return externalOrigin === undefined
|
|
56
|
-
? sanitized
|
|
57
|
-
: { ...sanitized, external_origin: externalOrigin };
|
|
58
|
-
}
|
|
59
|
-
function validWriteId(value) {
|
|
60
|
-
return Number.isSafeInteger(value) && Number(value) > 0;
|
|
61
|
-
}
|
|
62
|
-
function bridgeWebSocket(runtime, msg, port, onTerminal) {
|
|
63
|
-
const capabilities = Array.isArray(msg.capabilities)
|
|
64
|
-
? msg.capabilities.filter((value) => typeof value === "string")
|
|
65
|
-
: [];
|
|
66
|
-
if (!capabilities.includes(PROXY_WINDOW_WS_BIDIRECTIONAL_ACK_CAPABILITY)) {
|
|
67
|
-
try {
|
|
68
|
-
port.postMessage({
|
|
69
|
-
type: PROXY_WINDOW_WS_ERROR_MSG_TYPE,
|
|
70
|
-
message: "proxy Window bridge requires bidirectional stream acknowledgements",
|
|
71
|
-
});
|
|
72
|
-
}
|
|
73
|
-
catch {
|
|
74
|
-
// Best-effort.
|
|
75
|
-
}
|
|
76
|
-
finally {
|
|
77
|
-
port.close();
|
|
78
|
-
}
|
|
79
|
-
onTerminal();
|
|
80
|
-
return { dispose: () => { }, isTerminal: () => true };
|
|
81
|
-
}
|
|
82
|
-
const ac = new AbortController();
|
|
83
|
-
let terminal = false;
|
|
84
|
-
let terminalError = null;
|
|
85
|
-
let acceptingWrites = true;
|
|
86
|
-
let stream = null;
|
|
87
|
-
let pendingInboundWriteId = null;
|
|
88
|
-
let pendingOutboundAcknowledgement = null;
|
|
89
|
-
let nextWriteId = 1;
|
|
90
|
-
const maxBufferedBytes = runtime.limits.maxWsBufferedAmountBytes ?? 4 * (1 << 20);
|
|
91
|
-
let terminalNotified = false;
|
|
92
|
-
const notifyTerminal = () => {
|
|
93
|
-
if (terminalNotified)
|
|
94
|
-
return;
|
|
95
|
-
terminalNotified = true;
|
|
96
|
-
onTerminal();
|
|
97
|
-
};
|
|
98
|
-
const closePort = () => {
|
|
99
|
-
try {
|
|
100
|
-
port.close();
|
|
101
|
-
}
|
|
102
|
-
catch {
|
|
103
|
-
// Best-effort.
|
|
104
|
-
}
|
|
105
|
-
};
|
|
106
|
-
const failBridge = (error, notifyPeer = true) => {
|
|
107
|
-
if (terminal)
|
|
108
|
-
return;
|
|
109
|
-
terminal = true;
|
|
110
|
-
acceptingWrites = false;
|
|
111
|
-
const err = error instanceof Error ? error : new Error(String(error));
|
|
112
|
-
terminalError = err;
|
|
113
|
-
pendingInboundWriteId = null;
|
|
114
|
-
pendingOutboundAcknowledgement?.reject(err);
|
|
115
|
-
pendingOutboundAcknowledgement = null;
|
|
116
|
-
if (stream != null) {
|
|
117
|
-
void Promise.resolve(stream.reset(err)).catch(() => {
|
|
118
|
-
// The bridge error is already delivered through the terminal response.
|
|
119
|
-
});
|
|
120
|
-
}
|
|
121
|
-
try {
|
|
122
|
-
ac.abort(err.message);
|
|
123
|
-
}
|
|
124
|
-
catch {
|
|
125
|
-
// Best-effort.
|
|
126
|
-
}
|
|
127
|
-
if (notifyPeer) {
|
|
128
|
-
try {
|
|
129
|
-
port.postMessage({
|
|
130
|
-
type: PROXY_WINDOW_STREAM_RESET_MSG_TYPE,
|
|
131
|
-
message: err.message,
|
|
132
|
-
});
|
|
133
|
-
}
|
|
134
|
-
catch {
|
|
135
|
-
// Best-effort.
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
closePort();
|
|
139
|
-
notifyTerminal();
|
|
140
|
-
};
|
|
141
|
-
const failProtocol = (message) => {
|
|
142
|
-
failBridge(new Error(`proxy Window stream protocol error: ${message}`));
|
|
143
|
-
};
|
|
144
|
-
const postChunkAndWait = async (chunk) => {
|
|
145
|
-
if (chunk.byteLength > maxBufferedBytes) {
|
|
146
|
-
throw new Error("proxy WebSocket inbound chunk exceeded the buffer limit");
|
|
147
|
-
}
|
|
148
|
-
if (!Number.isSafeInteger(nextWriteId)) {
|
|
149
|
-
throw new Error("proxy Window stream write identifier space exhausted");
|
|
150
|
-
}
|
|
151
|
-
if (pendingOutboundAcknowledgement != null) {
|
|
152
|
-
throw new Error("proxy Window stream already has an unacknowledged outbound chunk");
|
|
153
|
-
}
|
|
154
|
-
const writeId = nextWriteId++;
|
|
155
|
-
const ab = cloneChunk(chunk);
|
|
156
|
-
await new Promise((resolve, reject) => {
|
|
157
|
-
pendingOutboundAcknowledgement = { writeId, resolve, reject };
|
|
158
|
-
try {
|
|
159
|
-
port.postMessage({
|
|
160
|
-
type: PROXY_WINDOW_STREAM_CHUNK_MSG_TYPE,
|
|
161
|
-
data: ab,
|
|
162
|
-
writeId,
|
|
163
|
-
}, [ab]);
|
|
164
|
-
}
|
|
165
|
-
catch (error) {
|
|
166
|
-
pendingOutboundAcknowledgement = null;
|
|
167
|
-
reject(error instanceof Error ? error : new Error(String(error)));
|
|
168
|
-
}
|
|
169
|
-
});
|
|
170
|
-
};
|
|
171
|
-
port.onmessage = (ev) => {
|
|
172
|
-
const data = ev.data;
|
|
173
|
-
if (data == null || typeof data !== "object")
|
|
174
|
-
return;
|
|
175
|
-
const type = typeof data.type === "string" ? data.type : "";
|
|
176
|
-
if (stream == null) {
|
|
177
|
-
if (type === PROXY_WINDOW_STREAM_RESET_MSG_TYPE) {
|
|
178
|
-
const message = String(data.message ?? "stream reset");
|
|
179
|
-
failBridge(new Error(message), false);
|
|
180
|
-
}
|
|
181
|
-
else if (type === PROXY_WINDOW_STREAM_CHUNK_MSG_TYPE
|
|
182
|
-
|| type === PROXY_WINDOW_STREAM_CLOSE_MSG_TYPE
|
|
183
|
-
|| type === PROXY_WINDOW_STREAM_WRITE_ACK_MSG_TYPE) {
|
|
184
|
-
failProtocol("received stream traffic before the websocket opened");
|
|
185
|
-
}
|
|
186
|
-
return;
|
|
187
|
-
}
|
|
188
|
-
switch (type) {
|
|
189
|
-
case PROXY_WINDOW_STREAM_CHUNK_MSG_TYPE: {
|
|
190
|
-
if (!acceptingWrites)
|
|
191
|
-
return;
|
|
192
|
-
const chunkMessage = data;
|
|
193
|
-
const raw = chunkMessage.data;
|
|
194
|
-
if (!(raw instanceof ArrayBuffer) || !validWriteId(chunkMessage.writeId)) {
|
|
195
|
-
failProtocol("invalid stream chunk");
|
|
196
|
-
return;
|
|
197
|
-
}
|
|
198
|
-
if (pendingInboundWriteId != null) {
|
|
199
|
-
failProtocol("received more than one unacknowledged chunk");
|
|
200
|
-
return;
|
|
201
|
-
}
|
|
202
|
-
if (raw.byteLength > maxBufferedBytes) {
|
|
203
|
-
failBridge(new Error("proxy WebSocket outbound buffer exceeded"));
|
|
204
|
-
return;
|
|
205
|
-
}
|
|
206
|
-
const writeId = chunkMessage.writeId;
|
|
207
|
-
const chunk = new Uint8Array(raw);
|
|
208
|
-
pendingInboundWriteId = writeId;
|
|
209
|
-
void stream.write(chunk)
|
|
210
|
-
.then(() => {
|
|
211
|
-
if (terminal)
|
|
212
|
-
return;
|
|
213
|
-
if (pendingInboundWriteId !== writeId) {
|
|
214
|
-
failProtocol("completed write does not match the pending chunk");
|
|
215
|
-
return;
|
|
216
|
-
}
|
|
217
|
-
pendingInboundWriteId = null;
|
|
218
|
-
port.postMessage({
|
|
219
|
-
type: PROXY_WINDOW_STREAM_WRITE_ACK_MSG_TYPE,
|
|
220
|
-
writeId,
|
|
221
|
-
});
|
|
222
|
-
})
|
|
223
|
-
.catch((error) => failBridge(error));
|
|
224
|
-
return;
|
|
225
|
-
}
|
|
226
|
-
case PROXY_WINDOW_STREAM_CLOSE_MSG_TYPE: {
|
|
227
|
-
if (!acceptingWrites)
|
|
228
|
-
return;
|
|
229
|
-
if (pendingInboundWriteId != null) {
|
|
230
|
-
failProtocol("stream closed before the pending chunk was acknowledged");
|
|
231
|
-
return;
|
|
232
|
-
}
|
|
233
|
-
acceptingWrites = false;
|
|
234
|
-
terminal = true;
|
|
235
|
-
const closeError = new Error("stream is closed");
|
|
236
|
-
pendingInboundWriteId = null;
|
|
237
|
-
pendingOutboundAcknowledgement?.reject(closeError);
|
|
238
|
-
pendingOutboundAcknowledgement = null;
|
|
239
|
-
void Promise.resolve(stream.close()).catch(() => {
|
|
240
|
-
// The peer already closed its bridge endpoint.
|
|
241
|
-
});
|
|
242
|
-
closePort();
|
|
243
|
-
notifyTerminal();
|
|
244
|
-
return;
|
|
245
|
-
}
|
|
246
|
-
case PROXY_WINDOW_STREAM_WRITE_ACK_MSG_TYPE: {
|
|
247
|
-
const writeId = data.writeId;
|
|
248
|
-
const pending = pendingOutboundAcknowledgement;
|
|
249
|
-
if (!validWriteId(writeId) || pending == null || pending.writeId !== writeId) {
|
|
250
|
-
failProtocol("unexpected stream write acknowledgement");
|
|
251
|
-
return;
|
|
252
|
-
}
|
|
253
|
-
pendingOutboundAcknowledgement = null;
|
|
254
|
-
pending.resolve();
|
|
255
|
-
return;
|
|
256
|
-
}
|
|
257
|
-
case PROXY_WINDOW_STREAM_RESET_MSG_TYPE: {
|
|
258
|
-
const message = String(data.message ?? "stream reset");
|
|
259
|
-
failBridge(new Error(message), false);
|
|
260
|
-
return;
|
|
261
|
-
}
|
|
262
|
-
default:
|
|
263
|
-
return;
|
|
264
|
-
}
|
|
265
|
-
};
|
|
266
|
-
port.start?.();
|
|
267
|
-
void (async () => {
|
|
268
|
-
try {
|
|
269
|
-
const wsOpts = {
|
|
270
|
-
signal: ac.signal,
|
|
271
|
-
...(msg.protocols === undefined ? {} : { protocols: msg.protocols }),
|
|
272
|
-
};
|
|
273
|
-
const opened = await runtime.openWebSocketStream(msg.path, wsOpts);
|
|
274
|
-
if (terminal) {
|
|
275
|
-
await Promise.resolve(opened.stream.reset(terminalError ?? new Error("proxy controller Window bridge is closed")));
|
|
276
|
-
return;
|
|
277
|
-
}
|
|
278
|
-
stream = opened.stream;
|
|
279
|
-
port.postMessage({
|
|
280
|
-
type: PROXY_WINDOW_WS_OPEN_ACK_MSG_TYPE,
|
|
281
|
-
protocol: opened.protocol,
|
|
282
|
-
capabilities: [PROXY_WINDOW_WS_BIDIRECTIONAL_ACK_CAPABILITY],
|
|
283
|
-
});
|
|
284
|
-
while (!terminal) {
|
|
285
|
-
const chunk = await stream.read();
|
|
286
|
-
if (chunk == null) {
|
|
287
|
-
terminal = true;
|
|
288
|
-
acceptingWrites = false;
|
|
289
|
-
port.postMessage({ type: PROXY_WINDOW_STREAM_END_MSG_TYPE });
|
|
290
|
-
closePort();
|
|
291
|
-
notifyTerminal();
|
|
292
|
-
return;
|
|
293
|
-
}
|
|
294
|
-
await postChunkAndWait(chunk);
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
catch (error) {
|
|
298
|
-
if (terminal)
|
|
299
|
-
return;
|
|
300
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
301
|
-
if (stream == null) {
|
|
302
|
-
terminal = true;
|
|
303
|
-
acceptingWrites = false;
|
|
304
|
-
terminalError = error instanceof Error ? error : new Error(message);
|
|
305
|
-
try {
|
|
306
|
-
port.postMessage({ type: PROXY_WINDOW_WS_ERROR_MSG_TYPE, message });
|
|
307
|
-
}
|
|
308
|
-
finally {
|
|
309
|
-
closePort();
|
|
310
|
-
notifyTerminal();
|
|
311
|
-
}
|
|
312
|
-
return;
|
|
313
|
-
}
|
|
314
|
-
failBridge(error);
|
|
315
|
-
}
|
|
316
|
-
})();
|
|
317
|
-
return {
|
|
318
|
-
dispose: (error) => failBridge(error),
|
|
319
|
-
isTerminal: () => terminal,
|
|
320
|
-
};
|
|
321
|
-
}
|
|
322
|
-
export function registerProxyControllerWindow(opts) {
|
|
323
|
-
const allowedOrigins = normalizeOrigins(opts.allowedOrigins);
|
|
324
|
-
if (allowedOrigins.length === 0) {
|
|
325
|
-
throw new Error("allowedOrigins is required");
|
|
326
|
-
}
|
|
327
|
-
const capabilityNonce = normalizeCapabilityNonce(opts.capabilityNonce);
|
|
328
|
-
requireBridgeCapability(opts.expectedSource, capabilityNonce);
|
|
329
|
-
const activeWebSocketBridges = new Set();
|
|
330
|
-
let disposed = false;
|
|
331
|
-
const targetWindow = opts.targetWindow ?? globalThis.window;
|
|
332
|
-
if (targetWindow == null) {
|
|
333
|
-
throw new Error("targetWindow is not available");
|
|
334
|
-
}
|
|
335
|
-
const onMessage = (ev) => {
|
|
336
|
-
const eventOrigin = String(ev.origin ?? "").trim();
|
|
337
|
-
if (!allowedOrigins.includes(eventOrigin))
|
|
338
|
-
return;
|
|
339
|
-
if (opts.expectedSource != null && ev.source !== opts.expectedSource)
|
|
340
|
-
return;
|
|
341
|
-
const data = ev.data;
|
|
342
|
-
if (data == null || typeof data !== "object")
|
|
343
|
-
return;
|
|
344
|
-
if (!hasExpectedCapability(data, capabilityNonce))
|
|
345
|
-
return;
|
|
346
|
-
const type = typeof data.type === "string" ? data.type : "";
|
|
347
|
-
const port = ev.ports?.[0];
|
|
348
|
-
if (!port)
|
|
349
|
-
return;
|
|
350
|
-
switch (type) {
|
|
351
|
-
case PROXY_WINDOW_FETCH_MSG_TYPE: {
|
|
352
|
-
const msg = data;
|
|
353
|
-
opts.runtime.dispatchFetch(withTrustedExternalOrigin(msg.req, eventOrigin), port);
|
|
354
|
-
return;
|
|
355
|
-
}
|
|
356
|
-
case PROXY_WINDOW_WS_OPEN_MSG_TYPE: {
|
|
357
|
-
if (disposed)
|
|
358
|
-
return;
|
|
359
|
-
let bridge = null;
|
|
360
|
-
bridge = bridgeWebSocket(opts.runtime, data, port, () => {
|
|
361
|
-
if (bridge != null)
|
|
362
|
-
activeWebSocketBridges.delete(bridge);
|
|
363
|
-
});
|
|
364
|
-
if (!bridge.isTerminal())
|
|
365
|
-
activeWebSocketBridges.add(bridge);
|
|
366
|
-
return;
|
|
367
|
-
}
|
|
368
|
-
default:
|
|
369
|
-
return;
|
|
370
|
-
}
|
|
371
|
-
};
|
|
372
|
-
targetWindow.addEventListener("message", onMessage);
|
|
373
|
-
return {
|
|
374
|
-
dispose: () => {
|
|
375
|
-
if (disposed)
|
|
376
|
-
return;
|
|
377
|
-
disposed = true;
|
|
378
|
-
targetWindow.removeEventListener("message", onMessage);
|
|
379
|
-
const error = new Error("proxy controller Window bridge is disposed");
|
|
380
|
-
for (const bridge of [...activeWebSocketBridges])
|
|
381
|
-
bridge.dispose(error);
|
|
382
|
-
},
|
|
383
|
-
};
|
|
384
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
export declare class CookieJar {
|
|
2
|
-
private readonly cookies;
|
|
3
|
-
private nextCreatedAtSeq;
|
|
4
|
-
setCookie(setCookieHeader: string, requestPath?: string): void;
|
|
5
|
-
updateFromSetCookieHeaders(headers: readonly string[], requestPath?: string): void;
|
|
6
|
-
getCookieHeader(path: string): string;
|
|
7
|
-
}
|
package/dist/proxy/cookieJar.js
DELETED
|
@@ -1,136 +0,0 @@
|
|
|
1
|
-
function nowMs() {
|
|
2
|
-
return Date.now();
|
|
3
|
-
}
|
|
4
|
-
function parseCookieNameValue(s) {
|
|
5
|
-
const idx = s.indexOf("=");
|
|
6
|
-
if (idx <= 0)
|
|
7
|
-
return null;
|
|
8
|
-
const name = s.slice(0, idx).trim();
|
|
9
|
-
const value = s.slice(idx + 1).trim();
|
|
10
|
-
if (name === "")
|
|
11
|
-
return null;
|
|
12
|
-
return { name, value };
|
|
13
|
-
}
|
|
14
|
-
function cookieStorageKey(name, path) {
|
|
15
|
-
return `${name}\u0000${path}`;
|
|
16
|
-
}
|
|
17
|
-
function requestPathOnly(path) {
|
|
18
|
-
const raw = path.trim();
|
|
19
|
-
if (!raw.startsWith("/"))
|
|
20
|
-
return "/";
|
|
21
|
-
const q = raw.indexOf("?");
|
|
22
|
-
const out = q >= 0 ? raw.slice(0, q) : raw;
|
|
23
|
-
return out === "" ? "/" : out;
|
|
24
|
-
}
|
|
25
|
-
function defaultCookiePathFromRequestPath(requestPath) {
|
|
26
|
-
const path = requestPathOnly(requestPath);
|
|
27
|
-
if (path === "/")
|
|
28
|
-
return "/";
|
|
29
|
-
const lastSlash = path.lastIndexOf("/");
|
|
30
|
-
if (lastSlash <= 0)
|
|
31
|
-
return "/";
|
|
32
|
-
return path.slice(0, lastSlash);
|
|
33
|
-
}
|
|
34
|
-
function normalizeCookiePath(pathAttr, requestPath) {
|
|
35
|
-
const path = pathAttr?.trim() ?? "";
|
|
36
|
-
if (path === "" || !path.startsWith("/"))
|
|
37
|
-
return defaultCookiePathFromRequestPath(requestPath);
|
|
38
|
-
return path;
|
|
39
|
-
}
|
|
40
|
-
function pathMatchesCookiePath(requestPath, cookiePath) {
|
|
41
|
-
const path = requestPathOnly(requestPath);
|
|
42
|
-
if (cookiePath === "/")
|
|
43
|
-
return true;
|
|
44
|
-
if (path === cookiePath)
|
|
45
|
-
return true;
|
|
46
|
-
if (!path.startsWith(cookiePath))
|
|
47
|
-
return false;
|
|
48
|
-
if (cookiePath.endsWith("/"))
|
|
49
|
-
return true;
|
|
50
|
-
return path.charAt(cookiePath.length) === "/";
|
|
51
|
-
}
|
|
52
|
-
function compareCookiesForHeader(a, b) {
|
|
53
|
-
const pathLenDiff = b.path.length - a.path.length;
|
|
54
|
-
if (pathLenDiff !== 0)
|
|
55
|
-
return pathLenDiff;
|
|
56
|
-
return a.createdAtSeq - b.createdAtSeq;
|
|
57
|
-
}
|
|
58
|
-
export class CookieJar {
|
|
59
|
-
cookies = new Map();
|
|
60
|
-
nextCreatedAtSeq = 0;
|
|
61
|
-
setCookie(setCookieHeader, requestPath = "/") {
|
|
62
|
-
const raw = setCookieHeader.trim();
|
|
63
|
-
if (raw === "")
|
|
64
|
-
return;
|
|
65
|
-
const parts = raw.split(";").map((p) => p.trim()).filter((p) => p !== "");
|
|
66
|
-
if (parts.length === 0)
|
|
67
|
-
return;
|
|
68
|
-
const nv = parseCookieNameValue(parts[0] ?? "");
|
|
69
|
-
if (nv == null)
|
|
70
|
-
return;
|
|
71
|
-
let pathAttr;
|
|
72
|
-
let expiresAtMs;
|
|
73
|
-
let maxAgeSeen = false;
|
|
74
|
-
for (let i = 1; i < parts.length; i++) {
|
|
75
|
-
const p = parts[i];
|
|
76
|
-
const lower = p.toLowerCase();
|
|
77
|
-
if (lower.startsWith("path=")) {
|
|
78
|
-
const v = p.slice("path=".length).trim();
|
|
79
|
-
if (v !== "")
|
|
80
|
-
pathAttr = v;
|
|
81
|
-
continue;
|
|
82
|
-
}
|
|
83
|
-
if (lower.startsWith("max-age=")) {
|
|
84
|
-
const v = p.slice("max-age=".length).trim();
|
|
85
|
-
const n = Number.parseInt(v, 10);
|
|
86
|
-
if (!Number.isFinite(n))
|
|
87
|
-
continue;
|
|
88
|
-
maxAgeSeen = true;
|
|
89
|
-
expiresAtMs = n <= 0 ? 0 : nowMs() + n * 1000;
|
|
90
|
-
continue;
|
|
91
|
-
}
|
|
92
|
-
if (lower.startsWith("expires=")) {
|
|
93
|
-
if (maxAgeSeen)
|
|
94
|
-
continue;
|
|
95
|
-
const v = p.slice("expires=".length).trim();
|
|
96
|
-
const t = Date.parse(v);
|
|
97
|
-
if (!Number.isFinite(t))
|
|
98
|
-
continue;
|
|
99
|
-
expiresAtMs = t;
|
|
100
|
-
continue;
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
const path = normalizeCookiePath(pathAttr, requestPath);
|
|
104
|
-
const key = cookieStorageKey(nv.name, path);
|
|
105
|
-
if (expiresAtMs != null && expiresAtMs <= nowMs()) {
|
|
106
|
-
this.cookies.delete(key);
|
|
107
|
-
return;
|
|
108
|
-
}
|
|
109
|
-
const createdAtSeq = this.cookies.get(key)?.createdAtSeq ?? this.nextCreatedAtSeq++;
|
|
110
|
-
if (expiresAtMs == null) {
|
|
111
|
-
this.cookies.set(key, { name: nv.name, value: nv.value, path, createdAtSeq });
|
|
112
|
-
}
|
|
113
|
-
else {
|
|
114
|
-
this.cookies.set(key, { name: nv.name, value: nv.value, path, expiresAtMs, createdAtSeq });
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
updateFromSetCookieHeaders(headers, requestPath = "/") {
|
|
118
|
-
for (const h of headers)
|
|
119
|
-
this.setCookie(h, requestPath);
|
|
120
|
-
}
|
|
121
|
-
getCookieHeader(path) {
|
|
122
|
-
const now = nowMs();
|
|
123
|
-
const matched = [];
|
|
124
|
-
for (const [key, c] of this.cookies.entries()) {
|
|
125
|
-
if (c.expiresAtMs != null && c.expiresAtMs <= now) {
|
|
126
|
-
this.cookies.delete(key);
|
|
127
|
-
continue;
|
|
128
|
-
}
|
|
129
|
-
if (!pathMatchesCookiePath(path, c.path))
|
|
130
|
-
continue;
|
|
131
|
-
matched.push(c);
|
|
132
|
-
}
|
|
133
|
-
matched.sort(compareCookiesForHeader);
|
|
134
|
-
return matched.map((c) => `${c.name}=${c.value}`).join("; ");
|
|
135
|
-
}
|
|
136
|
-
}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import type { Header } from "./types.js";
|
|
2
|
-
export declare function normalizeHeaderName(name: string): string;
|
|
3
|
-
export declare function isValidHeaderName(name: string): boolean;
|
|
4
|
-
export declare function isSafeHeaderValue(value: string): boolean;
|
|
5
|
-
export type FilterHeadersOptions = Readonly<{
|
|
6
|
-
extraAllowed?: readonly string[];
|
|
7
|
-
}>;
|
|
8
|
-
export declare function filterRequestHeaders(input: readonly Header[], opts?: FilterHeadersOptions): Header[];
|
|
9
|
-
export type FilterResponseResult = Readonly<{
|
|
10
|
-
passthrough: Header[];
|
|
11
|
-
setCookie: string[];
|
|
12
|
-
}>;
|
|
13
|
-
export declare function filterResponseHeaders(input: readonly Header[], opts?: FilterHeadersOptions): FilterResponseResult;
|
|
14
|
-
export declare function filterWsOpenHeaders(input: readonly Header[], opts?: FilterHeadersOptions): Header[];
|
|
@@ -1,134 +0,0 @@
|
|
|
1
|
-
const DEFAULT_REQUEST_HEADER_ALLOWLIST = new Set([
|
|
2
|
-
"accept",
|
|
3
|
-
"accept-language",
|
|
4
|
-
"cache-control",
|
|
5
|
-
"content-type",
|
|
6
|
-
"if-match",
|
|
7
|
-
"if-modified-since",
|
|
8
|
-
"if-none-match",
|
|
9
|
-
"if-unmodified-since",
|
|
10
|
-
"origin",
|
|
11
|
-
"pragma",
|
|
12
|
-
"range",
|
|
13
|
-
"x-requested-with"
|
|
14
|
-
]);
|
|
15
|
-
const DEFAULT_RESPONSE_HEADER_ALLOWLIST = new Set([
|
|
16
|
-
"cache-control",
|
|
17
|
-
"content-disposition",
|
|
18
|
-
"content-encoding",
|
|
19
|
-
"content-language",
|
|
20
|
-
"content-security-policy",
|
|
21
|
-
"content-security-policy-report-only",
|
|
22
|
-
"content-type",
|
|
23
|
-
"cross-origin-embedder-policy",
|
|
24
|
-
"cross-origin-opener-policy",
|
|
25
|
-
"cross-origin-resource-policy",
|
|
26
|
-
"etag",
|
|
27
|
-
"expires",
|
|
28
|
-
"last-modified",
|
|
29
|
-
"location",
|
|
30
|
-
"permissions-policy",
|
|
31
|
-
"pragma",
|
|
32
|
-
"referrer-policy",
|
|
33
|
-
"vary",
|
|
34
|
-
"www-authenticate",
|
|
35
|
-
"set-cookie",
|
|
36
|
-
"x-content-type-options",
|
|
37
|
-
"x-frame-options"
|
|
38
|
-
]);
|
|
39
|
-
const DEFAULT_WS_HEADER_ALLOWLIST = new Set(["sec-websocket-protocol", "cookie"]);
|
|
40
|
-
export function normalizeHeaderName(name) {
|
|
41
|
-
return name.trim().toLowerCase();
|
|
42
|
-
}
|
|
43
|
-
export function isValidHeaderName(name) {
|
|
44
|
-
// Minimal RFC 7230 token validation; keep strict to avoid smuggling bugs.
|
|
45
|
-
for (let i = 0; i < name.length; i++) {
|
|
46
|
-
const c = name.charCodeAt(i);
|
|
47
|
-
const isAlpha = c >= 0x61 && c <= 0x7a;
|
|
48
|
-
const isDigit = c >= 0x30 && c <= 0x39;
|
|
49
|
-
if (isAlpha || isDigit)
|
|
50
|
-
continue;
|
|
51
|
-
// ! # $ % & ' * + - . ^ _ ` | ~
|
|
52
|
-
if (c === 0x21 || c === 0x23 || c === 0x24 || c === 0x25 || c === 0x26 || c === 0x27)
|
|
53
|
-
continue;
|
|
54
|
-
if (c === 0x2a || c === 0x2b || c === 0x2d || c === 0x2e)
|
|
55
|
-
continue;
|
|
56
|
-
if (c === 0x5e || c === 0x5f || c === 0x60 || c === 0x7c || c === 0x7e)
|
|
57
|
-
continue;
|
|
58
|
-
return false;
|
|
59
|
-
}
|
|
60
|
-
return name.length > 0;
|
|
61
|
-
}
|
|
62
|
-
export function isSafeHeaderValue(value) {
|
|
63
|
-
return !value.includes("\r") && !value.includes("\n");
|
|
64
|
-
}
|
|
65
|
-
function buildExtraAllowedSet(extraAllowed) {
|
|
66
|
-
if (extraAllowed == null || extraAllowed.length === 0)
|
|
67
|
-
return null;
|
|
68
|
-
const s = new Set();
|
|
69
|
-
for (const n of extraAllowed) {
|
|
70
|
-
const nn = normalizeHeaderName(n);
|
|
71
|
-
if (nn !== "" && isValidHeaderName(nn))
|
|
72
|
-
s.add(nn);
|
|
73
|
-
}
|
|
74
|
-
return s;
|
|
75
|
-
}
|
|
76
|
-
function isAllowed(allow, extra, name) {
|
|
77
|
-
return allow.has(name) || (extra != null && extra.has(name));
|
|
78
|
-
}
|
|
79
|
-
export function filterRequestHeaders(input, opts = {}) {
|
|
80
|
-
const extra = buildExtraAllowedSet(opts.extraAllowed);
|
|
81
|
-
const out = [];
|
|
82
|
-
for (const h of input) {
|
|
83
|
-
const name = normalizeHeaderName(h.name);
|
|
84
|
-
if (name === "" || !isValidHeaderName(name))
|
|
85
|
-
continue;
|
|
86
|
-
if (!isSafeHeaderValue(h.value))
|
|
87
|
-
continue;
|
|
88
|
-
// Never forward these from the client runtime.
|
|
89
|
-
if (name === "host" || name === "authorization")
|
|
90
|
-
continue;
|
|
91
|
-
// Cookie is injected by the runtime CookieJar (not copied from browser cookie store).
|
|
92
|
-
if (name === "cookie")
|
|
93
|
-
continue;
|
|
94
|
-
if (!isAllowed(DEFAULT_REQUEST_HEADER_ALLOWLIST, extra, name))
|
|
95
|
-
continue;
|
|
96
|
-
out.push({ name, value: h.value });
|
|
97
|
-
}
|
|
98
|
-
return out;
|
|
99
|
-
}
|
|
100
|
-
export function filterResponseHeaders(input, opts = {}) {
|
|
101
|
-
const extra = buildExtraAllowedSet(opts.extraAllowed);
|
|
102
|
-
const passthrough = [];
|
|
103
|
-
const setCookie = [];
|
|
104
|
-
for (const h of input) {
|
|
105
|
-
const name = normalizeHeaderName(h.name);
|
|
106
|
-
if (name === "" || !isValidHeaderName(name))
|
|
107
|
-
continue;
|
|
108
|
-
if (!isSafeHeaderValue(h.value))
|
|
109
|
-
continue;
|
|
110
|
-
if (!isAllowed(DEFAULT_RESPONSE_HEADER_ALLOWLIST, extra, name))
|
|
111
|
-
continue;
|
|
112
|
-
if (name === "set-cookie") {
|
|
113
|
-
setCookie.push(h.value);
|
|
114
|
-
continue;
|
|
115
|
-
}
|
|
116
|
-
passthrough.push({ name, value: h.value });
|
|
117
|
-
}
|
|
118
|
-
return { passthrough, setCookie };
|
|
119
|
-
}
|
|
120
|
-
export function filterWsOpenHeaders(input, opts = {}) {
|
|
121
|
-
const extra = buildExtraAllowedSet(opts.extraAllowed);
|
|
122
|
-
const out = [];
|
|
123
|
-
for (const h of input) {
|
|
124
|
-
const name = normalizeHeaderName(h.name);
|
|
125
|
-
if (name === "" || !isValidHeaderName(name))
|
|
126
|
-
continue;
|
|
127
|
-
if (!isSafeHeaderValue(h.value))
|
|
128
|
-
continue;
|
|
129
|
-
if (!isAllowed(DEFAULT_WS_HEADER_ALLOWLIST, extra, name))
|
|
130
|
-
continue;
|
|
131
|
-
out.push({ name, value: h.value });
|
|
132
|
-
}
|
|
133
|
-
return out;
|
|
134
|
-
}
|