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