vite-plugin-rpx 0.11.22 → 0.11.24
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/index.js +280 -83
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -22443,6 +22443,151 @@ var init_https = __esm(() => {
|
|
|
22443
22443
|
SHARED_DEV_HOST_CERT_PATH = join12(homedir8(), ".stacks", "ssl", "rpx.localhost.crt");
|
|
22444
22444
|
});
|
|
22445
22445
|
|
|
22446
|
+
// ../rpx/src/load-balancer.ts
|
|
22447
|
+
function resolveHealthCheckConfig(config6) {
|
|
22448
|
+
return {
|
|
22449
|
+
enabled: config6?.enabled ?? false,
|
|
22450
|
+
path: config6?.path ?? DEFAULT_HEALTH_CHECK_PATH,
|
|
22451
|
+
interval: config6?.interval ?? DEFAULT_HEALTH_CHECK_INTERVAL_MS,
|
|
22452
|
+
timeout: config6?.timeout ?? DEFAULT_HEALTH_CHECK_TIMEOUT_MS,
|
|
22453
|
+
healthyThreshold: config6?.healthyThreshold ?? DEFAULT_HEALTHY_THRESHOLD,
|
|
22454
|
+
unhealthyThreshold: config6?.unhealthyThreshold ?? DEFAULT_UNHEALTHY_THRESHOLD
|
|
22455
|
+
};
|
|
22456
|
+
}
|
|
22457
|
+
function normalizeUpstreams(from) {
|
|
22458
|
+
const list = Array.isArray(from) ? from : [from];
|
|
22459
|
+
return list.map((entry) => {
|
|
22460
|
+
const target = typeof entry === "string" ? { url: entry } : entry;
|
|
22461
|
+
return {
|
|
22462
|
+
url: target.url,
|
|
22463
|
+
weight: target.weight && target.weight > 0 ? target.weight : 1,
|
|
22464
|
+
healthy: true,
|
|
22465
|
+
activeConnections: 0,
|
|
22466
|
+
consecutiveFailures: 0,
|
|
22467
|
+
consecutiveSuccesses: 0
|
|
22468
|
+
};
|
|
22469
|
+
});
|
|
22470
|
+
}
|
|
22471
|
+
function primaryUpstreamUrl(from) {
|
|
22472
|
+
if (!from)
|
|
22473
|
+
return "localhost:5173";
|
|
22474
|
+
const first = Array.isArray(from) ? from[0] : from;
|
|
22475
|
+
if (!first)
|
|
22476
|
+
return "localhost:5173";
|
|
22477
|
+
return typeof first === "string" ? first : first.url;
|
|
22478
|
+
}
|
|
22479
|
+
function createUpstreamPool(from, lbConfig) {
|
|
22480
|
+
return {
|
|
22481
|
+
upstreams: normalizeUpstreams(from),
|
|
22482
|
+
strategy: lbConfig?.strategy ?? "round-robin",
|
|
22483
|
+
healthCheck: resolveHealthCheckConfig(lbConfig?.healthCheck),
|
|
22484
|
+
cursor: 0,
|
|
22485
|
+
wrrCurrentWeights: [],
|
|
22486
|
+
healthCheckTimer: null
|
|
22487
|
+
};
|
|
22488
|
+
}
|
|
22489
|
+
function healthyUpstreams(pool) {
|
|
22490
|
+
const healthy = pool.upstreams.filter((u2) => u2.healthy);
|
|
22491
|
+
if (healthy.length === 0 && pool.upstreams.length === 1)
|
|
22492
|
+
return pool.upstreams;
|
|
22493
|
+
return healthy;
|
|
22494
|
+
}
|
|
22495
|
+
function selectRoundRobin(pool, candidates) {
|
|
22496
|
+
const idx = pool.cursor % candidates.length;
|
|
22497
|
+
pool.cursor = (pool.cursor + 1) % candidates.length;
|
|
22498
|
+
return candidates[idx];
|
|
22499
|
+
}
|
|
22500
|
+
function selectWeightedRoundRobin(pool, candidates) {
|
|
22501
|
+
if (pool.wrrCurrentWeights.length !== candidates.length)
|
|
22502
|
+
pool.wrrCurrentWeights = candidates.map(() => 0);
|
|
22503
|
+
const totalWeight = candidates.reduce((sum, u2) => sum + u2.weight, 0);
|
|
22504
|
+
let bestIdx = 0;
|
|
22505
|
+
for (let i2 = 0;i2 < candidates.length; i2++) {
|
|
22506
|
+
pool.wrrCurrentWeights[i2] += candidates[i2].weight;
|
|
22507
|
+
if (pool.wrrCurrentWeights[i2] > pool.wrrCurrentWeights[bestIdx])
|
|
22508
|
+
bestIdx = i2;
|
|
22509
|
+
}
|
|
22510
|
+
pool.wrrCurrentWeights[bestIdx] -= totalWeight;
|
|
22511
|
+
return candidates[bestIdx];
|
|
22512
|
+
}
|
|
22513
|
+
function selectLeastConnections(candidates) {
|
|
22514
|
+
let best = candidates[0];
|
|
22515
|
+
for (let i2 = 1;i2 < candidates.length; i2++) {
|
|
22516
|
+
if (candidates[i2].activeConnections < best.activeConnections)
|
|
22517
|
+
best = candidates[i2];
|
|
22518
|
+
}
|
|
22519
|
+
return best;
|
|
22520
|
+
}
|
|
22521
|
+
function selectUpstream(pool) {
|
|
22522
|
+
const candidates = healthyUpstreams(pool);
|
|
22523
|
+
if (candidates.length === 0)
|
|
22524
|
+
return;
|
|
22525
|
+
if (candidates.length === 1)
|
|
22526
|
+
return candidates[0];
|
|
22527
|
+
switch (pool.strategy) {
|
|
22528
|
+
case "weighted-round-robin":
|
|
22529
|
+
return selectWeightedRoundRobin(pool, candidates);
|
|
22530
|
+
case "least-connections":
|
|
22531
|
+
return selectLeastConnections(candidates);
|
|
22532
|
+
case "round-robin":
|
|
22533
|
+
default:
|
|
22534
|
+
return selectRoundRobin(pool, candidates);
|
|
22535
|
+
}
|
|
22536
|
+
}
|
|
22537
|
+
function markSuccess(pool, upstream) {
|
|
22538
|
+
upstream.consecutiveFailures = 0;
|
|
22539
|
+
upstream.consecutiveSuccesses += 1;
|
|
22540
|
+
if (!upstream.healthy && upstream.consecutiveSuccesses >= pool.healthCheck.healthyThreshold)
|
|
22541
|
+
upstream.healthy = true;
|
|
22542
|
+
}
|
|
22543
|
+
function markFailure(pool, upstream) {
|
|
22544
|
+
upstream.consecutiveSuccesses = 0;
|
|
22545
|
+
upstream.consecutiveFailures += 1;
|
|
22546
|
+
if (upstream.healthy && upstream.consecutiveFailures >= pool.healthCheck.unhealthyThreshold)
|
|
22547
|
+
upstream.healthy = false;
|
|
22548
|
+
}
|
|
22549
|
+
function splitHostPort(hostPort) {
|
|
22550
|
+
const idx = hostPort.lastIndexOf(":");
|
|
22551
|
+
if (idx === -1)
|
|
22552
|
+
return { hostname: hostPort, port: 80 };
|
|
22553
|
+
const port = Number(hostPort.slice(idx + 1));
|
|
22554
|
+
return { hostname: hostPort.slice(0, idx), port: Number.isFinite(port) ? port : 80 };
|
|
22555
|
+
}
|
|
22556
|
+
async function probeUpstream(pool, upstream) {
|
|
22557
|
+
const { hostname, port } = splitHostPort(upstream.url);
|
|
22558
|
+
const controller = new AbortController;
|
|
22559
|
+
const timer = setTimeout(() => controller.abort(), pool.healthCheck.timeout);
|
|
22560
|
+
try {
|
|
22561
|
+
const res = await fetch(`http://${hostname}:${port}${pool.healthCheck.path}`, {
|
|
22562
|
+
signal: controller.signal,
|
|
22563
|
+
redirect: "manual"
|
|
22564
|
+
});
|
|
22565
|
+
res.body?.cancel().catch(() => {});
|
|
22566
|
+
markSuccess(pool, upstream);
|
|
22567
|
+
} catch {
|
|
22568
|
+
markFailure(pool, upstream);
|
|
22569
|
+
} finally {
|
|
22570
|
+
clearTimeout(timer);
|
|
22571
|
+
}
|
|
22572
|
+
}
|
|
22573
|
+
function startHealthChecks(pool) {
|
|
22574
|
+
if (!pool.healthCheck.enabled || pool.healthCheckTimer || pool.upstreams.length < 2)
|
|
22575
|
+
return;
|
|
22576
|
+
const timer = setInterval(() => {
|
|
22577
|
+
for (const upstream of pool.upstreams)
|
|
22578
|
+
probeUpstream(pool, upstream);
|
|
22579
|
+
}, pool.healthCheck.interval);
|
|
22580
|
+
timer.unref?.();
|
|
22581
|
+
pool.healthCheckTimer = timer;
|
|
22582
|
+
}
|
|
22583
|
+
function stopHealthChecks(pool) {
|
|
22584
|
+
if (pool.healthCheckTimer) {
|
|
22585
|
+
clearInterval(pool.healthCheckTimer);
|
|
22586
|
+
pool.healthCheckTimer = null;
|
|
22587
|
+
}
|
|
22588
|
+
}
|
|
22589
|
+
var DEFAULT_HEALTHY_THRESHOLD = 2, DEFAULT_UNHEALTHY_THRESHOLD = 3, DEFAULT_HEALTH_CHECK_PATH = "/", DEFAULT_HEALTH_CHECK_INTERVAL_MS = 1e4, DEFAULT_HEALTH_CHECK_TIMEOUT_MS = 2000;
|
|
22590
|
+
|
|
22446
22591
|
// ../rpx/src/auth.ts
|
|
22447
22592
|
import { createHash, timingSafeEqual } from "node:crypto";
|
|
22448
22593
|
import { readFileSync as readFileSync2 } from "node:fs";
|
|
@@ -23542,8 +23687,15 @@ function stripBasePath(pathname, basePath) {
|
|
|
23542
23687
|
}
|
|
23543
23688
|
return pathname;
|
|
23544
23689
|
}
|
|
23545
|
-
function
|
|
23546
|
-
|
|
23690
|
+
function pickUpstream(route) {
|
|
23691
|
+
if (route.upstreamPool)
|
|
23692
|
+
return selectUpstream(route.upstreamPool);
|
|
23693
|
+
if (route.sourceHost)
|
|
23694
|
+
return { url: route.sourceHost, weight: 1, healthy: true, activeConnections: 0, consecutiveFailures: 0, consecutiveSuccesses: 0 };
|
|
23695
|
+
return;
|
|
23696
|
+
}
|
|
23697
|
+
function resolveTarget(pathname, route, upstream, verbose) {
|
|
23698
|
+
let targetHost = upstream?.url ?? route.sourceHost ?? "";
|
|
23547
23699
|
const stripBase = route.stripBasePathPrefix ?? false;
|
|
23548
23700
|
let targetPath = stripBase ? stripBasePath(pathname, route.basePath) : pathname;
|
|
23549
23701
|
const rewriteMatch = resolvePathRewrite(targetPath, route.pathRewrites);
|
|
@@ -23598,9 +23750,10 @@ function createProxyFetchHandler(getRoute, verbose, onNoRoute) {
|
|
|
23598
23750
|
return serveStaticFile(staticPath, route.static);
|
|
23599
23751
|
}
|
|
23600
23752
|
if (req.headers.get("upgrade")?.toLowerCase() === "websocket") {
|
|
23601
|
-
|
|
23753
|
+
const wsUpstream = pickUpstream(route);
|
|
23754
|
+
if (!server || !wsUpstream)
|
|
23602
23755
|
return new Response("WebSocket upgrade not supported here", { status: 400 });
|
|
23603
|
-
const { targetHost: targetHost2, targetPath: targetPath2 } = resolveTarget(pathname, route, verbose);
|
|
23756
|
+
const { targetHost: targetHost2, targetPath: targetPath2 } = resolveTarget(pathname, route, wsUpstream, verbose);
|
|
23604
23757
|
const targetUrl = `ws://${targetHost2}${targetPath2}${search}`;
|
|
23605
23758
|
const forwardHeaders = {};
|
|
23606
23759
|
for (const [k2, v2] of req.headers) {
|
|
@@ -23619,8 +23772,10 @@ function createProxyFetchHandler(getRoute, verbose, onNoRoute) {
|
|
|
23619
23772
|
}
|
|
23620
23773
|
return new Response("WebSocket upgrade failed", { status: 400 });
|
|
23621
23774
|
}
|
|
23622
|
-
|
|
23775
|
+
const upstream = pickUpstream(route);
|
|
23776
|
+
if (!upstream) {
|
|
23623
23777
|
return new Response(`No upstream configured for ${hostname}`, { status: 502 });
|
|
23778
|
+
}
|
|
23624
23779
|
if (route.cleanUrls && pathname.endsWith(".html")) {
|
|
23625
23780
|
const cleanPath = pathname.replace(/\.html$/, "");
|
|
23626
23781
|
return new Response(null, {
|
|
@@ -23628,11 +23783,14 @@ function createProxyFetchHandler(getRoute, verbose, onNoRoute) {
|
|
|
23628
23783
|
headers: { Location: cleanPath }
|
|
23629
23784
|
});
|
|
23630
23785
|
}
|
|
23631
|
-
const { targetHost, targetPath } = resolveTarget(pathname, route, verbose);
|
|
23632
|
-
const originOverride = route.changeOrigin ? `http://${
|
|
23786
|
+
const { targetHost, targetPath } = resolveTarget(pathname, route, upstream, verbose);
|
|
23787
|
+
const originOverride = route.changeOrigin ? `http://${targetHost}` : undefined;
|
|
23633
23788
|
const hasBody = req.body != null && req.method !== "GET" && req.method !== "HEAD";
|
|
23789
|
+
const pool = route.upstreamPool;
|
|
23790
|
+
if (pool)
|
|
23791
|
+
upstream.activeConnections++;
|
|
23634
23792
|
try {
|
|
23635
|
-
|
|
23793
|
+
const res = await proxyViaPool({
|
|
23636
23794
|
hostPort: targetHost,
|
|
23637
23795
|
method: req.method,
|
|
23638
23796
|
path: `${targetPath}${search}`,
|
|
@@ -23641,9 +23799,14 @@ function createProxyFetchHandler(getRoute, verbose, onNoRoute) {
|
|
|
23641
23799
|
originOverride,
|
|
23642
23800
|
body: req.body
|
|
23643
23801
|
});
|
|
23802
|
+
if (pool)
|
|
23803
|
+
markSuccess(pool, upstream);
|
|
23804
|
+
return res;
|
|
23644
23805
|
} catch (err) {
|
|
23645
23806
|
if (err === TIMEOUT) {
|
|
23646
23807
|
debugLog("request", `Upstream timeout for ${hostname}`, verbose);
|
|
23808
|
+
if (pool)
|
|
23809
|
+
markFailure(pool, upstream);
|
|
23647
23810
|
return new Response("Gateway Timeout", { status: 504 });
|
|
23648
23811
|
}
|
|
23649
23812
|
if (err === POOL_BUSY) {
|
|
@@ -23659,19 +23822,29 @@ function createProxyFetchHandler(getRoute, verbose, onNoRoute) {
|
|
|
23659
23822
|
headers.set("x-forwarded-host", hostname);
|
|
23660
23823
|
if (originOverride !== undefined)
|
|
23661
23824
|
headers.set("origin", originOverride);
|
|
23662
|
-
|
|
23825
|
+
const res = await fetch(`http://${targetHost}${targetPath}${search}`, {
|
|
23663
23826
|
method: req.method,
|
|
23664
23827
|
headers,
|
|
23665
23828
|
body: req.body,
|
|
23666
23829
|
redirect: "manual"
|
|
23667
23830
|
});
|
|
23831
|
+
if (pool)
|
|
23832
|
+
markSuccess(pool, upstream);
|
|
23833
|
+
return res;
|
|
23668
23834
|
} catch (fetchErr) {
|
|
23669
23835
|
debugLog("request", `Proxy error for ${hostname}: ${fetchErr}`, verbose);
|
|
23836
|
+
if (pool)
|
|
23837
|
+
markFailure(pool, upstream);
|
|
23670
23838
|
return new Response(`Proxy Error: ${fetchErr}`, { status: 502 });
|
|
23671
23839
|
}
|
|
23672
23840
|
}
|
|
23673
23841
|
debugLog("request", `Proxy error for ${hostname}: ${err}`, verbose);
|
|
23842
|
+
if (pool)
|
|
23843
|
+
markFailure(pool, upstream);
|
|
23674
23844
|
return new Response(`Proxy Error: ${err}`, { status: 502 });
|
|
23845
|
+
} finally {
|
|
23846
|
+
if (pool)
|
|
23847
|
+
upstream.activeConnections--;
|
|
23675
23848
|
}
|
|
23676
23849
|
};
|
|
23677
23850
|
return async (req, server) => {
|
|
@@ -23778,6 +23951,24 @@ var init_proxy_handler = __esm(() => {
|
|
|
23778
23951
|
]);
|
|
23779
23952
|
});
|
|
23780
23953
|
|
|
23954
|
+
// ../rpx/src/acme-challenge.ts
|
|
23955
|
+
import * as fs3 from "node:fs";
|
|
23956
|
+
import * as path3 from "node:path";
|
|
23957
|
+
function readAcmeChallenge(webroot, pathname) {
|
|
23958
|
+
if (!webroot || !pathname.startsWith(ACME_CHALLENGE_PREFIX2))
|
|
23959
|
+
return null;
|
|
23960
|
+
const token = pathname.slice(ACME_CHALLENGE_PREFIX2.length);
|
|
23961
|
+
if (!token || !/^[A-Za-z0-9_-]+$/.test(token))
|
|
23962
|
+
return null;
|
|
23963
|
+
try {
|
|
23964
|
+
return fs3.readFileSync(path3.join(webroot, token), "utf8");
|
|
23965
|
+
} catch {
|
|
23966
|
+
return null;
|
|
23967
|
+
}
|
|
23968
|
+
}
|
|
23969
|
+
var ACME_CHALLENGE_PREFIX2 = "/.well-known/acme-challenge/";
|
|
23970
|
+
var init_acme_challenge = () => {};
|
|
23971
|
+
|
|
23781
23972
|
// ../rpx/src/host-match.ts
|
|
23782
23973
|
function isWildcardPattern(pattern) {
|
|
23783
23974
|
return pattern.startsWith("*.");
|
|
@@ -23790,10 +23981,10 @@ function matchesWildcard(hostname, pattern) {
|
|
|
23790
23981
|
}
|
|
23791
23982
|
|
|
23792
23983
|
// ../rpx/src/host-routes.ts
|
|
23793
|
-
function normalizePathPrefix(
|
|
23794
|
-
if (!
|
|
23984
|
+
function normalizePathPrefix(path4) {
|
|
23985
|
+
if (!path4 || path4 === "/")
|
|
23795
23986
|
return "/";
|
|
23796
|
-
let p2 =
|
|
23987
|
+
let p2 = path4.trim();
|
|
23797
23988
|
if (!p2.startsWith("/"))
|
|
23798
23989
|
p2 = `/${p2}`;
|
|
23799
23990
|
p2 = p2.replace(/\/+$/, "");
|
|
@@ -23820,8 +24011,8 @@ function buildHostRoutes(entries) {
|
|
|
23820
24011
|
const table = new Map;
|
|
23821
24012
|
for (const [host, paths] of byHost) {
|
|
23822
24013
|
const list = [];
|
|
23823
|
-
for (const [
|
|
23824
|
-
list.push({ path:
|
|
24014
|
+
for (const [path4, route] of paths)
|
|
24015
|
+
list.push({ path: path4, route });
|
|
23825
24016
|
list.sort((a2, b2) => b2.path.length - a2.path.length);
|
|
23826
24017
|
table.set(host, list);
|
|
23827
24018
|
}
|
|
@@ -23860,7 +24051,7 @@ var init_host_routes = () => {};
|
|
|
23860
24051
|
|
|
23861
24052
|
// ../rpx/src/sni.ts
|
|
23862
24053
|
import * as fsp from "node:fs/promises";
|
|
23863
|
-
import * as
|
|
24054
|
+
import * as path4 from "node:path";
|
|
23864
24055
|
function serverNameFromCertFilename(filename) {
|
|
23865
24056
|
if (!filename.endsWith(".crt"))
|
|
23866
24057
|
return null;
|
|
@@ -23898,8 +24089,8 @@ async function buildSniTlsConfig(cfg, verbose) {
|
|
|
23898
24089
|
continue;
|
|
23899
24090
|
const base = name.slice(0, -".crt".length);
|
|
23900
24091
|
bySrvName.set(serverName, {
|
|
23901
|
-
certPath:
|
|
23902
|
-
keyPath:
|
|
24092
|
+
certPath: path4.join(cfg.certsDir, name),
|
|
24093
|
+
keyPath: path4.join(cfg.certsDir, `${base}.key`)
|
|
23903
24094
|
});
|
|
23904
24095
|
}
|
|
23905
24096
|
}
|
|
@@ -23921,7 +24112,7 @@ var init_sni = __esm(() => {
|
|
|
23921
24112
|
|
|
23922
24113
|
// ../rpx/src/on-demand.ts
|
|
23923
24114
|
import * as fsp2 from "node:fs/promises";
|
|
23924
|
-
import * as
|
|
24115
|
+
import * as path5 from "node:path";
|
|
23925
24116
|
function matchesAllowedSuffix(host, suffixes) {
|
|
23926
24117
|
if (!suffixes || suffixes.length === 0)
|
|
23927
24118
|
return false;
|
|
@@ -24072,8 +24263,8 @@ class OnDemandCertManager {
|
|
|
24072
24263
|
}
|
|
24073
24264
|
pathsFor(host) {
|
|
24074
24265
|
return {
|
|
24075
|
-
certPath:
|
|
24076
|
-
keyPath:
|
|
24266
|
+
certPath: path5.join(this.certsDir, `${host}.crt`),
|
|
24267
|
+
keyPath: path5.join(this.certsDir, `${host}.key`)
|
|
24077
24268
|
};
|
|
24078
24269
|
}
|
|
24079
24270
|
async persist(host, certPem, keyPem) {
|
|
@@ -24232,10 +24423,10 @@ var init_port_manager = __esm(() => {
|
|
|
24232
24423
|
// ../rpx/src/registry.ts
|
|
24233
24424
|
import * as fsp3 from "node:fs/promises";
|
|
24234
24425
|
import { homedir as homedir9 } from "node:os";
|
|
24235
|
-
import * as
|
|
24426
|
+
import * as path6 from "node:path";
|
|
24236
24427
|
import * as process23 from "node:process";
|
|
24237
24428
|
function getRegistryDir() {
|
|
24238
|
-
return
|
|
24429
|
+
return path6.join(homedir9(), ".stacks", "rpx", "registry.d");
|
|
24239
24430
|
}
|
|
24240
24431
|
function isValidId(id) {
|
|
24241
24432
|
return typeof id === "string" && id.length > 0 && id.length <= 128 && ID_PATTERN.test(id);
|
|
@@ -24243,7 +24434,7 @@ function isValidId(id) {
|
|
|
24243
24434
|
function entryPath(dir, id) {
|
|
24244
24435
|
if (!isValidId(id))
|
|
24245
24436
|
throw new Error(`invalid registry id: ${JSON.stringify(id)}`);
|
|
24246
|
-
return
|
|
24437
|
+
return path6.join(dir, `${id}.json`);
|
|
24247
24438
|
}
|
|
24248
24439
|
function isPidAlive(pid2) {
|
|
24249
24440
|
if (!Number.isInteger(pid2) || pid2 <= 0)
|
|
@@ -24260,7 +24451,7 @@ function isValidEntry(value) {
|
|
|
24260
24451
|
return false;
|
|
24261
24452
|
const e = value;
|
|
24262
24453
|
const pidOk = e.pid === undefined || typeof e.pid === "number" && Number.isInteger(e.pid) && e.pid > 0;
|
|
24263
|
-
const hasFrom = typeof e.from === "string" && e.from.length > 0;
|
|
24454
|
+
const hasFrom = typeof e.from === "string" && e.from.length > 0 || Array.isArray(e.from) && e.from.length > 0;
|
|
24264
24455
|
const hasStatic = typeof e.static === "string" || !!e.static && typeof e.static === "object" && typeof e.static.dir === "string";
|
|
24265
24456
|
const pathOk = e.path === undefined || typeof e.path === "string";
|
|
24266
24457
|
return typeof e.id === "string" && isValidId(e.id) && (hasFrom || hasStatic) && typeof e.to === "string" && e.to.length > 0 && pathOk && pidOk && typeof e.createdAt === "string";
|
|
@@ -24301,11 +24492,11 @@ var init_registry = __esm(() => {
|
|
|
24301
24492
|
});
|
|
24302
24493
|
|
|
24303
24494
|
// ../rpx/src/site-supervisor.ts
|
|
24304
|
-
import { closeSync as closeSync6, openSync as openSync6, readFileSync as
|
|
24495
|
+
import { closeSync as closeSync6, openSync as openSync6, readFileSync as readFileSync4 } from "node:fs";
|
|
24305
24496
|
import * as fsp4 from "node:fs/promises";
|
|
24306
24497
|
import { spawn } from "node:child_process";
|
|
24307
24498
|
import { homedir as homedir10 } from "node:os";
|
|
24308
|
-
import * as
|
|
24499
|
+
import * as path7 from "node:path";
|
|
24309
24500
|
import * as process25 from "node:process";
|
|
24310
24501
|
|
|
24311
24502
|
class SiteSupervisor {
|
|
@@ -24331,7 +24522,7 @@ class SiteSupervisor {
|
|
|
24331
24522
|
constructor(opts) {
|
|
24332
24523
|
this.resolver = opts.resolver;
|
|
24333
24524
|
this.registryDir = opts.registryDir ?? getRegistryDir();
|
|
24334
|
-
this.rpxDir = opts.rpxDir ??
|
|
24525
|
+
this.rpxDir = opts.rpxDir ?? path7.join(homedir10(), ".stacks", "rpx");
|
|
24335
24526
|
this.verbose = opts.verbose ?? false;
|
|
24336
24527
|
this.startupTimeoutMs = opts.startupTimeoutMs ?? DEFAULT_STARTUP_TIMEOUT_MS;
|
|
24337
24528
|
this.pollIntervalMs = opts.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS;
|
|
@@ -24386,8 +24577,8 @@ class SiteSupervisor {
|
|
|
24386
24577
|
ports.set(route.portEnv, port);
|
|
24387
24578
|
}
|
|
24388
24579
|
}
|
|
24389
|
-
const logPath =
|
|
24390
|
-
await fsp4.mkdir(
|
|
24580
|
+
const logPath = path7.join(this.rpxDir, "sites", `${site.id}.log`);
|
|
24581
|
+
await fsp4.mkdir(path7.dirname(logPath), { recursive: true }).catch(() => {});
|
|
24391
24582
|
const env2 = this.buildEnv(site, ports);
|
|
24392
24583
|
let handle = null;
|
|
24393
24584
|
let startError;
|
|
@@ -24525,7 +24716,7 @@ class SiteSupervisor {
|
|
|
24525
24716
|
}
|
|
24526
24717
|
readLogTail(state, lines = 40) {
|
|
24527
24718
|
try {
|
|
24528
|
-
const text =
|
|
24719
|
+
const text = readFileSync4(state.logPath, "utf8");
|
|
24529
24720
|
return text.split(`
|
|
24530
24721
|
`).slice(-lines).join(`
|
|
24531
24722
|
`).trim();
|
|
@@ -24683,12 +24874,12 @@ var init_site_supervisor = __esm(() => {
|
|
|
24683
24874
|
// ../rpx/src/dns-state.ts
|
|
24684
24875
|
import * as fsp5 from "node:fs/promises";
|
|
24685
24876
|
import { homedir as homedir11 } from "node:os";
|
|
24686
|
-
import * as
|
|
24877
|
+
import * as path8 from "node:path";
|
|
24687
24878
|
function defaultRpxDir() {
|
|
24688
|
-
return
|
|
24879
|
+
return path8.join(homedir11(), ".stacks", "rpx");
|
|
24689
24880
|
}
|
|
24690
24881
|
function getDnsStatePath(rpxDir = defaultRpxDir()) {
|
|
24691
|
-
return
|
|
24882
|
+
return path8.join(rpxDir, RPX_DNS_STATE_FILE);
|
|
24692
24883
|
}
|
|
24693
24884
|
async function loadDnsState(rpxDir = defaultRpxDir()) {
|
|
24694
24885
|
try {
|
|
@@ -24792,7 +24983,7 @@ __export(exports_dns, {
|
|
|
24792
24983
|
});
|
|
24793
24984
|
import dgram from "node:dgram";
|
|
24794
24985
|
import * as fsp6 from "node:fs/promises";
|
|
24795
|
-
import * as
|
|
24986
|
+
import * as path9 from "node:path";
|
|
24796
24987
|
import * as process26 from "node:process";
|
|
24797
24988
|
function parseHeader(buffer) {
|
|
24798
24989
|
return {
|
|
@@ -25027,7 +25218,7 @@ port ${DNS_PORT}
|
|
|
25027
25218
|
`;
|
|
25028
25219
|
}
|
|
25029
25220
|
function resolverFilePath(basename) {
|
|
25030
|
-
return
|
|
25221
|
+
return path9.join(MACOS_RESOLVER_DIR, basename);
|
|
25031
25222
|
}
|
|
25032
25223
|
function contentLooksLikeRpxResolver(content) {
|
|
25033
25224
|
return content.includes("127.0.0.1") && content.includes(String(DNS_PORT));
|
|
@@ -25212,13 +25403,13 @@ var init_dns = __esm(() => {
|
|
|
25212
25403
|
import { spawn as nodeSpawn } from "node:child_process";
|
|
25213
25404
|
import * as fsp7 from "node:fs/promises";
|
|
25214
25405
|
import { homedir as homedir12 } from "node:os";
|
|
25215
|
-
import * as
|
|
25406
|
+
import * as path10 from "node:path";
|
|
25216
25407
|
import * as process27 from "node:process";
|
|
25217
25408
|
function getDaemonRpxDir() {
|
|
25218
|
-
return
|
|
25409
|
+
return path10.join(homedir12(), ".stacks", "rpx");
|
|
25219
25410
|
}
|
|
25220
25411
|
function getDaemonPidPath(rpxDir = getDaemonRpxDir()) {
|
|
25221
|
-
return
|
|
25412
|
+
return path10.join(rpxDir, "daemon.pid");
|
|
25222
25413
|
}
|
|
25223
25414
|
async function readDaemonPid(rpxDir = getDaemonRpxDir()) {
|
|
25224
25415
|
try {
|
|
@@ -25238,7 +25429,7 @@ async function releaseDaemonLock(rpxDir = getDaemonRpxDir()) {
|
|
|
25238
25429
|
}
|
|
25239
25430
|
function defaultDaemonSpawnCommand() {
|
|
25240
25431
|
const exec = process27.execPath;
|
|
25241
|
-
const interpName =
|
|
25432
|
+
const interpName = path10.basename(exec).toLowerCase();
|
|
25242
25433
|
const isInterpreter = interpName === "bun" || interpName === "node" || interpName.startsWith("bun-");
|
|
25243
25434
|
if (isInterpreter && process27.argv[1])
|
|
25244
25435
|
return [exec, process27.argv[1], "daemon:start"];
|
|
@@ -25292,10 +25483,12 @@ async function ensureDaemonRunning(opts = {}) {
|
|
|
25292
25483
|
throw spawnError;
|
|
25293
25484
|
throw new Error(`rpx daemon failed to start within ${timeoutMs}ms (rpxDir=${rpxDir})`);
|
|
25294
25485
|
}
|
|
25486
|
+
var registryUpstreamPools;
|
|
25295
25487
|
var init_daemon = __esm(() => {
|
|
25296
25488
|
init_logger();
|
|
25297
25489
|
init_https();
|
|
25298
25490
|
init_proxy_handler();
|
|
25491
|
+
init_acme_challenge();
|
|
25299
25492
|
init_host_routes();
|
|
25300
25493
|
init_sni();
|
|
25301
25494
|
init_on_demand();
|
|
@@ -25306,6 +25499,7 @@ var init_daemon = __esm(() => {
|
|
|
25306
25499
|
init_registry();
|
|
25307
25500
|
init_dns();
|
|
25308
25501
|
init_utils();
|
|
25502
|
+
registryUpstreamPools = new Map;
|
|
25309
25503
|
});
|
|
25310
25504
|
|
|
25311
25505
|
// src/index.ts
|
|
@@ -25337,8 +25531,8 @@ init_daemon();
|
|
|
25337
25531
|
init_logger();
|
|
25338
25532
|
init_registry();
|
|
25339
25533
|
init_utils();
|
|
25340
|
-
import * as
|
|
25341
|
-
import * as
|
|
25534
|
+
import * as fs4 from "node:fs";
|
|
25535
|
+
import * as path11 from "node:path";
|
|
25342
25536
|
import * as process28 from "node:process";
|
|
25343
25537
|
function deriveIdFromTarget(to, routePath) {
|
|
25344
25538
|
const base = routePath && routePath !== "/" ? `${to}${routePath}` : to;
|
|
@@ -25373,7 +25567,8 @@ async function runViaDaemon(opts) {
|
|
|
25373
25567
|
cleanUrls: p2.cleanUrls,
|
|
25374
25568
|
changeOrigin: p2.changeOrigin,
|
|
25375
25569
|
pathRewrites: p2.pathRewrites,
|
|
25376
|
-
static: p2.static
|
|
25570
|
+
static: p2.static,
|
|
25571
|
+
loadBalancer: p2.loadBalancer
|
|
25377
25572
|
}, registryDir, verbose);
|
|
25378
25573
|
}
|
|
25379
25574
|
const result = await ensureDaemonRunning({
|
|
@@ -25414,7 +25609,7 @@ async function runViaDaemon(opts) {
|
|
|
25414
25609
|
return;
|
|
25415
25610
|
for (const id of idsForCleanup) {
|
|
25416
25611
|
try {
|
|
25417
|
-
|
|
25612
|
+
fs4.unlinkSync(path11.join(dirForCleanup, `${id}.json`));
|
|
25418
25613
|
} catch {}
|
|
25419
25614
|
}
|
|
25420
25615
|
});
|
|
@@ -25424,9 +25619,9 @@ async function runViaDaemon(opts) {
|
|
|
25424
25619
|
// ../rpx/src/hosts.ts
|
|
25425
25620
|
init_utils();
|
|
25426
25621
|
import { exec } from "node:child_process";
|
|
25427
|
-
import
|
|
25622
|
+
import fs5 from "node:fs";
|
|
25428
25623
|
import os2 from "node:os";
|
|
25429
|
-
import
|
|
25624
|
+
import path12 from "node:path";
|
|
25430
25625
|
import * as process29 from "node:process";
|
|
25431
25626
|
import { promisify } from "node:util";
|
|
25432
25627
|
var execAsync = promisify(exec);
|
|
@@ -25434,7 +25629,7 @@ function isLoopbackDevelopmentHost(host) {
|
|
|
25434
25629
|
const normalized = host.trim().toLowerCase();
|
|
25435
25630
|
return normalized === "localhost" || normalized.endsWith(".localhost") || normalized.endsWith(".localhost.");
|
|
25436
25631
|
}
|
|
25437
|
-
var hostsFilePath = process29.platform === "win32" ?
|
|
25632
|
+
var hostsFilePath = process29.platform === "win32" ? path12.join(process29.env.windir || "C:\\Windows", "System32", "drivers", "etc", "hosts") : "/etc/hosts";
|
|
25438
25633
|
var sudoPrivilegesAcquired = false;
|
|
25439
25634
|
async function execSudo(command) {
|
|
25440
25635
|
if (process29.platform === "win32")
|
|
@@ -25483,7 +25678,7 @@ async function addHosts(hosts, verbose) {
|
|
|
25483
25678
|
try {
|
|
25484
25679
|
let existingContent;
|
|
25485
25680
|
try {
|
|
25486
|
-
existingContent = await
|
|
25681
|
+
existingContent = await fs5.promises.readFile(hostsFilePath, "utf-8");
|
|
25487
25682
|
} catch {
|
|
25488
25683
|
debugLog("hosts", "Reading hosts file requires elevated permissions, using sudo", verbose);
|
|
25489
25684
|
try {
|
|
@@ -25508,9 +25703,9 @@ async function addHosts(hosts, verbose) {
|
|
|
25508
25703
|
127.0.0.1 ${host}
|
|
25509
25704
|
::1 ${host}`).join(`
|
|
25510
25705
|
`);
|
|
25511
|
-
const tmpFile =
|
|
25706
|
+
const tmpFile = path12.join(os2.tmpdir(), `rpx-hosts-${Date.now()}.tmp`);
|
|
25512
25707
|
try {
|
|
25513
|
-
await
|
|
25708
|
+
await fs5.promises.writeFile(tmpFile, existingContent + hostEntries, "utf8");
|
|
25514
25709
|
await execSudo(`cat "${tmpFile}" | tee "${hostsFilePath}" > /dev/null`);
|
|
25515
25710
|
console.log(` Hosts updated: ${newEntries.join(", ")}`);
|
|
25516
25711
|
} catch (error) {
|
|
@@ -25523,7 +25718,7 @@ async function addHosts(hosts, verbose) {
|
|
|
25523
25718
|
console.log(` Or run: sudo nano ${hostsFilePath}`);
|
|
25524
25719
|
} finally {
|
|
25525
25720
|
try {
|
|
25526
|
-
await
|
|
25721
|
+
await fs5.promises.unlink(tmpFile);
|
|
25527
25722
|
} catch {}
|
|
25528
25723
|
}
|
|
25529
25724
|
} catch (err) {
|
|
@@ -25536,7 +25731,7 @@ async function removeHosts(hosts, verbose) {
|
|
|
25536
25731
|
try {
|
|
25537
25732
|
let content;
|
|
25538
25733
|
try {
|
|
25539
|
-
content = await
|
|
25734
|
+
content = await fs5.promises.readFile(hostsFilePath, "utf-8");
|
|
25540
25735
|
} catch {
|
|
25541
25736
|
debugLog("hosts", "Reading hosts file requires elevated permissions, using sudo", verbose);
|
|
25542
25737
|
try {
|
|
@@ -25570,16 +25765,16 @@ async function removeHosts(hosts, verbose) {
|
|
|
25570
25765
|
const newContent = `${filteredLines.join(`
|
|
25571
25766
|
`)}
|
|
25572
25767
|
`;
|
|
25573
|
-
const tmpFile =
|
|
25768
|
+
const tmpFile = path12.join(os2.tmpdir(), `rpx-hosts-${Date.now()}.tmp`);
|
|
25574
25769
|
try {
|
|
25575
|
-
await
|
|
25770
|
+
await fs5.promises.writeFile(tmpFile, newContent, "utf8");
|
|
25576
25771
|
await execSudo(`cat "${tmpFile}" | tee "${hostsFilePath}" > /dev/null`);
|
|
25577
25772
|
debugLog("hosts", "Hosts removed successfully", verbose);
|
|
25578
25773
|
} catch (error) {
|
|
25579
25774
|
debugLog("hosts", "Could not clean up hosts file automatically", verbose);
|
|
25580
25775
|
} finally {
|
|
25581
25776
|
try {
|
|
25582
|
-
await
|
|
25777
|
+
await fs5.promises.unlink(tmpFile);
|
|
25583
25778
|
} catch (unlinkErr) {
|
|
25584
25779
|
debugLog("hosts", `Failed to remove temporary file: ${unlinkErr}`, verbose);
|
|
25585
25780
|
}
|
|
@@ -25592,7 +25787,7 @@ async function checkHosts(hosts, verbose) {
|
|
|
25592
25787
|
debugLog("hosts", `Checking hosts: ${hosts}`, verbose);
|
|
25593
25788
|
let content;
|
|
25594
25789
|
try {
|
|
25595
|
-
content = await
|
|
25790
|
+
content = await fs5.promises.readFile(hostsFilePath, "utf-8");
|
|
25596
25791
|
} catch (readErr) {
|
|
25597
25792
|
debugLog("hosts", `Error reading hosts file: ${readErr}`, verbose);
|
|
25598
25793
|
try {
|
|
@@ -25805,25 +26000,7 @@ function createOriginGuard(options) {
|
|
|
25805
26000
|
|
|
25806
26001
|
// ../rpx/src/start.ts
|
|
25807
26002
|
init_proxy_handler();
|
|
25808
|
-
|
|
25809
|
-
// ../rpx/src/acme-challenge.ts
|
|
25810
|
-
import * as fs5 from "node:fs";
|
|
25811
|
-
import * as path12 from "node:path";
|
|
25812
|
-
var ACME_CHALLENGE_PREFIX2 = "/.well-known/acme-challenge/";
|
|
25813
|
-
function readAcmeChallenge(webroot, pathname) {
|
|
25814
|
-
if (!webroot || !pathname.startsWith(ACME_CHALLENGE_PREFIX2))
|
|
25815
|
-
return null;
|
|
25816
|
-
const token = pathname.slice(ACME_CHALLENGE_PREFIX2.length);
|
|
25817
|
-
if (!token || !/^[A-Za-z0-9_-]+$/.test(token))
|
|
25818
|
-
return null;
|
|
25819
|
-
try {
|
|
25820
|
-
return fs5.readFileSync(path12.join(webroot, token), "utf8");
|
|
25821
|
-
} catch {
|
|
25822
|
-
return null;
|
|
25823
|
-
}
|
|
25824
|
-
}
|
|
25825
|
-
|
|
25826
|
-
// ../rpx/src/start.ts
|
|
26003
|
+
init_acme_challenge();
|
|
25827
26004
|
init_auth();
|
|
25828
26005
|
init_host_routes();
|
|
25829
26006
|
init_sni();
|
|
@@ -25833,6 +26010,7 @@ var processManager2 = new ProcessManager;
|
|
|
25833
26010
|
var version3 = "0.12.0";
|
|
25834
26011
|
var globalPortManager = new DefaultPortManager("0.0.0.0");
|
|
25835
26012
|
var activeServers = new Set;
|
|
26013
|
+
var activeUpstreamPools = new Set;
|
|
25836
26014
|
var isCleaningUp = false;
|
|
25837
26015
|
var cleanupPromiseResolve = null;
|
|
25838
26016
|
var cleanupPromise = null;
|
|
@@ -25872,6 +26050,9 @@ async function cleanup(options) {
|
|
|
25872
26050
|
}));
|
|
25873
26051
|
cleanupPromises.push(...serverClosePromises);
|
|
25874
26052
|
activeServers.clear();
|
|
26053
|
+
for (const pool of activeUpstreamPools)
|
|
26054
|
+
stopHealthChecks(pool);
|
|
26055
|
+
activeUpstreamPools.clear();
|
|
25875
26056
|
if (options?.hosts && options.domains?.length) {
|
|
25876
26057
|
debugLog("cleanup", "Cleaning up hosts file entries", options?.verbose);
|
|
25877
26058
|
debugLog("cleanup", `Original domains for cleanup: ${JSON.stringify(options.domains)}`, options?.verbose);
|
|
@@ -26029,7 +26210,8 @@ async function testConnection(hostname, port, verbose, retries = 5) {
|
|
|
26029
26210
|
}
|
|
26030
26211
|
async function startServer(options) {
|
|
26031
26212
|
debugLog("server", `Starting server with options: ${safeStringify(options)}`, options.verbose);
|
|
26032
|
-
const
|
|
26213
|
+
const primaryFrom = primaryUpstreamUrl(options.from);
|
|
26214
|
+
const fromUrl = new URL(primaryFrom.startsWith("http") ? primaryFrom : `http://${primaryFrom}`);
|
|
26033
26215
|
const toUrl = new URL((options.to?.startsWith("http") ? options.to : `http://${options.to}`) || "rpx.localhost");
|
|
26034
26216
|
const fromPort = Number.parseInt(fromUrl.port) || (fromUrl.protocol.includes("https:") ? 443 : 80);
|
|
26035
26217
|
const hostsToCheck = [toUrl.hostname];
|
|
@@ -26110,7 +26292,8 @@ async function startServer(options) {
|
|
|
26110
26292
|
debugLog("server", `Setting up reverse proxy with SSL config for ${toUrl.hostname}`, options.verbose);
|
|
26111
26293
|
await setupProxy({
|
|
26112
26294
|
...options,
|
|
26113
|
-
from:
|
|
26295
|
+
from: primaryFrom,
|
|
26296
|
+
originalFrom: options.from || primaryFrom,
|
|
26114
26297
|
to: toUrl.hostname,
|
|
26115
26298
|
fromPort,
|
|
26116
26299
|
sourceUrl: {
|
|
@@ -26120,12 +26303,15 @@ async function startServer(options) {
|
|
|
26120
26303
|
ssl: sslConfig
|
|
26121
26304
|
});
|
|
26122
26305
|
}
|
|
26123
|
-
async function createProxyServer(from, to, listenPort, sourceUrl, ssl, vitePluginUsage, verbose, cleanUrls, changeOrigin, auth) {
|
|
26306
|
+
async function createProxyServer(from, to, listenPort, sourceUrl, ssl, vitePluginUsage, verbose, cleanUrls, changeOrigin, auth, originalFrom, loadBalancer) {
|
|
26124
26307
|
debugLog("proxy", `Creating proxy server ${from} -> ${to} with cleanUrls: ${cleanUrls}`, verbose);
|
|
26308
|
+
const pool = createUpstreamPool(originalFrom ?? sourceUrl.host, loadBalancer);
|
|
26309
|
+
startHealthChecks(pool);
|
|
26125
26310
|
const routeEntries = [{
|
|
26126
26311
|
host: to,
|
|
26127
26312
|
route: {
|
|
26128
26313
|
sourceHost: sourceUrl.host,
|
|
26314
|
+
upstreamPool: pool,
|
|
26129
26315
|
cleanUrls: cleanUrls || false,
|
|
26130
26316
|
changeOrigin: changeOrigin || false,
|
|
26131
26317
|
basePath: "/",
|
|
@@ -26133,8 +26319,11 @@ async function createProxyServer(from, to, listenPort, sourceUrl, ssl, vitePlugi
|
|
|
26133
26319
|
}
|
|
26134
26320
|
}];
|
|
26135
26321
|
const server = createSharedProxyServer({ routeEntries, listenPort, sslConfig: ssl, originGuard: null, verbose: verbose ?? false });
|
|
26136
|
-
if (!server)
|
|
26322
|
+
if (!server) {
|
|
26323
|
+
stopHealthChecks(pool);
|
|
26137
26324
|
throw new Error(`Failed to start proxy server for ${to} on port ${listenPort}`);
|
|
26325
|
+
}
|
|
26326
|
+
activeUpstreamPools.add(pool);
|
|
26138
26327
|
logToConsole({
|
|
26139
26328
|
from,
|
|
26140
26329
|
to,
|
|
@@ -26147,7 +26336,7 @@ async function createProxyServer(from, to, listenPort, sourceUrl, ssl, vitePlugi
|
|
|
26147
26336
|
}
|
|
26148
26337
|
async function setupProxy(options) {
|
|
26149
26338
|
debugLog("setup", `Setting up reverse proxy: ${safeStringify(options)}`, options.verbose);
|
|
26150
|
-
const { from, to, sourceUrl, ssl, verbose, cleanup: cleanupOptions, vitePluginUsage, changeOrigin, cleanUrls } = options;
|
|
26339
|
+
const { from, originalFrom, to, sourceUrl, ssl, verbose, cleanup: cleanupOptions, vitePluginUsage, changeOrigin, cleanUrls } = options;
|
|
26151
26340
|
const httpPort = 80;
|
|
26152
26341
|
const httpsPort = 443;
|
|
26153
26342
|
const hostname = "0.0.0.0";
|
|
@@ -26214,7 +26403,7 @@ async function setupProxy(options) {
|
|
|
26214
26403
|
portManager2.usedPorts.add(finalPort);
|
|
26215
26404
|
debugLog("setup", `Using standard ${targetPort === 443 ? "HTTPS" : "HTTP"} port ${targetPort} for ${to}`, verbose);
|
|
26216
26405
|
}
|
|
26217
|
-
await createProxyServer(from, to, finalPort, sourceUrl, ssl, vitePluginUsage, verbose, cleanUrls, changeOrigin, resolveAuth(options.auth));
|
|
26406
|
+
await createProxyServer(from, to, finalPort, sourceUrl, ssl, vitePluginUsage, verbose, cleanUrls, changeOrigin, resolveAuth(options.auth), originalFrom, options.loadBalancer);
|
|
26218
26407
|
} catch (err) {
|
|
26219
26408
|
debugLog("setup", `Setup failed: ${err}`, verbose);
|
|
26220
26409
|
log.error(`Failed to setup reverse proxy: ${err.message}`);
|
|
@@ -26322,7 +26511,8 @@ async function startProxies(options) {
|
|
|
26322
26511
|
debugLog("watch", `Starting command for ${proxyId} with command: ${proxy.start.command}`, verbose);
|
|
26323
26512
|
log.info(`Starting command for ${proxyId}...`);
|
|
26324
26513
|
await processManager2.startProcess(proxyId, proxy.start, verbose);
|
|
26325
|
-
const
|
|
26514
|
+
const proxyPrimaryFrom = primaryUpstreamUrl(proxy.from);
|
|
26515
|
+
const fromUrl = new URL(proxyPrimaryFrom.startsWith("http") ? proxyPrimaryFrom : `http://${proxyPrimaryFrom}`);
|
|
26326
26516
|
const hostname = fromUrl.hostname || "localhost";
|
|
26327
26517
|
const port = Number(fromUrl.port) || 80;
|
|
26328
26518
|
try {
|
|
@@ -26348,7 +26538,8 @@ async function startProxies(options) {
|
|
|
26348
26538
|
debugLog("watch", `Starting command: ${mergedOptions.start.command}`, verbose);
|
|
26349
26539
|
await processManager2.startProcess(proxyId, mergedOptions.start, verbose);
|
|
26350
26540
|
}
|
|
26351
|
-
const
|
|
26541
|
+
const mergedPrimaryFrom = primaryUpstreamUrl(mergedOptions.from);
|
|
26542
|
+
const fromUrl = new URL(mergedPrimaryFrom.startsWith("http") ? mergedPrimaryFrom : `http://${mergedPrimaryFrom}`);
|
|
26352
26543
|
const hostname = fromUrl.hostname || "localhost";
|
|
26353
26544
|
const port = Number(fromUrl.port) || 80;
|
|
26354
26545
|
try {
|
|
@@ -26558,12 +26749,17 @@ async function collectRouteEntries(proxyOptions, hostsEnabled, verbose) {
|
|
|
26558
26749
|
});
|
|
26559
26750
|
debugLog("proxies", `Route: ${domain}${routePath ?? ""} → static ${typeof option.static === "string" ? option.static : option.static.dir}${auth ? " (auth)" : ""}`, verbose);
|
|
26560
26751
|
} else {
|
|
26561
|
-
const
|
|
26752
|
+
const primaryFrom = primaryUpstreamUrl(option.from);
|
|
26753
|
+
const fromUrl = new URL(primaryFrom.startsWith("http") ? primaryFrom : `http://${primaryFrom}`);
|
|
26754
|
+
const pool = createUpstreamPool(option.from ?? fromUrl.host, option.loadBalancer);
|
|
26755
|
+
startHealthChecks(pool);
|
|
26756
|
+
activeUpstreamPools.add(pool);
|
|
26562
26757
|
routeEntries.push({
|
|
26563
26758
|
host: domain,
|
|
26564
26759
|
path: routePath,
|
|
26565
26760
|
route: {
|
|
26566
26761
|
sourceHost: fromUrl.host,
|
|
26762
|
+
upstreamPool: pool,
|
|
26567
26763
|
cleanUrls,
|
|
26568
26764
|
changeOrigin: option.changeOrigin || false,
|
|
26569
26765
|
pathRewrites: option.pathRewrites,
|
|
@@ -26655,6 +26851,7 @@ init_dns();
|
|
|
26655
26851
|
init_dns_state();
|
|
26656
26852
|
init_daemon();
|
|
26657
26853
|
init_proxy_handler();
|
|
26854
|
+
init_acme_challenge();
|
|
26658
26855
|
init_auth();
|
|
26659
26856
|
init_host_routes();
|
|
26660
26857
|
init_static_files();
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vite-plugin-rpx",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.11.
|
|
4
|
+
"version": "0.11.24",
|
|
5
5
|
"description": "A modern and smart reverse proxy. Vite plugin.",
|
|
6
6
|
"author": "Chris Breuer <chris@stacksjs.org>",
|
|
7
7
|
"license": "MIT",
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
"typecheck": "bunx tsc --noEmit"
|
|
48
48
|
},
|
|
49
49
|
"dependencies": {
|
|
50
|
-
"@stacksjs/rpx": "0.11.
|
|
50
|
+
"@stacksjs/rpx": "0.11.24",
|
|
51
51
|
"@stacksjs/tlsx": "^0.13.9"
|
|
52
52
|
},
|
|
53
53
|
"simple-git-hooks": {
|