@inkbox/sdk 0.2.16 → 0.3.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 +10 -1
- package/dist/_http.d.ts +24 -5
- package/dist/_http.d.ts.map +1 -1
- package/dist/_http.js +21 -11
- package/dist/_http.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/inkbox.d.ts +4 -0
- package/dist/inkbox.d.ts.map +1 -1
- package/dist/inkbox.js +5 -0
- package/dist/inkbox.js.map +1 -1
- package/dist/tunnels/_validation.d.ts +7 -0
- package/dist/tunnels/_validation.d.ts.map +1 -0
- package/dist/tunnels/_validation.js +27 -0
- package/dist/tunnels/_validation.js.map +1 -0
- package/dist/tunnels/client/_bridge.d.ts +35 -0
- package/dist/tunnels/client/_bridge.d.ts.map +1 -0
- package/dist/tunnels/client/_bridge.js +52 -0
- package/dist/tunnels/client/_bridge.js.map +1 -0
- package/dist/tunnels/client/_callable_streaming.d.ts +25 -0
- package/dist/tunnels/client/_callable_streaming.d.ts.map +1 -0
- package/dist/tunnels/client/_callable_streaming.js +158 -0
- package/dist/tunnels/client/_callable_streaming.js.map +1 -0
- package/dist/tunnels/client/_cert.d.ts +45 -0
- package/dist/tunnels/client/_cert.d.ts.map +1 -0
- package/dist/tunnels/client/_cert.js +193 -0
- package/dist/tunnels/client/_cert.js.map +1 -0
- package/dist/tunnels/client/_dispatch.d.ts +109 -0
- package/dist/tunnels/client/_dispatch.d.ts.map +1 -0
- package/dist/tunnels/client/_dispatch.js +314 -0
- package/dist/tunnels/client/_dispatch.js.map +1 -0
- package/dist/tunnels/client/_envelope.d.ts +55 -0
- package/dist/tunnels/client/_envelope.d.ts.map +1 -0
- package/dist/tunnels/client/_envelope.js +97 -0
- package/dist/tunnels/client/_envelope.js.map +1 -0
- package/dist/tunnels/client/_h1_server.d.ts +37 -0
- package/dist/tunnels/client/_h1_server.d.ts.map +1 -0
- package/dist/tunnels/client/_h1_server.js +433 -0
- package/dist/tunnels/client/_h1_server.js.map +1 -0
- package/dist/tunnels/client/_h2_transcode.d.ts +43 -0
- package/dist/tunnels/client/_h2_transcode.d.ts.map +1 -0
- package/dist/tunnels/client/_h2_transcode.js +488 -0
- package/dist/tunnels/client/_h2_transcode.js.map +1 -0
- package/dist/tunnels/client/_handler.d.ts +62 -0
- package/dist/tunnels/client/_handler.d.ts.map +1 -0
- package/dist/tunnels/client/_handler.js +121 -0
- package/dist/tunnels/client/_handler.js.map +1 -0
- package/dist/tunnels/client/_listener.d.ts +64 -0
- package/dist/tunnels/client/_listener.d.ts.map +1 -0
- package/dist/tunnels/client/_listener.js +113 -0
- package/dist/tunnels/client/_listener.js.map +1 -0
- package/dist/tunnels/client/_protocol.d.ts +67 -0
- package/dist/tunnels/client/_protocol.d.ts.map +1 -0
- package/dist/tunnels/client/_protocol.js +86 -0
- package/dist/tunnels/client/_protocol.js.map +1 -0
- package/dist/tunnels/client/_runtime.d.ts +143 -0
- package/dist/tunnels/client/_runtime.d.ts.map +1 -0
- package/dist/tunnels/client/_runtime.js +1679 -0
- package/dist/tunnels/client/_runtime.js.map +1 -0
- package/dist/tunnels/client/_state.d.ts +45 -0
- package/dist/tunnels/client/_state.d.ts.map +1 -0
- package/dist/tunnels/client/_state.js +165 -0
- package/dist/tunnels/client/_state.js.map +1 -0
- package/dist/tunnels/client/_tls.d.ts +50 -0
- package/dist/tunnels/client/_tls.d.ts.map +1 -0
- package/dist/tunnels/client/_tls.js +139 -0
- package/dist/tunnels/client/_tls.js.map +1 -0
- package/dist/tunnels/client/_upstream_tls.d.ts +25 -0
- package/dist/tunnels/client/_upstream_tls.d.ts.map +1 -0
- package/dist/tunnels/client/_upstream_tls.js +24 -0
- package/dist/tunnels/client/_upstream_tls.js.map +1 -0
- package/dist/tunnels/client/_url_forward.d.ts +92 -0
- package/dist/tunnels/client/_url_forward.d.ts.map +1 -0
- package/dist/tunnels/client/_url_forward.js +255 -0
- package/dist/tunnels/client/_url_forward.js.map +1 -0
- package/dist/tunnels/client/_validation.d.ts +27 -0
- package/dist/tunnels/client/_validation.d.ts.map +1 -0
- package/dist/tunnels/client/_validation.js +96 -0
- package/dist/tunnels/client/_validation.js.map +1 -0
- package/dist/tunnels/client/_ws.d.ts +149 -0
- package/dist/tunnels/client/_ws.d.ts.map +1 -0
- package/dist/tunnels/client/_ws.js +351 -0
- package/dist/tunnels/client/_ws.js.map +1 -0
- package/dist/tunnels/client/_ws_passthrough.d.ts +129 -0
- package/dist/tunnels/client/_ws_passthrough.d.ts.map +1 -0
- package/dist/tunnels/client/_ws_passthrough.js +432 -0
- package/dist/tunnels/client/_ws_passthrough.js.map +1 -0
- package/dist/tunnels/client/_ws_url_bridge.d.ts +71 -0
- package/dist/tunnels/client/_ws_url_bridge.d.ts.map +1 -0
- package/dist/tunnels/client/_ws_url_bridge.js +474 -0
- package/dist/tunnels/client/_ws_url_bridge.js.map +1 -0
- package/dist/tunnels/client/_ws_url_edge_bridge.d.ts +26 -0
- package/dist/tunnels/client/_ws_url_edge_bridge.d.ts.map +1 -0
- package/dist/tunnels/client/_ws_url_edge_bridge.js +256 -0
- package/dist/tunnels/client/_ws_url_edge_bridge.js.map +1 -0
- package/dist/tunnels/client/_wsframe.d.ts +142 -0
- package/dist/tunnels/client/_wsframe.d.ts.map +1 -0
- package/dist/tunnels/client/_wsframe.js +282 -0
- package/dist/tunnels/client/_wsframe.js.map +1 -0
- package/dist/tunnels/client/index.d.ts +101 -0
- package/dist/tunnels/client/index.d.ts.map +1 -0
- package/dist/tunnels/client/index.js +242 -0
- package/dist/tunnels/client/index.js.map +1 -0
- package/dist/tunnels/exceptions.d.ts +31 -0
- package/dist/tunnels/exceptions.d.ts.map +1 -0
- package/dist/tunnels/exceptions.js +68 -0
- package/dist/tunnels/exceptions.js.map +1 -0
- package/dist/tunnels/resources/tunnels.d.ts +73 -0
- package/dist/tunnels/resources/tunnels.d.ts.map +1 -0
- package/dist/tunnels/resources/tunnels.js +173 -0
- package/dist/tunnels/resources/tunnels.js.map +1 -0
- package/dist/tunnels/types.d.ts +99 -0
- package/dist/tunnels/types.d.ts.map +1 -0
- package/dist/tunnels/types.js +76 -0
- package/dist/tunnels/types.js.map +1 -0
- package/package.json +14 -5
- package/protocol/tunnel_protocol_constants.json +65 -0
|
@@ -0,0 +1,474 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* inkbox-tunnels/client/_ws_url_bridge.ts
|
|
3
|
+
*
|
|
4
|
+
* Bridge a WebSocket upgrade between an inbound `WebSocketSink` (h1
|
|
5
|
+
* parser or h2 transcoder) and an `http://` / `https://` URL upstream.
|
|
6
|
+
*
|
|
7
|
+
* Flow per request:
|
|
8
|
+
*
|
|
9
|
+
* 1. Open a TCP / TLS connection to ``forwardTo``.
|
|
10
|
+
* 2. Send a standard h1 ``GET /<path> HTTP/1.1`` upgrade request.
|
|
11
|
+
* 3. Read the upstream's status line + headers; if not 101, reject
|
|
12
|
+
* the inbound sink with the upstream status.
|
|
13
|
+
* 4. Accept on the inbound sink (with the upstream's negotiated
|
|
14
|
+
* subprotocol, when present).
|
|
15
|
+
* 5. Bridge frames: inbound third-party frames re-encoded with the
|
|
16
|
+
* mask bit (we are the h1 client to upstream, RFC 6455 §5.1) and
|
|
17
|
+
* written to the upstream socket; upstream server frames decoded
|
|
18
|
+
* (unmasked) and forwarded back via ``ws.sendFrame``.
|
|
19
|
+
*/
|
|
20
|
+
import * as net from "node:net";
|
|
21
|
+
import * as tls from "node:tls";
|
|
22
|
+
import { randomBytes } from "node:crypto";
|
|
23
|
+
import { computeWsAccept, decodeClientFrame, encodeServerFrame, } from "./_ws_passthrough.js";
|
|
24
|
+
import { WS_OPCODE_CLOSE, encodeWsFrame, } from "./_wsframe.js";
|
|
25
|
+
import { HOP_BY_HOP_REQUEST, HOP_BY_HOP_RESPONSE } from "./_protocol.js";
|
|
26
|
+
import { buildUpstreamTlsConnectOpts } from "./_upstream_tls.js";
|
|
27
|
+
const SKIP_REQUEST_HEADERS = new Set([
|
|
28
|
+
"host",
|
|
29
|
+
"x-forwarded-host",
|
|
30
|
+
"x-forwarded-proto",
|
|
31
|
+
"x-forwarded-for",
|
|
32
|
+
"forwarded",
|
|
33
|
+
"sec-websocket-key",
|
|
34
|
+
"sec-websocket-version",
|
|
35
|
+
"sec-websocket-protocol",
|
|
36
|
+
"upgrade",
|
|
37
|
+
"connection",
|
|
38
|
+
]);
|
|
39
|
+
const UPSTREAM_HANDSHAKE_TIMEOUT_MS = 30_000;
|
|
40
|
+
export class WsUpstreamError extends Error {
|
|
41
|
+
status;
|
|
42
|
+
reason;
|
|
43
|
+
constructor(status, reason) {
|
|
44
|
+
super(reason);
|
|
45
|
+
this.status = status;
|
|
46
|
+
this.reason = reason;
|
|
47
|
+
this.name = "WsUpstreamError";
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Open a TCP/TLS connection to ``forwardTo`` and complete an h1
|
|
52
|
+
* ``Upgrade: websocket`` handshake. Verifies the upstream's
|
|
53
|
+
* ``Sec-WebSocket-Accept`` per RFC 6455 §1.3 and returns the connected
|
|
54
|
+
* socket + negotiated subprotocol + any bytes received past the head
|
|
55
|
+
* (typically empty, but possibly the start of an early-pushed frame).
|
|
56
|
+
*/
|
|
57
|
+
export async function openWsUpstream(opts) {
|
|
58
|
+
const { forwardTo, publicHost, verifyTls, caBundle, requestPath, requestHeaders, wsSubprotocol, forwardedForIp, } = opts;
|
|
59
|
+
const timeoutMs = opts.handshakeTimeoutMs ?? UPSTREAM_HANDSHAKE_TIMEOUT_MS;
|
|
60
|
+
const host = forwardTo.hostname || "localhost";
|
|
61
|
+
const port = forwardTo.port
|
|
62
|
+
? Number(forwardTo.port)
|
|
63
|
+
: forwardTo.protocol === "https:"
|
|
64
|
+
? 443
|
|
65
|
+
: 80;
|
|
66
|
+
let pathOnly = requestPath.startsWith("/")
|
|
67
|
+
? requestPath
|
|
68
|
+
: `/${requestPath}`;
|
|
69
|
+
const baseSegments = forwardTo.pathname.replace(/\/+$/, "");
|
|
70
|
+
if (baseSegments)
|
|
71
|
+
pathOnly = `${baseSegments}${pathOnly}`;
|
|
72
|
+
let socket;
|
|
73
|
+
const connectDeadline = Date.now() + timeoutMs;
|
|
74
|
+
const withTimeout = (p, ms, onTimeout) => new Promise((resolve, reject) => {
|
|
75
|
+
let done = false;
|
|
76
|
+
const timer = setTimeout(() => {
|
|
77
|
+
if (done)
|
|
78
|
+
return;
|
|
79
|
+
done = true;
|
|
80
|
+
onTimeout();
|
|
81
|
+
reject(new Error("timeout"));
|
|
82
|
+
}, Math.max(0, ms));
|
|
83
|
+
p.then((v) => {
|
|
84
|
+
if (done)
|
|
85
|
+
return;
|
|
86
|
+
done = true;
|
|
87
|
+
clearTimeout(timer);
|
|
88
|
+
resolve(v);
|
|
89
|
+
}, (e) => {
|
|
90
|
+
if (done)
|
|
91
|
+
return;
|
|
92
|
+
done = true;
|
|
93
|
+
clearTimeout(timer);
|
|
94
|
+
reject(e);
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
try {
|
|
98
|
+
if (forwardTo.protocol === "https:") {
|
|
99
|
+
const tlsOpts = buildUpstreamTlsConnectOpts({ verify: verifyTls, caBundle });
|
|
100
|
+
socket = tls.connect({
|
|
101
|
+
host, port, servername: host,
|
|
102
|
+
rejectUnauthorized: tlsOpts.rejectUnauthorized,
|
|
103
|
+
ca: tlsOpts.ca,
|
|
104
|
+
});
|
|
105
|
+
const s = socket;
|
|
106
|
+
await withTimeout(new Promise((resolve, reject) => {
|
|
107
|
+
s.once("secureConnect", () => resolve());
|
|
108
|
+
s.once("error", reject);
|
|
109
|
+
}), timeoutMs, () => {
|
|
110
|
+
try {
|
|
111
|
+
s.destroy();
|
|
112
|
+
}
|
|
113
|
+
catch { /* swallow */ }
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
socket = net.connect(port, host);
|
|
118
|
+
const s = socket;
|
|
119
|
+
await withTimeout(new Promise((resolve, reject) => {
|
|
120
|
+
s.once("connect", () => resolve());
|
|
121
|
+
s.once("error", reject);
|
|
122
|
+
}), timeoutMs, () => {
|
|
123
|
+
try {
|
|
124
|
+
s.destroy();
|
|
125
|
+
}
|
|
126
|
+
catch { /* swallow */ }
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
catch (e) {
|
|
131
|
+
if (e?.message === "timeout") {
|
|
132
|
+
throw new WsUpstreamError(504, "upstream-connect-timeout");
|
|
133
|
+
}
|
|
134
|
+
throw new WsUpstreamError(502, `upstream-unreachable: ${String(e)}`);
|
|
135
|
+
}
|
|
136
|
+
const wsKey = randomBytes(16).toString("base64");
|
|
137
|
+
const lines = [
|
|
138
|
+
`GET ${pathOnly} HTTP/1.1`,
|
|
139
|
+
`Host: ${forwardTo.host}`,
|
|
140
|
+
"Connection: Upgrade",
|
|
141
|
+
"Upgrade: websocket",
|
|
142
|
+
"Sec-WebSocket-Version: 13",
|
|
143
|
+
`Sec-WebSocket-Key: ${wsKey}`,
|
|
144
|
+
`X-Forwarded-Host: ${publicHost}`,
|
|
145
|
+
"X-Forwarded-Proto: https",
|
|
146
|
+
];
|
|
147
|
+
if (forwardedForIp !== null) {
|
|
148
|
+
lines.push(`X-Forwarded-For: ${forwardedForIp}`);
|
|
149
|
+
}
|
|
150
|
+
if (wsSubprotocol !== null) {
|
|
151
|
+
lines.push(`Sec-WebSocket-Protocol: ${wsSubprotocol}`);
|
|
152
|
+
}
|
|
153
|
+
for (const [k, v] of requestHeaders) {
|
|
154
|
+
const kl = k.toLowerCase();
|
|
155
|
+
if (kl.startsWith(":"))
|
|
156
|
+
continue;
|
|
157
|
+
if (HOP_BY_HOP_REQUEST.has(kl))
|
|
158
|
+
continue;
|
|
159
|
+
if (SKIP_REQUEST_HEADERS.has(kl))
|
|
160
|
+
continue;
|
|
161
|
+
lines.push(`${k}: ${v}`);
|
|
162
|
+
}
|
|
163
|
+
const upgradeReq = Buffer.from(lines.join("\r\n") + "\r\n\r\n", "ascii");
|
|
164
|
+
try {
|
|
165
|
+
await new Promise((resolve, reject) => {
|
|
166
|
+
socket.write(upgradeReq, (err) => (err ? reject(err) : resolve()));
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
catch {
|
|
170
|
+
socket.destroy();
|
|
171
|
+
throw new WsUpstreamError(502, "upstream-write");
|
|
172
|
+
}
|
|
173
|
+
// Bound the head-read by what's left of the handshake budget.
|
|
174
|
+
const remainingMs = Math.max(0, connectDeadline - Date.now());
|
|
175
|
+
let timedOut = false;
|
|
176
|
+
let result;
|
|
177
|
+
try {
|
|
178
|
+
result = await withTimeout(new Promise((resolve) => {
|
|
179
|
+
let merged = Buffer.alloc(0);
|
|
180
|
+
const onData = (chunk) => {
|
|
181
|
+
merged = Buffer.concat([merged, chunk]);
|
|
182
|
+
const idx = merged.indexOf("\r\n\r\n");
|
|
183
|
+
if (idx === -1) {
|
|
184
|
+
if (merged.length > 65536) {
|
|
185
|
+
socket.off("data", onData);
|
|
186
|
+
resolve(null);
|
|
187
|
+
}
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
socket.off("data", onData);
|
|
191
|
+
const head = merged.subarray(0, idx).toString("latin1");
|
|
192
|
+
const rest = merged.subarray(idx + 4);
|
|
193
|
+
const headLines = head.split("\r\n");
|
|
194
|
+
let status = 502;
|
|
195
|
+
const m = headLines[0]?.match(/^HTTP\/1\.[01]\s+(\d{3})/);
|
|
196
|
+
if (m)
|
|
197
|
+
status = Number(m[1]);
|
|
198
|
+
let sub = null;
|
|
199
|
+
let accept = null;
|
|
200
|
+
let extensions = null;
|
|
201
|
+
const headers = [];
|
|
202
|
+
for (const line of headLines.slice(1)) {
|
|
203
|
+
const ci = line.indexOf(":");
|
|
204
|
+
if (ci === -1)
|
|
205
|
+
continue;
|
|
206
|
+
const name = line.slice(0, ci).trim().toLowerCase();
|
|
207
|
+
const value = line.slice(ci + 1).trim();
|
|
208
|
+
headers.push([name, value]);
|
|
209
|
+
if (name === "sec-websocket-protocol")
|
|
210
|
+
sub = value;
|
|
211
|
+
else if (name === "sec-websocket-accept")
|
|
212
|
+
accept = value;
|
|
213
|
+
else if (name === "sec-websocket-extensions")
|
|
214
|
+
extensions = value;
|
|
215
|
+
}
|
|
216
|
+
resolve({ status, subprotocol: sub, accept, extensions, headers, rest });
|
|
217
|
+
};
|
|
218
|
+
socket.on("data", onData);
|
|
219
|
+
socket.once("error", () => {
|
|
220
|
+
socket.off("data", onData);
|
|
221
|
+
resolve(null);
|
|
222
|
+
});
|
|
223
|
+
socket.once("close", () => {
|
|
224
|
+
socket.off("data", onData);
|
|
225
|
+
resolve(null);
|
|
226
|
+
});
|
|
227
|
+
}), remainingMs, () => {
|
|
228
|
+
timedOut = true;
|
|
229
|
+
try {
|
|
230
|
+
socket.destroy();
|
|
231
|
+
}
|
|
232
|
+
catch { /* swallow */ }
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
catch (e) {
|
|
236
|
+
if (timedOut || e?.message === "timeout") {
|
|
237
|
+
throw new WsUpstreamError(504, "upstream-handshake-timeout");
|
|
238
|
+
}
|
|
239
|
+
throw new WsUpstreamError(502, "upstream-read");
|
|
240
|
+
}
|
|
241
|
+
if (result === null) {
|
|
242
|
+
socket.destroy();
|
|
243
|
+
throw new WsUpstreamError(502, "upstream-read");
|
|
244
|
+
}
|
|
245
|
+
if (result.status !== 101) {
|
|
246
|
+
socket.destroy();
|
|
247
|
+
throw new WsUpstreamError(result.status, `upstream-status-${result.status}`);
|
|
248
|
+
}
|
|
249
|
+
const expectedAccept = computeWsAccept(wsKey);
|
|
250
|
+
if (result.accept !== expectedAccept) {
|
|
251
|
+
socket.destroy();
|
|
252
|
+
throw new WsUpstreamError(502, "upstream-accept-mismatch");
|
|
253
|
+
}
|
|
254
|
+
// We never offer Sec-WebSocket-Extensions; per RFC 6455 §9.1 the server
|
|
255
|
+
// MUST NOT confirm one not offered. Reject defensively — we have no
|
|
256
|
+
// codec for permessage-deflate or any other extension.
|
|
257
|
+
if (result.extensions !== null && result.extensions.length > 0) {
|
|
258
|
+
socket.destroy();
|
|
259
|
+
throw new WsUpstreamError(502, `upstream-unsupported-extensions: ${result.extensions}`);
|
|
260
|
+
}
|
|
261
|
+
// RFC 6455 §4.1: the server's selected subprotocol MUST be one the
|
|
262
|
+
// client offered (or omitted). A misbehaving upstream that picks an
|
|
263
|
+
// un-offered token would force us to advertise something the third
|
|
264
|
+
// party never asked for; the third party then fails the handshake.
|
|
265
|
+
// Reject 502 instead of leaking the broken negotiation.
|
|
266
|
+
if (result.subprotocol !== null && result.subprotocol.length > 0) {
|
|
267
|
+
const offered = parseSubprotocolOffer(wsSubprotocol);
|
|
268
|
+
if (!offered.includes(result.subprotocol)) {
|
|
269
|
+
socket.destroy();
|
|
270
|
+
throw new WsUpstreamError(502, `upstream-subprotocol-not-offered: ${result.subprotocol}`);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
return {
|
|
274
|
+
socket,
|
|
275
|
+
subprotocol: result.subprotocol,
|
|
276
|
+
leftover: result.rest,
|
|
277
|
+
headers: result.headers,
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* Split a ``Sec-WebSocket-Protocol`` request value (comma-separated
|
|
282
|
+
* tokens) into the list the client actually offered. Whitespace is
|
|
283
|
+
* trimmed; empty tokens are dropped. RFC 6455 protocol tokens are
|
|
284
|
+
* case-sensitive — preserve case.
|
|
285
|
+
*/
|
|
286
|
+
function parseSubprotocolOffer(offer) {
|
|
287
|
+
if (offer === null || offer.length === 0)
|
|
288
|
+
return [];
|
|
289
|
+
return offer
|
|
290
|
+
.split(",")
|
|
291
|
+
.map((s) => s.trim())
|
|
292
|
+
.filter((s) => s.length > 0);
|
|
293
|
+
}
|
|
294
|
+
export async function bridgeWsUpgradeToUrl(opts) {
|
|
295
|
+
const { forwardTo, publicHost, verifyTls, caBundle, request, ws } = opts;
|
|
296
|
+
let upstream;
|
|
297
|
+
try {
|
|
298
|
+
upstream = await openWsUpstream({
|
|
299
|
+
forwardTo,
|
|
300
|
+
publicHost,
|
|
301
|
+
verifyTls,
|
|
302
|
+
caBundle,
|
|
303
|
+
requestPath: request.path,
|
|
304
|
+
requestHeaders: request.headers,
|
|
305
|
+
wsSubprotocol: request.wsSubprotocol,
|
|
306
|
+
forwardedForIp: request.forwardedForIp,
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
catch (e) {
|
|
310
|
+
const status = e instanceof WsUpstreamError ? e.status : 502;
|
|
311
|
+
try {
|
|
312
|
+
await ws.reject({ status });
|
|
313
|
+
}
|
|
314
|
+
catch {
|
|
315
|
+
/* swallow */
|
|
316
|
+
}
|
|
317
|
+
return;
|
|
318
|
+
}
|
|
319
|
+
const socket = upstream.socket;
|
|
320
|
+
const headResult = {
|
|
321
|
+
subprotocol: upstream.subprotocol,
|
|
322
|
+
rest: upstream.leftover,
|
|
323
|
+
};
|
|
324
|
+
// Filter the upstream's 101 response headers — same shape as the
|
|
325
|
+
// edge URL forward fix. Application-defined headers (Set-Cookie,
|
|
326
|
+
// X-Use-Inkbox-* opt-outs, custom correlation IDs) flow through;
|
|
327
|
+
// hop-by-hop, ws handshake-control, and h2 pseudo-headers are
|
|
328
|
+
// stripped. sec-websocket-protocol is dropped from the headers list
|
|
329
|
+
// because it rides the dedicated subprotocol arg below — emitting
|
|
330
|
+
// both would double-write the header on the third-party 101.
|
|
331
|
+
const wsHandshakeStrip = new Set([
|
|
332
|
+
"sec-websocket-accept",
|
|
333
|
+
"sec-websocket-extensions",
|
|
334
|
+
"sec-websocket-key",
|
|
335
|
+
"sec-websocket-version",
|
|
336
|
+
"sec-websocket-protocol",
|
|
337
|
+
]);
|
|
338
|
+
const forwardedHeaders = [];
|
|
339
|
+
for (const [hk, hv] of upstream.headers) {
|
|
340
|
+
if (hk.startsWith(":"))
|
|
341
|
+
continue;
|
|
342
|
+
if (HOP_BY_HOP_RESPONSE.has(hk))
|
|
343
|
+
continue;
|
|
344
|
+
if (wsHandshakeStrip.has(hk))
|
|
345
|
+
continue;
|
|
346
|
+
forwardedHeaders.push([hk, hv]);
|
|
347
|
+
}
|
|
348
|
+
try {
|
|
349
|
+
await ws.accept({
|
|
350
|
+
subprotocol: headResult.subprotocol ?? undefined,
|
|
351
|
+
extraHeaders: forwardedHeaders.length > 0 ? forwardedHeaders : undefined,
|
|
352
|
+
});
|
|
353
|
+
}
|
|
354
|
+
catch {
|
|
355
|
+
socket.destroy();
|
|
356
|
+
return;
|
|
357
|
+
}
|
|
358
|
+
// Bridge frames in both directions.
|
|
359
|
+
let upstreamClosed = false;
|
|
360
|
+
let thirdPartyClosed = false;
|
|
361
|
+
const upstreamBuf = [];
|
|
362
|
+
if (headResult.rest.length > 0)
|
|
363
|
+
upstreamBuf.push(headResult.rest);
|
|
364
|
+
// Wake the recvFrame() await on abrupt upstream close. Without it the
|
|
365
|
+
// third-party→upstream loop sits inside recvFrame indefinitely and
|
|
366
|
+
// the bridge task leaks a fd / queued state.
|
|
367
|
+
let signalUpstreamClosed = () => { };
|
|
368
|
+
const upstreamClosedSignal = new Promise((resolve) => {
|
|
369
|
+
signalUpstreamClosed = resolve;
|
|
370
|
+
});
|
|
371
|
+
const upstreamData = (chunk) => {
|
|
372
|
+
upstreamBuf.push(chunk);
|
|
373
|
+
drainUpstream().catch(() => undefined);
|
|
374
|
+
};
|
|
375
|
+
socket.on("data", upstreamData);
|
|
376
|
+
socket.once("close", () => {
|
|
377
|
+
upstreamClosed = true;
|
|
378
|
+
signalUpstreamClosed();
|
|
379
|
+
});
|
|
380
|
+
socket.once("error", () => {
|
|
381
|
+
upstreamClosed = true;
|
|
382
|
+
signalUpstreamClosed();
|
|
383
|
+
});
|
|
384
|
+
// The upstream may already be gone before we attach listeners
|
|
385
|
+
// (close is one-shot). Check explicitly so we don't sit in
|
|
386
|
+
// recvFrame() forever after a fast-closing upstream.
|
|
387
|
+
if (socket.destroyed) {
|
|
388
|
+
upstreamClosed = true;
|
|
389
|
+
signalUpstreamClosed();
|
|
390
|
+
}
|
|
391
|
+
let draining = false;
|
|
392
|
+
async function drainUpstream() {
|
|
393
|
+
if (draining)
|
|
394
|
+
return;
|
|
395
|
+
draining = true;
|
|
396
|
+
try {
|
|
397
|
+
while (!thirdPartyClosed) {
|
|
398
|
+
const decoded = decodeClientFrame(upstreamBuf, {
|
|
399
|
+
requireMask: false,
|
|
400
|
+
});
|
|
401
|
+
if (decoded.kind === "need-more")
|
|
402
|
+
return;
|
|
403
|
+
if (decoded.kind === "rejected") {
|
|
404
|
+
upstreamClosed = true;
|
|
405
|
+
return;
|
|
406
|
+
}
|
|
407
|
+
try {
|
|
408
|
+
await ws.sendFrame(decoded.opcode, decoded.payload, {
|
|
409
|
+
fin: decoded.fin,
|
|
410
|
+
});
|
|
411
|
+
}
|
|
412
|
+
catch {
|
|
413
|
+
return;
|
|
414
|
+
}
|
|
415
|
+
if (decoded.opcode === WS_OPCODE_CLOSE) {
|
|
416
|
+
upstreamClosed = true;
|
|
417
|
+
return;
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
finally {
|
|
422
|
+
draining = false;
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
// Initial drain in case upgrade head shipped trailing frame bytes.
|
|
426
|
+
void drainUpstream();
|
|
427
|
+
// Pump third-party frames into upstream (h1 client masking).
|
|
428
|
+
try {
|
|
429
|
+
while (!upstreamClosed) {
|
|
430
|
+
// Race the recvFrame await against upstream-close so an abrupt
|
|
431
|
+
// RST/EOF doesn't leave us pinned indefinitely.
|
|
432
|
+
const got = await Promise.race([
|
|
433
|
+
ws.recvFrame(),
|
|
434
|
+
upstreamClosedSignal.then(() => null),
|
|
435
|
+
]);
|
|
436
|
+
if (got === null)
|
|
437
|
+
break;
|
|
438
|
+
const { opcode, payload, fin } = got;
|
|
439
|
+
// Preserve fin so multi-frame messages stay fragmented and the
|
|
440
|
+
// upstream can stream them rather than being coalesced into a
|
|
441
|
+
// single FIN=1 frame.
|
|
442
|
+
const frame = encodeWsFrame(opcode, payload, { mask: true, fin });
|
|
443
|
+
try {
|
|
444
|
+
await new Promise((resolve, reject) => {
|
|
445
|
+
if (socket.write(frame, (err) => err ? reject(err) : resolve())) {
|
|
446
|
+
// wrote synchronously
|
|
447
|
+
}
|
|
448
|
+
});
|
|
449
|
+
}
|
|
450
|
+
catch {
|
|
451
|
+
break;
|
|
452
|
+
}
|
|
453
|
+
if (opcode === WS_OPCODE_CLOSE)
|
|
454
|
+
break;
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
finally {
|
|
458
|
+
thirdPartyClosed = true;
|
|
459
|
+
try {
|
|
460
|
+
socket.destroy();
|
|
461
|
+
}
|
|
462
|
+
catch {
|
|
463
|
+
/* swallow */
|
|
464
|
+
}
|
|
465
|
+
try {
|
|
466
|
+
await ws.aclose();
|
|
467
|
+
}
|
|
468
|
+
catch {
|
|
469
|
+
/* swallow */
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
void encodeServerFrame; // silence unused-import lint
|
|
473
|
+
}
|
|
474
|
+
//# sourceMappingURL=_ws_url_bridge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_ws_url_bridge.js","sourceRoot":"","sources":["../../../src/tunnels/client/_ws_url_bridge.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* inkbox-tunnels/client/_ws_url_edge_bridge.ts
|
|
3
|
+
*
|
|
4
|
+
* Edge-mode URL WebSocket bridge.
|
|
5
|
+
*
|
|
6
|
+
* The third party's WS frames arrive over the bridge stream as
|
|
7
|
+
* length-prefixed JSON envelopes wrapped in outer WS BINARY frames
|
|
8
|
+
* (the standard inkbox bridge protocol). We translate each direction:
|
|
9
|
+
*
|
|
10
|
+
* * Bridge → upstream: outer WS frames → inner JSON envelopes →
|
|
11
|
+
* RFC 6455 frames (masked, h1 client-side) written to the upstream
|
|
12
|
+
* socket.
|
|
13
|
+
* * Upstream → bridge: RFC 6455 frames (server, unmasked) → JSON
|
|
14
|
+
* envelopes → outer WS BINARY frames (masked) sent on the bridge
|
|
15
|
+
* via ``WsBridgeIO.sendFrame``.
|
|
16
|
+
*
|
|
17
|
+
* PING / PONG control frames are answered locally and not propagated.
|
|
18
|
+
*/
|
|
19
|
+
import type { WsBridgeIO } from "./_ws.js";
|
|
20
|
+
import type { WsUpstreamHandle } from "./_ws_url_bridge.js";
|
|
21
|
+
export interface PumpEdgeBridgeOpts {
|
|
22
|
+
upstream: WsUpstreamHandle;
|
|
23
|
+
bridge: WsBridgeIO;
|
|
24
|
+
}
|
|
25
|
+
export declare function pumpWsUrlEdgeBridge(opts: PumpEdgeBridgeOpts): Promise<void>;
|
|
26
|
+
//# sourceMappingURL=_ws_url_edge_bridge.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_ws_url_edge_bridge.d.ts","sourceRoot":"","sources":["../../../src/tunnels/client/_ws_url_edge_bridge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAC3C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAc5D,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,MAAM,EAAE,UAAU,CAAC;CACpB;AAED,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,kBAAkB,GACvB,OAAO,CAAC,IAAI,CAAC,CAoPf"}
|