Skip to content

Commit a2ef780

Browse files
committed
improving our use of http-proxy-3 now that I understand this library better
- there was a lot of silliness with close events and close that did nothing, since we were never launching a standalone proxy server - also a lot of silliness involving closing/deleting a ProxyServer instance, which is pointless when there is no http server involved a proxy is just a lightweight configuration object!
1 parent a836b43 commit a2ef780

File tree

6 files changed

+33
-46
lines changed

6 files changed

+33
-46
lines changed

src/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
"build-dev": "./workspaces.py install && ./workspaces.py build --dev",
1010
"clean": "rm -rf packages/node_modules && ./workspaces.py clean && cd compute/compute && pnpm clean ",
1111
"hub": "cd packages/hub && npm run hub-project-dev-nobuild",
12+
"hub-prod": "cd packages/hub && npm run hub-project-prod-nobuild",
1213
"rspack": "cd packages/static && pnpm watch",
1314
"psql": "export PGHOST=${PGHOST:=$INIT_CWD/data/postgres/socket}; PGUSER='smc' psql",
1415
"database": "cd dev/project && ./start_postgres.py",

src/packages/hub/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@
9393
"hub-project-dev-nobuild": "unset DATA COCALC_ROOT BASE_PATH && export DEBUG=${DEBUG:='cocalc:*,-cocalc:silly:*'} && export PGHOST=${PGHOST:=`realpath $INIT_CWD/../../data/postgres/socket`} && PGUSER='smc' NODE_ENV=${NODE_ENV:=development} NODE_OPTIONS='--max_old_space_size=8000 --trace-warnings --enable-source-maps --inspect' cocalc-hub-server --mode=single-user --all --hostname=0.0.0.0",
9494
"hub-personal": "unset DATA COCALC_ROOT BASE_PATH && export DEBUG=${DEBUG:='cocalc:*,-cocalc:silly:*'} && export PGHOST=${PGHOST:=`realpath $INIT_CWD/../../data/postgres/socket`} && PGUSER='smc' NODE_ENV=${NODE_ENV:=development} NODE_OPTIONS='--max_old_space_size=8000 --trace-warnings --enable-source-maps --inspect' cocalc-hub-server --mode=single-user --all --hostname=0.0.0.0 --personal",
9595
"hub-project-dev": "pnpm build && NODE_OPTIONS='--inspect' pnpm hub-project-dev-nobuild",
96-
"hub-project-prod": "pnpm build && unset DATA COCALC_ROOT BASE_PATH && export DEBUG=${DEBUG:='cocalc:*,-cocalc:silly:*'} && export PGHOST=${PGHOST:=`realpath $INIT_CWD/../../data/postgres/socket`} && PGUSER='smc' NODE_ENV=production NODE_OPTIONS='--max_old_space_size=8000 --enable-source-maps' cocalc-hub-server --mode=single-user --all --hostname=0.0.0.0",
96+
"hub-project-prod-nobuild": "unset DATA COCALC_ROOT BASE_PATH && export DEBUG=${DEBUG:='cocalc:*,-cocalc:silly:*'} && export PGHOST=${PGHOST:=`realpath $INIT_CWD/../../data/postgres/socket`} && PGUSER='smc' NODE_ENV=production NODE_OPTIONS='--max_old_space_size=8000 --enable-source-maps' cocalc-hub-server --mode=single-user --all --hostname=0.0.0.0",
9797
"hub-docker-dev": "export DEBUG=${DEBUG:='cocalc:*,-cocalc:silly:*'} && COCALC_DOCKER=true NODE_ENV=development PROJECTS=/projects/[project_id] PORT=443 NODE_OPTIONS='--max_old_space_size=8000 --enable-source-maps --trace-warnings --inspect' cocalc-hub-server --mode=multi-user --all --hostname=0.0.0.0 --https-key=/projects/conf/cert/key.pem --https-cert=/projects/conf/cert/cert.pem",
9898
"hub-docker-prod": "export DEBUG=${DEBUG:='cocalc:*,-cocalc:silly:*'} && COCALC_DOCKER=true NODE_ENV=production PROJECTS=/projects/[project_id] PORT=443 NODE_OPTIONS='--max_old_space_size=8000 --enable-source-maps' cocalc-hub-server --mode=multi-user --all --hostname=0.0.0.0 --https-key=/projects/conf/cert/key.pem --https-cert=/projects/conf/cert/cert.pem",
9999
"hub-docker-prod-nossl": "export DEBUG=${DEBUG:='cocalc:*,-cocalc:silly:*'} && COCALC_DOCKER=true NODE_ENV=production PROJECTS=/projects/[project_id] PORT=80 NODE_OPTIONS='--max_old_space_size=8000 --enable-source-maps' cocalc-hub-server --mode=multi-user --all --hostname=0.0.0.0",

src/packages/hub/proxy/handle-request.ts

Lines changed: 5 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
/* Handle a proxy request */
22

3-
import { createProxyServer } from "http-proxy-3";
3+
import { createProxyServer, type ProxyServer } from "http-proxy-3";
44
import LRU from "lru-cache";
55
import stripRememberMeCookie from "./strip-remember-me-cookie";
66
import { versionCheckFails } from "./version";
7-
import { getTarget, invalidateTargetCache } from "./target";
7+
import { getTarget } from "./target";
88
import getLogger from "../logger";
99
import { stripBasePath } from "./util";
1010
import { ProjectControlFunction } from "@cocalc/server/projects/control";
@@ -34,14 +34,9 @@ export default function init({ projectControl, isPersonal }: Options) {
3434
a permissions and security point of view.
3535
*/
3636

37-
const cache = new LRU({
37+
const cache = new LRU<string, ProxyServer>({
3838
max: 5000,
3939
ttl: 1000 * 60 * 3,
40-
dispose: (proxy) => {
41-
// important to close the proxy whenever it gets removed
42-
// from the cache, to avoid wasting resources.
43-
(proxy as any)?.close();
44-
},
4540
});
4641

4742
async function handleProxyRequest(req, res): Promise<void> {
@@ -158,26 +153,13 @@ export default function init({ projectControl, isPersonal }: Options) {
158153
proxy = createProxyServer({
159154
ws: false,
160155
target,
161-
timeout: 60000,
162156
});
163157
// and cache it.
164158
cache.set(target, proxy);
165159
logger.debug("created new proxy");
166-
// setup error handler, so that if something goes wrong with this proxy (it will,
167-
// e.g., on project restart), we properly invalidate it.
168-
const remove_from_cache = () => {
169-
cache.delete(target); // this also closes the proxy.
170-
invalidateTargetCache(remember_me, url);
171-
};
172-
173-
proxy.on("error", (e) => {
174-
logger.debug("http proxy error event (ending proxy)", e);
175-
remove_from_cache();
176-
});
177160

178-
proxy.on("close", () => {
179-
logger.debug("http proxy close event (ending proxy)");
180-
remove_from_cache();
161+
proxy.on("error", (err) => {
162+
logger.debug(`http proxy error -- ${err}`);
181163
});
182164
}
183165

src/packages/hub/proxy/handle-upgrade.ts

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// Websocket support
22

3-
import { createProxyServer } from "http-proxy-3";
3+
import { createProxyServer, type ProxyServer } from "http-proxy-3";
44
import LRU from "lru-cache";
55
import { getEventListeners } from "node:events";
66
import getLogger from "@cocalc/hub/logger";
@@ -16,7 +16,7 @@ export default function init(
1616
{ projectControl, isPersonal, httpServer, listenersHack },
1717
proxy_regexp: string,
1818
) {
19-
const cache = new LRU({
19+
const cache = new LRU<string, ProxyServer>({
2020
max: 5000,
2121
ttl: 1000 * 60 * 3,
2222
});
@@ -77,17 +77,18 @@ export default function init(
7777
if (cache.has(target)) {
7878
dbg("using cache");
7979
const proxy = cache.get(target);
80-
(proxy as any)?.ws(req, socket, head);
80+
proxy.ws(req, socket, head);
8181
return;
8282
}
8383

8484
dbg("target", target);
8585
dbg("not using cache");
86+
8687
const proxy = createProxyServer({
8788
ws: true,
8889
target,
89-
timeout: 3000,
9090
});
91+
9192
cache.set(target, proxy);
9293

9394
// taken from https://github.com/http-party/node-http-proxy/issues/1401
@@ -107,14 +108,9 @@ export default function init(
107108
});
108109

109110
proxy.on("error", (err) => {
110-
logger.debug(`websocket proxy error, so clearing cache -- ${err}`);
111-
cache.delete(target);
112-
proxy.close();
113-
});
114-
proxy.on("close", () => {
115-
dbg("websocket proxy closed, so removing from cache");
116-
cache.delete(target);
111+
logger.debug(`WARNING: websocket proxy error -- ${err}`);
117112
});
113+
118114
proxy.ws(req, socket, head);
119115
}
120116

src/packages/hub/servers/nats.ts

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ $ pnpm nats-server
1010
1111
*/
1212

13-
import { createProxyServer } from "http-proxy-3";
13+
import { createProxyServer, type ProxyServer } from "http-proxy-3";
1414
import getLogger from "@cocalc/backend/logger";
1515
import { type Router } from "express";
1616
import { natsWebsocketServer } from "@cocalc/backend/data";
@@ -22,6 +22,7 @@ import { delay } from "awaiting";
2222

2323
const logger = getLogger("hub:nats");
2424

25+
let proxy: ProxyServer | null = null;
2526
export async function proxyNatsWebsocket(req, socket, head) {
2627
const target = natsWebsocketServer;
2728
logger.debug(`nats proxy -- proxying a connection to ${target}`);
@@ -32,16 +33,19 @@ export async function proxyNatsWebsocket(req, socket, head) {
3233
socket.destroy();
3334
return;
3435
}
35-
const proxy = createProxyServer({
36-
ws: true,
37-
target,
38-
timeout: 5000,
39-
});
36+
if (proxy == null) {
37+
// make the proxy server
38+
proxy = createProxyServer({
39+
ws: true,
40+
target,
41+
});
42+
proxy.on("error", (err) => {
43+
logger.debug(`WARNING: nats websocket proxy error -- ${err}`);
44+
});
45+
}
46+
47+
// connect the client's socket to nats via the proxy server:
4048
proxy.ws(req, socket, head);
41-
proxy.on("error", (err) => {
42-
logger.debug(`nats websocket proxy error, so closing -- ${err}`);
43-
proxy.close();
44-
});
4549

4650
while (socket.readyState !== socket.CLOSED) {
4751
if (versionCheckFails(req)) {

src/scripts/g.sh

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ unset DEBUG_CONSOLE
1616
#export NO_RSPACK_DEV_SERVER=yes
1717

1818
while true; do
19-
pnpm hub
19+
if [ x"$COCALC_PROD_MODE" = "x" ]; then
20+
pnpm hub
21+
else
22+
pnpm hub-prod
23+
fi
2024
sleep 1
2125
done

0 commit comments

Comments
 (0)