Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemathinc
GitHub Repository: sagemathinc/cocalc
Path: blob/master/src/packages/hub/proxy/proxy-conat.ts
1496 views
1
/*
2
Conat WebSocket proxy -- this primarily just directly proxied the conats
3
socketio websocket server, so outside browsers can connect to it.
4
So far I'm only using this for testing, but it could be useful in a non-kubernetes
5
setting, where we need certain types of scalability.
6
*/
7
8
import { createProxyServer, type ProxyServer } from "http-proxy-3";
9
import getLogger from "@cocalc/backend/logger";
10
import {
11
conatServer as conatServer0,
12
conatClusterPort,
13
} from "@cocalc/backend/data";
14
import basePath from "@cocalc/backend/base-path";
15
import { conat } from "@cocalc/backend/conat";
16
import { type Client } from "@cocalc/conat/core/client";
17
import { delay } from "awaiting";
18
19
const logger = getLogger("hub:proxy-conat");
20
21
const ADDRESS_UPDATE_INTERVAL = 30_000;
22
23
export async function proxyConatWebsocket(req, socket, head) {
24
const i = req.url.lastIndexOf("/conat");
25
const target = randomServer() + req.url.slice(i);
26
logger.debug(`conat proxy -- proxying a WEBSOCKET connection to ${target}`);
27
// todo -- allowing no cookie, since that's used by projects and compute servers!
28
// do NOT disable this until compute servers all set a cookie... which could be a long time.
29
// make the proxy server
30
const proxy: ProxyServer = createProxyServer({
31
ws: true,
32
secure: false,
33
target,
34
});
35
proxy.on("error", (err) => {
36
logger.debug(`WARNING: conat websocket proxy error -- ${err}`);
37
});
38
39
// connect the client's socket to conat via the proxy server:
40
proxy.ws(req, socket, head);
41
}
42
43
let client: Client | null = null;
44
let addresses: string[] = [];
45
function randomServer(): string {
46
if (client == null) {
47
addressUpdateLoop();
48
}
49
if (addresses.length == 0) {
50
addresses.push(
51
conatServer0
52
? conatServer0
53
: `http://localhost:${conatClusterPort}${basePath.length > 1 ? basePath : ""}`,
54
);
55
return addresses[0];
56
}
57
// random choice
58
const i = Math.floor(Math.random() * addresses.length);
59
return addresses[i];
60
}
61
62
async function addressUpdateLoop() {
63
client = conat();
64
await client.waitUntilSignedIn();
65
if (!client.info?.clusterName) {
66
// no point -- not a cluster
67
return;
68
}
69
while (true) {
70
try {
71
addresses = await client.cluster();
72
logger.debug("addressUpdateLoop: got", addresses);
73
} catch (err) {
74
logger.debug(
75
"addressUpdateLoop: error -- updating cluster addresses",
76
err,
77
);
78
}
79
await delay(ADDRESS_UPDATE_INTERVAL);
80
}
81
}
82
83