unplugin-https-reverse-proxy 4.1.0-beta.3 → 4.1.0-beta.5
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/dist/{chunk-HBXMM25C.js → chunk-A3KSOGWY.js} +272 -652
- package/dist/esbuild.cjs +275 -655
- package/dist/esbuild.js +1 -1
- package/dist/index.cjs +275 -655
- package/dist/index.js +1 -1
- package/dist/nuxt.cjs +273 -653
- package/dist/nuxt.js +1 -1
- package/dist/privileged-helper.cjs +110 -13
- package/dist/privileged-helper.js +111 -14
- package/dist/rollup.cjs +275 -655
- package/dist/rollup.js +1 -1
- package/dist/rspack.cjs +275 -655
- package/dist/rspack.js +1 -1
- package/dist/vite.cjs +275 -655
- package/dist/vite.js +1 -1
- package/dist/webpack.cjs +275 -655
- package/dist/webpack.js +1 -1
- package/package.json +1 -1
- package/src/caddy/config.ts +176 -57
- package/src/caddy/index.ts +82 -125
- package/src/privileged/bootstrap.ts +83 -2
- package/src/privileged/launch.ts +46 -9
- package/src/privileged/server.ts +95 -14
- package/src/privileged/session.ts +63 -14
package/dist/nuxt.js
CHANGED
|
@@ -29,6 +29,7 @@ var import_node_process3 = __toESM(require("process"), 1);
|
|
|
29
29
|
var import_node_buffer = require("buffer");
|
|
30
30
|
var import_node_fs2 = require("fs");
|
|
31
31
|
var import_node_net3 = require("net");
|
|
32
|
+
var import_node_path2 = require("path");
|
|
32
33
|
var import_node_process2 = __toESM(require("process"), 1);
|
|
33
34
|
|
|
34
35
|
// src/privileged/server.ts
|
|
@@ -215,6 +216,28 @@ function createHelperRuntime(deps) {
|
|
|
215
216
|
let teardown;
|
|
216
217
|
let generation = 0;
|
|
217
218
|
let caddy;
|
|
219
|
+
const hostOwners = /* @__PURE__ */ new Map();
|
|
220
|
+
const hostId = (ip, host) => `${ip} ${host.toLowerCase()}`;
|
|
221
|
+
function addHostOwner(client, ip, host) {
|
|
222
|
+
const id = hostId(ip, host);
|
|
223
|
+
let owners = hostOwners.get(id);
|
|
224
|
+
if (!owners) {
|
|
225
|
+
owners = /* @__PURE__ */ new Set();
|
|
226
|
+
hostOwners.set(id, owners);
|
|
227
|
+
}
|
|
228
|
+
owners.add(client ?? deps);
|
|
229
|
+
}
|
|
230
|
+
function releaseHostOwner(client, ip, host) {
|
|
231
|
+
const id = hostId(ip, host);
|
|
232
|
+
const owners = hostOwners.get(id);
|
|
233
|
+
if (!owners)
|
|
234
|
+
return true;
|
|
235
|
+
owners.delete(client ?? deps);
|
|
236
|
+
if (owners.size > 0)
|
|
237
|
+
return false;
|
|
238
|
+
hostOwners.delete(id);
|
|
239
|
+
return true;
|
|
240
|
+
}
|
|
218
241
|
const broadcast = (event) => {
|
|
219
242
|
const line = serializeMessage(event);
|
|
220
243
|
for (const client of clients) {
|
|
@@ -273,7 +296,7 @@ function createHelperRuntime(deps) {
|
|
|
273
296
|
return false;
|
|
274
297
|
}
|
|
275
298
|
}
|
|
276
|
-
async function handle(request) {
|
|
299
|
+
async function handle(request, client) {
|
|
277
300
|
try {
|
|
278
301
|
switch (request.method) {
|
|
279
302
|
case "ping":
|
|
@@ -285,6 +308,7 @@ function createHelperRuntime(deps) {
|
|
|
285
308
|
const edited = addHost(deps.readHosts(), ip, host);
|
|
286
309
|
if (edited.changed)
|
|
287
310
|
deps.writeHosts(edited.content);
|
|
311
|
+
addHostOwner(client, ip, host);
|
|
288
312
|
await flushDnsBestEffort(deps);
|
|
289
313
|
return { id: request.id, ok: true };
|
|
290
314
|
}
|
|
@@ -292,6 +316,9 @@ function createHelperRuntime(deps) {
|
|
|
292
316
|
const { ip, host } = request.params;
|
|
293
317
|
if (!isSafeIp(ip) || !isSafeHost(host))
|
|
294
318
|
return { id: request.id, ok: false, error: { message: "invalid hosts entry" } };
|
|
319
|
+
const last = releaseHostOwner(client, ip, host);
|
|
320
|
+
if (!last)
|
|
321
|
+
return { id: request.id, ok: true, result: { kept: true } };
|
|
295
322
|
const edited = removeHost(deps.readHosts(), ip, host);
|
|
296
323
|
if (edited.changed)
|
|
297
324
|
deps.writeHosts(edited.content);
|
|
@@ -302,14 +329,14 @@ function createHelperRuntime(deps) {
|
|
|
302
329
|
const { port } = request.params;
|
|
303
330
|
if (!isAllowedFreePort(port))
|
|
304
331
|
return { id: request.id, ok: false, error: { message: `port ${port} is not releasable` } };
|
|
305
|
-
const killed = await deps.freePort(port);
|
|
332
|
+
const killed = await deps.freePort(port, caddy == null ? void 0 : caddy.pid);
|
|
306
333
|
return { id: request.id, ok: true, result: { killed } };
|
|
307
334
|
}
|
|
308
335
|
case "caddy.start": {
|
|
309
|
-
if (caddy)
|
|
310
|
-
|
|
336
|
+
if (caddy && caddy.running !== false)
|
|
337
|
+
return { id: request.id, ok: true, result: { pid: caddy.pid, started: false } };
|
|
311
338
|
caddy = deps.startCaddy(broadcast);
|
|
312
|
-
return { id: request.id, ok: true, result: { pid: caddy.pid } };
|
|
339
|
+
return { id: request.id, ok: true, result: { pid: caddy.pid, started: true } };
|
|
313
340
|
}
|
|
314
341
|
case "caddy.stop": {
|
|
315
342
|
await stopCaddy();
|
|
@@ -335,6 +362,21 @@ function createHelperRuntime(deps) {
|
|
|
335
362
|
},
|
|
336
363
|
async detach(client) {
|
|
337
364
|
clients.delete(client);
|
|
365
|
+
for (const [id, owners] of [...hostOwners]) {
|
|
366
|
+
if (!owners.delete(client) || owners.size > 0)
|
|
367
|
+
continue;
|
|
368
|
+
hostOwners.delete(id);
|
|
369
|
+
const [ip, host] = id.split(" ");
|
|
370
|
+
try {
|
|
371
|
+
const edited = removeHost(deps.readHosts(), ip, host);
|
|
372
|
+
if (edited.changed) {
|
|
373
|
+
deps.writeHosts(edited.content);
|
|
374
|
+
await flushDnsBestEffort(deps);
|
|
375
|
+
}
|
|
376
|
+
} catch (error) {
|
|
377
|
+
deps.log(`hosts cleanup failed: ${error.message}`);
|
|
378
|
+
}
|
|
379
|
+
}
|
|
338
380
|
if (clients.size === 0)
|
|
339
381
|
await dispose();
|
|
340
382
|
},
|
|
@@ -408,11 +450,11 @@ function createNodeHelperDeps(options) {
|
|
|
408
450
|
}
|
|
409
451
|
throw lastError ?? new Error("no DNS cache flush command for this platform");
|
|
410
452
|
},
|
|
411
|
-
freePort: async (port) => {
|
|
453
|
+
freePort: async (port, keepPid) => {
|
|
412
454
|
const pids = (0, import_node_os.platform)() === "win32" ? parseWindowsListeningPids((await execFileAsync("netstat", ["-ano"])).stdout, port) : parseListeningPids((await execFileQuiet("lsof", [`-ti:${port}`, "-sTCP:LISTEN"])).stdout);
|
|
413
455
|
const killed = [];
|
|
414
456
|
for (const pid of pids) {
|
|
415
|
-
if (pid === import_node_process.default.pid)
|
|
457
|
+
if (pid === import_node_process.default.pid || keepPid !== void 0 && pid === keepPid)
|
|
416
458
|
continue;
|
|
417
459
|
try {
|
|
418
460
|
import_node_process.default.kill(pid, "SIGTERM");
|
|
@@ -431,16 +473,24 @@ function createNodeHelperDeps(options) {
|
|
|
431
473
|
storageOwner: options.storageOwner,
|
|
432
474
|
startCaddy: (emit) => {
|
|
433
475
|
var _a, _b;
|
|
434
|
-
const child = (0, import_node_child_process.spawn)(options.caddyBin, ["run", "--adapter", "caddyfile", "--config", options.caddyConfigPath], {
|
|
476
|
+
const child = (0, import_node_child_process.spawn)(options.caddyBin, ["run", "--adapter", "caddyfile", "--config", options.caddyConfigPath, "--watch"], {
|
|
435
477
|
cwd: options.caddyCwd ?? import_node_process.default.cwd(),
|
|
436
478
|
env: { ...import_node_process.default.env, ...options.caddyEnv },
|
|
437
479
|
stdio: ["ignore", "pipe", "pipe"]
|
|
438
480
|
});
|
|
481
|
+
const handle = {
|
|
482
|
+
pid: child.pid,
|
|
483
|
+
kill: (signal) => child.kill(signal),
|
|
484
|
+
running: true
|
|
485
|
+
};
|
|
439
486
|
(_a = child.stdout) == null ? void 0 : _a.on("data", (data) => emit({ type: "event", kind: "caddy.stdout", data: data.toString() }));
|
|
440
487
|
(_b = child.stderr) == null ? void 0 : _b.on("data", (data) => emit({ type: "event", kind: "caddy.stderr", data: data.toString() }));
|
|
441
|
-
child.on("exit", (code, signal) =>
|
|
442
|
-
|
|
443
|
-
|
|
488
|
+
child.on("exit", (code, signal) => {
|
|
489
|
+
handle.running = false;
|
|
490
|
+
emit({ type: "event", kind: "caddy.exit", code, signal });
|
|
491
|
+
});
|
|
492
|
+
caddy = handle;
|
|
493
|
+
return handle;
|
|
444
494
|
},
|
|
445
495
|
stopCaddy: async () => {
|
|
446
496
|
const current = caddy;
|
|
@@ -474,7 +524,7 @@ function attachSocket(socket, runtime, log) {
|
|
|
474
524
|
log(`invalid request: ${error.message}`);
|
|
475
525
|
continue;
|
|
476
526
|
}
|
|
477
|
-
void runtime.handle(request).then((response) => {
|
|
527
|
+
void runtime.handle(request, socket).then((response) => {
|
|
478
528
|
if (!socket.destroyed)
|
|
479
529
|
socket.write(serializeMessage(response));
|
|
480
530
|
});
|
|
@@ -490,6 +540,7 @@ function attachSocket(socket, runtime, log) {
|
|
|
490
540
|
|
|
491
541
|
// src/privileged/bootstrap.ts
|
|
492
542
|
var HANDSHAKE_TIMEOUT_MS = 12e4;
|
|
543
|
+
var DEFAULT_IDLE_TIMEOUT_MS = 3e4;
|
|
493
544
|
async function startHelper(options) {
|
|
494
545
|
const { socketPath, token } = options;
|
|
495
546
|
const log = options.log ?? ((message) => import_node_process2.default.stdout.write(`[uhrp-helper] ${message}
|
|
@@ -512,12 +563,25 @@ async function startHelper(options) {
|
|
|
512
563
|
} catch {
|
|
513
564
|
}
|
|
514
565
|
const connections = /* @__PURE__ */ new Set();
|
|
566
|
+
const idleTimeoutMs = options.idleTimeoutMs ?? DEFAULT_IDLE_TIMEOUT_MS;
|
|
567
|
+
let idleTimer;
|
|
568
|
+
const stopIdleTimer = () => {
|
|
569
|
+
if (idleTimer) {
|
|
570
|
+
clearTimeout(idleTimer);
|
|
571
|
+
idleTimer = void 0;
|
|
572
|
+
}
|
|
573
|
+
};
|
|
515
574
|
const server = (0, import_node_net3.createServer)((socket) => {
|
|
516
575
|
var _a;
|
|
517
576
|
let buffer = "";
|
|
518
577
|
let authenticated = false;
|
|
578
|
+
stopIdleTimer();
|
|
519
579
|
connections.add(socket);
|
|
520
|
-
socket.on("close", () =>
|
|
580
|
+
socket.on("close", () => {
|
|
581
|
+
connections.delete(socket);
|
|
582
|
+
if (connections.size === 0)
|
|
583
|
+
scheduleIdleExit();
|
|
584
|
+
});
|
|
521
585
|
const timer = setTimeout(() => {
|
|
522
586
|
if (!authenticated)
|
|
523
587
|
socket.destroy();
|
|
@@ -559,10 +623,27 @@ async function startHelper(options) {
|
|
|
559
623
|
socket.on("error", () => {
|
|
560
624
|
});
|
|
561
625
|
});
|
|
626
|
+
function scheduleIdleExit() {
|
|
627
|
+
var _a;
|
|
628
|
+
if (idleTimer || connections.size > 0)
|
|
629
|
+
return;
|
|
630
|
+
idleTimer = setTimeout(() => {
|
|
631
|
+
var _a2, _b;
|
|
632
|
+
idleTimer = void 0;
|
|
633
|
+
if (connections.size > 0)
|
|
634
|
+
return;
|
|
635
|
+
log("no clients left; shutting down");
|
|
636
|
+
removeOwnSocket(socketPath, token);
|
|
637
|
+
server.close(() => import_node_process2.default.exit(0));
|
|
638
|
+
(_b = (_a2 = setTimeout(() => import_node_process2.default.exit(0), 1e3)).unref) == null ? void 0 : _b.call(_a2);
|
|
639
|
+
}, idleTimeoutMs);
|
|
640
|
+
(_a = idleTimer.unref) == null ? void 0 : _a.call(idleTimer);
|
|
641
|
+
}
|
|
562
642
|
await new Promise((resolve, reject) => {
|
|
563
643
|
server.once("error", reject);
|
|
564
644
|
server.listen(socketPath, () => resolve());
|
|
565
645
|
});
|
|
646
|
+
scheduleIdleExit();
|
|
566
647
|
try {
|
|
567
648
|
if (typeof options.ownerUid === "number") {
|
|
568
649
|
(0, import_node_fs2.chownSync)(socketPath, options.ownerUid, options.ownerGid ?? options.ownerUid);
|
|
@@ -585,6 +666,22 @@ async function startHelper(options) {
|
|
|
585
666
|
}
|
|
586
667
|
};
|
|
587
668
|
}
|
|
669
|
+
function removeOwnSocket(socketPath, token) {
|
|
670
|
+
if (import_node_process2.default.platform === "win32")
|
|
671
|
+
return;
|
|
672
|
+
try {
|
|
673
|
+
const tokensDir = (0, import_node_path2.dirname)(socketPath);
|
|
674
|
+
const tokenFile = (0, import_node_path2.join)(tokensDir, "helper.token");
|
|
675
|
+
const current = (0, import_node_fs2.existsSync)(tokenFile) ? (0, import_node_fs2.readFileSync)(tokenFile, "utf8").trim() : void 0;
|
|
676
|
+
if (current === token)
|
|
677
|
+
(0, import_node_fs2.rmSync)(tokenFile, { force: true });
|
|
678
|
+
} catch {
|
|
679
|
+
}
|
|
680
|
+
try {
|
|
681
|
+
(0, import_node_fs2.rmSync)(socketPath, { force: true });
|
|
682
|
+
} catch {
|
|
683
|
+
}
|
|
684
|
+
}
|
|
588
685
|
|
|
589
686
|
// src/privileged-helper.ts
|
|
590
687
|
function parseArgs(argv) {
|
|
@@ -7,8 +7,9 @@ import process3 from "node:process";
|
|
|
7
7
|
|
|
8
8
|
// src/privileged/bootstrap.ts
|
|
9
9
|
import { Buffer } from "node:buffer";
|
|
10
|
-
import { chmodSync, chownSync, rmSync } from "node:fs";
|
|
10
|
+
import { chmodSync, chownSync, existsSync, readFileSync as readFileSync2, rmSync } from "node:fs";
|
|
11
11
|
import { createServer } from "node:net";
|
|
12
|
+
import { dirname, join as join2 } from "node:path";
|
|
12
13
|
import process2 from "node:process";
|
|
13
14
|
|
|
14
15
|
// src/privileged/server.ts
|
|
@@ -189,6 +190,28 @@ function createHelperRuntime(deps) {
|
|
|
189
190
|
let teardown;
|
|
190
191
|
let generation = 0;
|
|
191
192
|
let caddy;
|
|
193
|
+
const hostOwners = /* @__PURE__ */ new Map();
|
|
194
|
+
const hostId = (ip, host) => `${ip} ${host.toLowerCase()}`;
|
|
195
|
+
function addHostOwner(client, ip, host) {
|
|
196
|
+
const id = hostId(ip, host);
|
|
197
|
+
let owners = hostOwners.get(id);
|
|
198
|
+
if (!owners) {
|
|
199
|
+
owners = /* @__PURE__ */ new Set();
|
|
200
|
+
hostOwners.set(id, owners);
|
|
201
|
+
}
|
|
202
|
+
owners.add(client ?? deps);
|
|
203
|
+
}
|
|
204
|
+
function releaseHostOwner(client, ip, host) {
|
|
205
|
+
const id = hostId(ip, host);
|
|
206
|
+
const owners = hostOwners.get(id);
|
|
207
|
+
if (!owners)
|
|
208
|
+
return true;
|
|
209
|
+
owners.delete(client ?? deps);
|
|
210
|
+
if (owners.size > 0)
|
|
211
|
+
return false;
|
|
212
|
+
hostOwners.delete(id);
|
|
213
|
+
return true;
|
|
214
|
+
}
|
|
192
215
|
const broadcast = (event) => {
|
|
193
216
|
const line = serializeMessage(event);
|
|
194
217
|
for (const client of clients) {
|
|
@@ -247,7 +270,7 @@ function createHelperRuntime(deps) {
|
|
|
247
270
|
return false;
|
|
248
271
|
}
|
|
249
272
|
}
|
|
250
|
-
async function handle(request) {
|
|
273
|
+
async function handle(request, client) {
|
|
251
274
|
try {
|
|
252
275
|
switch (request.method) {
|
|
253
276
|
case "ping":
|
|
@@ -259,6 +282,7 @@ function createHelperRuntime(deps) {
|
|
|
259
282
|
const edited = addHost(deps.readHosts(), ip, host);
|
|
260
283
|
if (edited.changed)
|
|
261
284
|
deps.writeHosts(edited.content);
|
|
285
|
+
addHostOwner(client, ip, host);
|
|
262
286
|
await flushDnsBestEffort(deps);
|
|
263
287
|
return { id: request.id, ok: true };
|
|
264
288
|
}
|
|
@@ -266,6 +290,9 @@ function createHelperRuntime(deps) {
|
|
|
266
290
|
const { ip, host } = request.params;
|
|
267
291
|
if (!isSafeIp(ip) || !isSafeHost(host))
|
|
268
292
|
return { id: request.id, ok: false, error: { message: "invalid hosts entry" } };
|
|
293
|
+
const last = releaseHostOwner(client, ip, host);
|
|
294
|
+
if (!last)
|
|
295
|
+
return { id: request.id, ok: true, result: { kept: true } };
|
|
269
296
|
const edited = removeHost(deps.readHosts(), ip, host);
|
|
270
297
|
if (edited.changed)
|
|
271
298
|
deps.writeHosts(edited.content);
|
|
@@ -276,14 +303,14 @@ function createHelperRuntime(deps) {
|
|
|
276
303
|
const { port } = request.params;
|
|
277
304
|
if (!isAllowedFreePort(port))
|
|
278
305
|
return { id: request.id, ok: false, error: { message: `port ${port} is not releasable` } };
|
|
279
|
-
const killed = await deps.freePort(port);
|
|
306
|
+
const killed = await deps.freePort(port, caddy == null ? void 0 : caddy.pid);
|
|
280
307
|
return { id: request.id, ok: true, result: { killed } };
|
|
281
308
|
}
|
|
282
309
|
case "caddy.start": {
|
|
283
|
-
if (caddy)
|
|
284
|
-
|
|
310
|
+
if (caddy && caddy.running !== false)
|
|
311
|
+
return { id: request.id, ok: true, result: { pid: caddy.pid, started: false } };
|
|
285
312
|
caddy = deps.startCaddy(broadcast);
|
|
286
|
-
return { id: request.id, ok: true, result: { pid: caddy.pid } };
|
|
313
|
+
return { id: request.id, ok: true, result: { pid: caddy.pid, started: true } };
|
|
287
314
|
}
|
|
288
315
|
case "caddy.stop": {
|
|
289
316
|
await stopCaddy();
|
|
@@ -309,6 +336,21 @@ function createHelperRuntime(deps) {
|
|
|
309
336
|
},
|
|
310
337
|
async detach(client) {
|
|
311
338
|
clients.delete(client);
|
|
339
|
+
for (const [id, owners] of [...hostOwners]) {
|
|
340
|
+
if (!owners.delete(client) || owners.size > 0)
|
|
341
|
+
continue;
|
|
342
|
+
hostOwners.delete(id);
|
|
343
|
+
const [ip, host] = id.split(" ");
|
|
344
|
+
try {
|
|
345
|
+
const edited = removeHost(deps.readHosts(), ip, host);
|
|
346
|
+
if (edited.changed) {
|
|
347
|
+
deps.writeHosts(edited.content);
|
|
348
|
+
await flushDnsBestEffort(deps);
|
|
349
|
+
}
|
|
350
|
+
} catch (error) {
|
|
351
|
+
deps.log(`hosts cleanup failed: ${error.message}`);
|
|
352
|
+
}
|
|
353
|
+
}
|
|
312
354
|
if (clients.size === 0)
|
|
313
355
|
await dispose();
|
|
314
356
|
},
|
|
@@ -382,11 +424,11 @@ function createNodeHelperDeps(options) {
|
|
|
382
424
|
}
|
|
383
425
|
throw lastError ?? new Error("no DNS cache flush command for this platform");
|
|
384
426
|
},
|
|
385
|
-
freePort: async (port) => {
|
|
427
|
+
freePort: async (port, keepPid) => {
|
|
386
428
|
const pids = platform() === "win32" ? parseWindowsListeningPids((await execFileAsync("netstat", ["-ano"])).stdout, port) : parseListeningPids((await execFileQuiet("lsof", [`-ti:${port}`, "-sTCP:LISTEN"])).stdout);
|
|
387
429
|
const killed = [];
|
|
388
430
|
for (const pid of pids) {
|
|
389
|
-
if (pid === process.pid)
|
|
431
|
+
if (pid === process.pid || keepPid !== void 0 && pid === keepPid)
|
|
390
432
|
continue;
|
|
391
433
|
try {
|
|
392
434
|
process.kill(pid, "SIGTERM");
|
|
@@ -405,16 +447,24 @@ function createNodeHelperDeps(options) {
|
|
|
405
447
|
storageOwner: options.storageOwner,
|
|
406
448
|
startCaddy: (emit) => {
|
|
407
449
|
var _a, _b;
|
|
408
|
-
const child = spawn(options.caddyBin, ["run", "--adapter", "caddyfile", "--config", options.caddyConfigPath], {
|
|
450
|
+
const child = spawn(options.caddyBin, ["run", "--adapter", "caddyfile", "--config", options.caddyConfigPath, "--watch"], {
|
|
409
451
|
cwd: options.caddyCwd ?? process.cwd(),
|
|
410
452
|
env: { ...process.env, ...options.caddyEnv },
|
|
411
453
|
stdio: ["ignore", "pipe", "pipe"]
|
|
412
454
|
});
|
|
455
|
+
const handle = {
|
|
456
|
+
pid: child.pid,
|
|
457
|
+
kill: (signal) => child.kill(signal),
|
|
458
|
+
running: true
|
|
459
|
+
};
|
|
413
460
|
(_a = child.stdout) == null ? void 0 : _a.on("data", (data) => emit({ type: "event", kind: "caddy.stdout", data: data.toString() }));
|
|
414
461
|
(_b = child.stderr) == null ? void 0 : _b.on("data", (data) => emit({ type: "event", kind: "caddy.stderr", data: data.toString() }));
|
|
415
|
-
child.on("exit", (code, signal) =>
|
|
416
|
-
|
|
417
|
-
|
|
462
|
+
child.on("exit", (code, signal) => {
|
|
463
|
+
handle.running = false;
|
|
464
|
+
emit({ type: "event", kind: "caddy.exit", code, signal });
|
|
465
|
+
});
|
|
466
|
+
caddy = handle;
|
|
467
|
+
return handle;
|
|
418
468
|
},
|
|
419
469
|
stopCaddy: async () => {
|
|
420
470
|
const current = caddy;
|
|
@@ -448,7 +498,7 @@ function attachSocket(socket, runtime, log) {
|
|
|
448
498
|
log(`invalid request: ${error.message}`);
|
|
449
499
|
continue;
|
|
450
500
|
}
|
|
451
|
-
void runtime.handle(request).then((response) => {
|
|
501
|
+
void runtime.handle(request, socket).then((response) => {
|
|
452
502
|
if (!socket.destroyed)
|
|
453
503
|
socket.write(serializeMessage(response));
|
|
454
504
|
});
|
|
@@ -464,6 +514,7 @@ function attachSocket(socket, runtime, log) {
|
|
|
464
514
|
|
|
465
515
|
// src/privileged/bootstrap.ts
|
|
466
516
|
var HANDSHAKE_TIMEOUT_MS = 12e4;
|
|
517
|
+
var DEFAULT_IDLE_TIMEOUT_MS = 3e4;
|
|
467
518
|
async function startHelper(options) {
|
|
468
519
|
const { socketPath, token } = options;
|
|
469
520
|
const log = options.log ?? ((message) => process2.stdout.write(`[uhrp-helper] ${message}
|
|
@@ -486,12 +537,25 @@ async function startHelper(options) {
|
|
|
486
537
|
} catch {
|
|
487
538
|
}
|
|
488
539
|
const connections = /* @__PURE__ */ new Set();
|
|
540
|
+
const idleTimeoutMs = options.idleTimeoutMs ?? DEFAULT_IDLE_TIMEOUT_MS;
|
|
541
|
+
let idleTimer;
|
|
542
|
+
const stopIdleTimer = () => {
|
|
543
|
+
if (idleTimer) {
|
|
544
|
+
clearTimeout(idleTimer);
|
|
545
|
+
idleTimer = void 0;
|
|
546
|
+
}
|
|
547
|
+
};
|
|
489
548
|
const server = createServer((socket) => {
|
|
490
549
|
var _a;
|
|
491
550
|
let buffer = "";
|
|
492
551
|
let authenticated = false;
|
|
552
|
+
stopIdleTimer();
|
|
493
553
|
connections.add(socket);
|
|
494
|
-
socket.on("close", () =>
|
|
554
|
+
socket.on("close", () => {
|
|
555
|
+
connections.delete(socket);
|
|
556
|
+
if (connections.size === 0)
|
|
557
|
+
scheduleIdleExit();
|
|
558
|
+
});
|
|
495
559
|
const timer = setTimeout(() => {
|
|
496
560
|
if (!authenticated)
|
|
497
561
|
socket.destroy();
|
|
@@ -533,10 +597,27 @@ async function startHelper(options) {
|
|
|
533
597
|
socket.on("error", () => {
|
|
534
598
|
});
|
|
535
599
|
});
|
|
600
|
+
function scheduleIdleExit() {
|
|
601
|
+
var _a;
|
|
602
|
+
if (idleTimer || connections.size > 0)
|
|
603
|
+
return;
|
|
604
|
+
idleTimer = setTimeout(() => {
|
|
605
|
+
var _a2, _b;
|
|
606
|
+
idleTimer = void 0;
|
|
607
|
+
if (connections.size > 0)
|
|
608
|
+
return;
|
|
609
|
+
log("no clients left; shutting down");
|
|
610
|
+
removeOwnSocket(socketPath, token);
|
|
611
|
+
server.close(() => process2.exit(0));
|
|
612
|
+
(_b = (_a2 = setTimeout(() => process2.exit(0), 1e3)).unref) == null ? void 0 : _b.call(_a2);
|
|
613
|
+
}, idleTimeoutMs);
|
|
614
|
+
(_a = idleTimer.unref) == null ? void 0 : _a.call(idleTimer);
|
|
615
|
+
}
|
|
536
616
|
await new Promise((resolve, reject) => {
|
|
537
617
|
server.once("error", reject);
|
|
538
618
|
server.listen(socketPath, () => resolve());
|
|
539
619
|
});
|
|
620
|
+
scheduleIdleExit();
|
|
540
621
|
try {
|
|
541
622
|
if (typeof options.ownerUid === "number") {
|
|
542
623
|
chownSync(socketPath, options.ownerUid, options.ownerGid ?? options.ownerUid);
|
|
@@ -559,6 +640,22 @@ async function startHelper(options) {
|
|
|
559
640
|
}
|
|
560
641
|
};
|
|
561
642
|
}
|
|
643
|
+
function removeOwnSocket(socketPath, token) {
|
|
644
|
+
if (process2.platform === "win32")
|
|
645
|
+
return;
|
|
646
|
+
try {
|
|
647
|
+
const tokensDir = dirname(socketPath);
|
|
648
|
+
const tokenFile = join2(tokensDir, "helper.token");
|
|
649
|
+
const current = existsSync(tokenFile) ? readFileSync2(tokenFile, "utf8").trim() : void 0;
|
|
650
|
+
if (current === token)
|
|
651
|
+
rmSync(tokenFile, { force: true });
|
|
652
|
+
} catch {
|
|
653
|
+
}
|
|
654
|
+
try {
|
|
655
|
+
rmSync(socketPath, { force: true });
|
|
656
|
+
} catch {
|
|
657
|
+
}
|
|
658
|
+
}
|
|
562
659
|
|
|
563
660
|
// src/privileged-helper.ts
|
|
564
661
|
function parseArgs(argv) {
|