@maintainer-pro/ai-bridge 0.1.19 → 0.1.21
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/package.json +2 -2
- package/src/daemon.mjs +57 -50
- package/src/share-rewrite.mjs +52 -27
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@maintainer-pro/ai-bridge",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.21",
|
|
4
4
|
"description": "Local bridge daemon that pairs a machine to Maintainer Pro and configures multiple client sandboxes.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"maintainer-pro",
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"node": ">=22"
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@maintainer-pro/ai-cli": "^0.1.
|
|
31
|
+
"@maintainer-pro/ai-cli": "^0.1.12",
|
|
32
32
|
"@maintainer-pro/ai-server": "^0.1.7"
|
|
33
33
|
}
|
|
34
34
|
}
|
package/src/daemon.mjs
CHANGED
|
@@ -257,7 +257,21 @@ function loadConfig() {
|
|
|
257
257
|
const file = configPath();
|
|
258
258
|
if (!fs.existsSync(file)) return null;
|
|
259
259
|
try {
|
|
260
|
-
|
|
260
|
+
const cfg = JSON.parse(fs.readFileSync(file, "utf8"));
|
|
261
|
+
let dirty = false;
|
|
262
|
+
for (const ws of cfg.workspaces || []) {
|
|
263
|
+
const before = JSON.stringify(ws.hostApps || []);
|
|
264
|
+
const beforeProxy = JSON.stringify(ws.proxy || null);
|
|
265
|
+
stripAiServerFromWorkspace(ws);
|
|
266
|
+
if (
|
|
267
|
+
JSON.stringify(ws.hostApps || []) !== before ||
|
|
268
|
+
JSON.stringify(ws.proxy || null) !== beforeProxy
|
|
269
|
+
) {
|
|
270
|
+
dirty = true;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
if (dirty) saveConfig(cfg);
|
|
274
|
+
return cfg;
|
|
261
275
|
} catch {
|
|
262
276
|
return null;
|
|
263
277
|
}
|
|
@@ -434,7 +448,7 @@ async function resolveWorkspaceHostApps(ws, opts = {}) {
|
|
|
434
448
|
const match = previous.find((row) => row && row.id === app.id);
|
|
435
449
|
return match ? { ...app, host: match.host === true || app.host === true } : app;
|
|
436
450
|
});
|
|
437
|
-
ws.hostApps = result.apps;
|
|
451
|
+
ws.hostApps = listedHostApps(result.apps);
|
|
438
452
|
if (opts.cfg) persistWorkspaceEntry(opts.cfg, ws);
|
|
439
453
|
const summary = result.apps
|
|
440
454
|
.map((app) => `${app.name}:${app.port}`)
|
|
@@ -455,19 +469,10 @@ async function resolveWorkspaceHostApps(ws, opts = {}) {
|
|
|
455
469
|
activity(
|
|
456
470
|
ws.sandboxId,
|
|
457
471
|
"warn",
|
|
458
|
-
`port detect failed (${message}) —
|
|
472
|
+
`port detect failed (${message}) — no host apps listed yet`
|
|
459
473
|
);
|
|
460
474
|
if (!Array.isArray(ws.hostApps) || !ws.hostApps.length) {
|
|
461
|
-
ws.hostApps = [
|
|
462
|
-
{
|
|
463
|
-
id: "ai-server",
|
|
464
|
-
name: "AI server",
|
|
465
|
-
role: "ai-server",
|
|
466
|
-
port: Number(ws.port) || 3100,
|
|
467
|
-
source: "default",
|
|
468
|
-
locked: true,
|
|
469
|
-
},
|
|
470
|
-
];
|
|
475
|
+
ws.hostApps = [];
|
|
471
476
|
}
|
|
472
477
|
return {
|
|
473
478
|
apps: ws.hostApps,
|
|
@@ -763,8 +768,31 @@ function isLocalAppUrl(url) {
|
|
|
763
768
|
}
|
|
764
769
|
}
|
|
765
770
|
|
|
771
|
+
function isAiServerApp(app) {
|
|
772
|
+
return Boolean(app && (app.role === "ai-server" || app.id === "ai-server"));
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
function listedHostApps(apps) {
|
|
776
|
+
return (Array.isArray(apps) ? apps : []).filter((app) => !isAiServerApp(app));
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
function stripAiServerFromWorkspace(ws) {
|
|
780
|
+
if (!ws || typeof ws !== "object") return ws;
|
|
781
|
+
if (Array.isArray(ws.hostApps)) ws.hostApps = listedHostApps(ws.hostApps);
|
|
782
|
+
if (ws.proxy && typeof ws.proxy === "object") {
|
|
783
|
+
if (ws.proxy.slugs && typeof ws.proxy.slugs === "object") {
|
|
784
|
+
delete ws.proxy.slugs["ai-server"];
|
|
785
|
+
}
|
|
786
|
+
if (ws.proxy.urls && typeof ws.proxy.urls === "object") {
|
|
787
|
+
delete ws.proxy.urls["ai-server"];
|
|
788
|
+
}
|
|
789
|
+
}
|
|
790
|
+
return ws;
|
|
791
|
+
}
|
|
792
|
+
|
|
766
793
|
function persistWorkspaceEntry(cfg, ws) {
|
|
767
794
|
if (!cfg || !ws?.sandboxId) return;
|
|
795
|
+
stripAiServerFromWorkspace(ws);
|
|
768
796
|
cfg.workspaces = cfg.workspaces || [];
|
|
769
797
|
const index = cfg.workspaces.findIndex((row) => row.sandboxId === ws.sandboxId);
|
|
770
798
|
if (index >= 0) cfg.workspaces[index] = { ...cfg.workspaces[index], ...ws };
|
|
@@ -1001,16 +1029,7 @@ function probeEmbedConfig(url, timeoutMs = 2500) {
|
|
|
1001
1029
|
|
|
1002
1030
|
function sanitizeAiServerPort(ws) {
|
|
1003
1031
|
if (!ws || typeof ws !== "object") return;
|
|
1004
|
-
|
|
1005
|
-
for (const app of apps) {
|
|
1006
|
-
if (
|
|
1007
|
-
app &&
|
|
1008
|
-
(app.role === "ai-server" || app.id === "ai-server") &&
|
|
1009
|
-
isAdminListenPort(app.port)
|
|
1010
|
-
) {
|
|
1011
|
-
app.port = 3100;
|
|
1012
|
-
}
|
|
1013
|
-
}
|
|
1032
|
+
if (Array.isArray(ws.hostApps)) ws.hostApps = listedHostApps(ws.hostApps);
|
|
1014
1033
|
if (isAdminListenPort(ws.port)) ws.port = 3100;
|
|
1015
1034
|
}
|
|
1016
1035
|
|
|
@@ -1304,10 +1323,6 @@ async function reconcileWorkspacePresence(ws, cfg, opts = {}) {
|
|
|
1304
1323
|
// 3. Host + CORS origins for Maintainer Pro
|
|
1305
1324
|
const host = workspaceHostReport(ws);
|
|
1306
1325
|
const uiShare = proxyUrlForApp(ws, hostAppOf(ws) || { id: "ui", role: "ui", host: true });
|
|
1307
|
-
const aiShare = proxyUrlForApp(ws, {
|
|
1308
|
-
id: "ai-server",
|
|
1309
|
-
role: "ai-server",
|
|
1310
|
-
});
|
|
1311
1326
|
if (uiShare) {
|
|
1312
1327
|
host.appUrl = uiShare;
|
|
1313
1328
|
} else if (probe.running) {
|
|
@@ -1316,12 +1331,9 @@ async function reconcileWorkspacePresence(ws, cfg, opts = {}) {
|
|
|
1316
1331
|
);
|
|
1317
1332
|
if (ui?.port) {
|
|
1318
1333
|
host.appUrl = `http://localhost:${ui.port}`;
|
|
1319
|
-
} else if (probe.chatUp) {
|
|
1320
|
-
host.appUrl = `http://localhost:${probe.chatPort}`;
|
|
1321
1334
|
}
|
|
1322
1335
|
}
|
|
1323
1336
|
if (uiShare && !host.origins.includes(uiShare)) host.origins.push(uiShare);
|
|
1324
|
-
if (aiShare && !host.origins.includes(aiShare)) host.origins.push(aiShare);
|
|
1325
1337
|
const proxyOrigin = String(ws?.proxy?.origin || "").replace(/\/$/, "");
|
|
1326
1338
|
if (proxyOrigin && !host.origins.includes(proxyOrigin)) {
|
|
1327
1339
|
host.origins.push(proxyOrigin);
|
|
@@ -1491,7 +1503,7 @@ function uniqueProxySlugs(apps) {
|
|
|
1491
1503
|
const used = new Set();
|
|
1492
1504
|
/** @type {Record<string, string>} */
|
|
1493
1505
|
const slugs = {};
|
|
1494
|
-
for (const app of apps
|
|
1506
|
+
for (const app of listedHostApps(apps)) {
|
|
1495
1507
|
let slug = proxySlugForApp(app);
|
|
1496
1508
|
if (!slug || !app?.id) continue;
|
|
1497
1509
|
if (used.has(slug)) {
|
|
@@ -1512,7 +1524,7 @@ function uniqueProxySlugs(apps) {
|
|
|
1512
1524
|
}
|
|
1513
1525
|
|
|
1514
1526
|
function sharePortUrls(ws) {
|
|
1515
|
-
const apps =
|
|
1527
|
+
const apps = listedHostApps(ws?.hostApps);
|
|
1516
1528
|
/** @type {Record<string, string>} */
|
|
1517
1529
|
const out = {};
|
|
1518
1530
|
for (const app of apps) {
|
|
@@ -1547,8 +1559,10 @@ function applyAssignedProxy(ws, remote, cfg) {
|
|
|
1547
1559
|
}
|
|
1548
1560
|
|
|
1549
1561
|
function appsFrom(ws, remote) {
|
|
1550
|
-
if (Array.isArray(ws?.hostApps) && ws.hostApps.length)
|
|
1551
|
-
|
|
1562
|
+
if (Array.isArray(ws?.hostApps) && ws.hostApps.length) {
|
|
1563
|
+
return listedHostApps(ws.hostApps);
|
|
1564
|
+
}
|
|
1565
|
+
if (Array.isArray(remote?.hostApps)) return listedHostApps(remote.hostApps);
|
|
1552
1566
|
return [];
|
|
1553
1567
|
}
|
|
1554
1568
|
|
|
@@ -1569,10 +1583,9 @@ function proxyUrlForApp(ws, app) {
|
|
|
1569
1583
|
}
|
|
1570
1584
|
|
|
1571
1585
|
function jobsFromHostApps(ws, filter = {}) {
|
|
1572
|
-
const apps =
|
|
1586
|
+
const apps = listedHostApps(ws.hostApps);
|
|
1573
1587
|
const hostId = hostAppOf(ws)?.id;
|
|
1574
1588
|
return apps
|
|
1575
|
-
.filter((app) => app && app.role !== "ai-server")
|
|
1576
1589
|
.filter((app) => (filter.appId ? app.id === filter.appId : true))
|
|
1577
1590
|
.map((app) => {
|
|
1578
1591
|
const port = Number(app.port) || 3000;
|
|
@@ -1622,7 +1635,7 @@ async function probeRunningApps(ws, timeoutMs = 2500) {
|
|
|
1622
1635
|
appId: job.appId || job.role,
|
|
1623
1636
|
});
|
|
1624
1637
|
}
|
|
1625
|
-
const listed =
|
|
1638
|
+
const listed = listedHostApps(ws.hostApps);
|
|
1626
1639
|
const hostApps = await Promise.all(
|
|
1627
1640
|
listed.map(async (app) => {
|
|
1628
1641
|
const port = Number(app.port) || 0;
|
|
@@ -1645,7 +1658,7 @@ async function probeRunningApps(ws, timeoutMs = 2500) {
|
|
|
1645
1658
|
chatPort: chat.port,
|
|
1646
1659
|
hosts,
|
|
1647
1660
|
hostApps,
|
|
1648
|
-
running:
|
|
1661
|
+
running: hosts.some((host) => host.up) || hostApps.some((app) => app.running),
|
|
1649
1662
|
};
|
|
1650
1663
|
}
|
|
1651
1664
|
|
|
@@ -1662,9 +1675,7 @@ async function restoreHostsAfterReconnect(cfg) {
|
|
|
1662
1675
|
.join(" ");
|
|
1663
1676
|
if (status.appsRunning) {
|
|
1664
1677
|
log(
|
|
1665
|
-
`found running apps for ${label}:
|
|
1666
|
-
status.probe.chatUp ? "(up)" : "(down)"
|
|
1667
|
-
}${hostSummary ? ` ${hostSummary}` : ""} share=${
|
|
1678
|
+
`found running apps for ${label}: ${hostSummary || "(none)"} share=${
|
|
1668
1679
|
status.host.appUrl || "(none)"
|
|
1669
1680
|
} origins=${
|
|
1670
1681
|
status.host.origins.join(",") || "none"
|
|
@@ -1703,10 +1714,7 @@ async function prepareWorkspaceLaunch(ws, cfg, reserved) {
|
|
|
1703
1714
|
return { aiPort, jobs: [] };
|
|
1704
1715
|
}
|
|
1705
1716
|
log(`ports pick ${label} in ${folder}`);
|
|
1706
|
-
const
|
|
1707
|
-
? ws.hostApps.find((app) => app.role === "ai-server" || app.id === "ai-server")
|
|
1708
|
-
: null;
|
|
1709
|
-
const preferredRaw = Number(listedAi?.port || ws.port) || 3100;
|
|
1717
|
+
const preferredRaw = Number(ws.port) || 3100;
|
|
1710
1718
|
const preferredAi = isAdminListenPort(preferredRaw) ? 3100 : preferredRaw;
|
|
1711
1719
|
const aiUp = await isChatServerOnPort(preferredAi);
|
|
1712
1720
|
const aiPort = aiUp
|
|
@@ -4679,12 +4687,11 @@ async function runActions(cfg, actions) {
|
|
|
4679
4687
|
String(action.payload.folderPathRemaining || remaining[0] || ws.folderPath);
|
|
4680
4688
|
ws.folderPath = primary;
|
|
4681
4689
|
ws.extraFolders = remaining.filter((folder) => !sameFolder(folder, primary));
|
|
4682
|
-
ws.hostApps = (
|
|
4690
|
+
ws.hostApps = listedHostApps(
|
|
4691
|
+
Array.isArray(ws.hostApps) ? ws.hostApps : []
|
|
4692
|
+
).filter(
|
|
4683
4693
|
(app) =>
|
|
4684
|
-
!app ||
|
|
4685
|
-
app.role === "ai-server" ||
|
|
4686
|
-
!app.folderPath ||
|
|
4687
|
-
!sameFolder(app.folderPath, removed)
|
|
4694
|
+
!app.folderPath || !sameFolder(app.folderPath, removed)
|
|
4688
4695
|
);
|
|
4689
4696
|
persistWorkspaceEntry(cfg, ws);
|
|
4690
4697
|
result = {
|
package/src/share-rewrite.mjs
CHANGED
|
@@ -284,8 +284,8 @@ function isProbablyUtf8Text(buf) {
|
|
|
284
284
|
}
|
|
285
285
|
|
|
286
286
|
/**
|
|
287
|
-
* Replace app
|
|
288
|
-
*
|
|
287
|
+
* Replace loopback app origins only (`localhost:8080`, `127.0.0.1`, `::1`,
|
|
288
|
+
* `0.0.0.0`). Real hostnames and other base URLs are left unchanged.
|
|
289
289
|
*
|
|
290
290
|
* @param {string} text
|
|
291
291
|
* @param {Record<string, string> | null | undefined} portUrls
|
|
@@ -297,14 +297,7 @@ export function rewriteMappedLocalUrls(text, portUrls) {
|
|
|
297
297
|
.filter((port) => Number.isInteger(port) && port > 0 && port <= 65535)
|
|
298
298
|
.sort((a, b) => b - a);
|
|
299
299
|
if (!ports.length) return text;
|
|
300
|
-
const localHost =
|
|
301
|
-
"(?:localhost|127\\.0\\.0\\.1|\\[::1\\]|::1|0\\.0\\.0\\.0|" +
|
|
302
|
-
"10\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}|" +
|
|
303
|
-
"192\\.168\\.\\d{1,3}\\.\\d{1,3}|" +
|
|
304
|
-
"172\\.(?:1[6-9]|2\\d|3[01])\\.\\d{1,3}\\.\\d{1,3}|" +
|
|
305
|
-
"169\\.254\\.\\d{1,3}\\.\\d{1,3}|" +
|
|
306
|
-
"[A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?(?:\\.(?:local|lan|internal|home))?)";
|
|
307
|
-
const anyHost = "(?:[^\\s'\"\\\\/<>@:]+|\\[[0-9a-fA-F:]+\\])";
|
|
300
|
+
const localHost = "(?:localhost|127\\.0\\.0\\.1|\\[::1\\]|::1|0\\.0\\.0\\.0)";
|
|
308
301
|
let out = String(text);
|
|
309
302
|
for (let i = 0; i < ports.length; i++) {
|
|
310
303
|
const port = ports[i];
|
|
@@ -339,12 +332,6 @@ export function rewriteMappedLocalUrls(text, portUrls) {
|
|
|
339
332
|
out = out.replace(new RegExp("//" + localHost + ":" + port + tail, "gi"), function (m) {
|
|
340
333
|
return swap(m, dest.replace(/^https?:/i, ""));
|
|
341
334
|
});
|
|
342
|
-
out = out.replace(new RegExp("http://" + anyHost + ":" + port + tail, "gi"), function (m) {
|
|
343
|
-
return swap(m, dest);
|
|
344
|
-
});
|
|
345
|
-
out = out.replace(new RegExp("ws://" + anyHost + ":" + port + tail, "gi"), function (m) {
|
|
346
|
-
return swap(m, destWs);
|
|
347
|
-
});
|
|
348
335
|
out = out.replace(
|
|
349
336
|
new RegExp("(?<![\\w./])" + localHost + ":" + port + tail, "gi"),
|
|
350
337
|
function (m) {
|
|
@@ -360,7 +347,7 @@ export function rewriteMappedLocalUrls(text, portUrls) {
|
|
|
360
347
|
* @param {Record<string, string>} headers
|
|
361
348
|
* @param {Record<string, string> | null | undefined} portUrls
|
|
362
349
|
*/
|
|
363
|
-
export function rewriteShareRequestBody(body, headers, portUrls,
|
|
350
|
+
export function rewriteShareRequestBody(body, headers, portUrls, _publicBase) {
|
|
364
351
|
if (!body) return body;
|
|
365
352
|
const buf = Buffer.isBuffer(body) ? body : Buffer.from(body);
|
|
366
353
|
if (!buf.length) return buf;
|
|
@@ -370,7 +357,6 @@ export function rewriteShareRequestBody(body, headers, portUrls, publicBase) {
|
|
|
370
357
|
if (portUrls && Object.keys(portUrls).length) {
|
|
371
358
|
next = rewriteMappedLocalUrls(next, portUrls);
|
|
372
359
|
}
|
|
373
|
-
if (publicBase) next = rewriteShareOriginPaths(next, publicBase);
|
|
374
360
|
if (next === text) return buf;
|
|
375
361
|
return Buffer.from(next, "utf8");
|
|
376
362
|
}
|
|
@@ -452,9 +438,10 @@ export function prefixShareOriginUrl(value, publicBase) {
|
|
|
452
438
|
const basePort = base.port || (base.protocol === "https:" ? "443" : "80");
|
|
453
439
|
if (reqPort !== basePort) return value;
|
|
454
440
|
const path = u.pathname || "/";
|
|
441
|
+
if (path === "/" || path === "") return value;
|
|
455
442
|
if (path === prefix || path.indexOf(prefix + "/") === 0) return u.toString();
|
|
456
443
|
if (path.indexOf("/p/") === 0) return u.toString();
|
|
457
|
-
u.pathname =
|
|
444
|
+
u.pathname = prefix + path;
|
|
458
445
|
return u.toString();
|
|
459
446
|
} catch {
|
|
460
447
|
return value;
|
|
@@ -475,11 +462,11 @@ export function rewriteShareOriginPaths(text, publicBase) {
|
|
|
475
462
|
.replace(/\//g, "\\/")
|
|
476
463
|
.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
477
464
|
let out = String(text);
|
|
478
|
-
out = out.replace(new RegExp(originEsc + "(
|
|
465
|
+
out = out.replace(new RegExp(originEsc + "/(?!p/)[^\\s'\"<>\\\\]+", "gi"), function (matched) {
|
|
479
466
|
return prefixShareOriginUrl(matched, publicBase);
|
|
480
467
|
});
|
|
481
468
|
out = out.replace(
|
|
482
|
-
new RegExp(originSlashEsc + "(
|
|
469
|
+
new RegExp(originSlashEsc + "\\\\/(?!p/)[^\\s'\"<>]+", "gi"),
|
|
483
470
|
function (matched) {
|
|
484
471
|
const unescaped = matched.replace(/\\\//g, "/");
|
|
485
472
|
return prefixShareOriginUrl(unescaped, publicBase).replace(/\//g, "\\/");
|
|
@@ -821,12 +808,11 @@ function prefixRootPaths(body, publicBase, contentType = "") {
|
|
|
821
808
|
let out = body;
|
|
822
809
|
if (
|
|
823
810
|
html &&
|
|
811
|
+
isViteDocument(out) &&
|
|
824
812
|
/<head[\s>]/i.test(out) &&
|
|
825
|
-
!/<base\s/i.test(out)
|
|
826
|
-
!isNextDocument(out)
|
|
813
|
+
!/<base\s/i.test(out)
|
|
827
814
|
) {
|
|
828
|
-
const
|
|
829
|
-
const href = joinProxyAndViteBase(pathPrefix, viteBase);
|
|
815
|
+
const href = joinProxyAndViteBase(pathPrefix, inferViteBase(out));
|
|
830
816
|
out = out.replace(/<head([^>]*)>/i, `<head$1><base href="${href}">`);
|
|
831
817
|
}
|
|
832
818
|
if (html) {
|
|
@@ -883,6 +869,12 @@ function isScriptRequestPath(path) {
|
|
|
883
869
|
return /\.(?:m?js|cjs)$/.test(p);
|
|
884
870
|
}
|
|
885
871
|
|
|
872
|
+
function isScriptOrJsonBody(headers, path) {
|
|
873
|
+
const mime = contentMime(headerGet(headers, "content-type"));
|
|
874
|
+
if (/javascript|ecmascript|json/.test(mime)) return true;
|
|
875
|
+
return isScriptRequestPath(path);
|
|
876
|
+
}
|
|
877
|
+
|
|
886
878
|
function rewriteLocalSidecarUrls(html, aiPublicBase, uiPublicBase) {
|
|
887
879
|
const ai = String(aiPublicBase || "").replace(/\/$/, "");
|
|
888
880
|
const ui = String(uiPublicBase || "").replace(/\/$/, "");
|
|
@@ -980,6 +972,14 @@ function shareProxyShim(p, portMap, rewriteMappedLocalUrls) {
|
|
|
980
972
|
)
|
|
981
973
|
);
|
|
982
974
|
}
|
|
975
|
+
function loopback(h) {
|
|
976
|
+
h = String(h || "")
|
|
977
|
+
.replace(/^\[|\]$/g, "")
|
|
978
|
+
.toLowerCase();
|
|
979
|
+
return (
|
|
980
|
+
h === "localhost" || h === "127.0.0.1" || h === "::1" || h === "0.0.0.0"
|
|
981
|
+
);
|
|
982
|
+
}
|
|
983
983
|
function prefixPath(path) {
|
|
984
984
|
if (typeof path !== "string" || !path) return path;
|
|
985
985
|
if (path.charAt(0) === "/" && path.charAt(1) !== "/") {
|
|
@@ -1019,17 +1019,29 @@ function shareProxyShim(p, portMap, rewriteMappedLocalUrls) {
|
|
|
1019
1019
|
}
|
|
1020
1020
|
function addNav(v) {
|
|
1021
1021
|
if (typeof v !== "string" || !v) return v;
|
|
1022
|
-
|
|
1022
|
+
var mapped = mapLocal(v);
|
|
1023
|
+
if (mapped !== v) return mapped;
|
|
1023
1024
|
if (v.charAt(0) === "/" && v.charAt(1) !== "/") return prefixPath(v);
|
|
1024
1025
|
try {
|
|
1025
1026
|
var nav = new URL(v, location.href);
|
|
1027
|
+
if (!loopback(nav.hostname)) return v;
|
|
1026
1028
|
if (nav.origin !== location.origin) return v;
|
|
1029
|
+
if (nav.pathname === "/" || nav.pathname === "") return v;
|
|
1027
1030
|
nav.pathname = prefixPath(nav.pathname);
|
|
1028
1031
|
return nav.toString();
|
|
1029
1032
|
} catch (e) {}
|
|
1030
1033
|
return v;
|
|
1031
1034
|
}
|
|
1032
1035
|
function addNet(v) {
|
|
1036
|
+
if (typeof v !== "string" || !v) return v;
|
|
1037
|
+
var mapped = mapLocal(v);
|
|
1038
|
+
if (mapped !== v) return mapped;
|
|
1039
|
+
if (/^(https?:|wss?:)\/\//i.test(v)) {
|
|
1040
|
+
try {
|
|
1041
|
+
var u = new URL(v);
|
|
1042
|
+
if (!loopback(u.hostname)) return v;
|
|
1043
|
+
} catch (e) {}
|
|
1044
|
+
}
|
|
1033
1045
|
return addNav(v);
|
|
1034
1046
|
}
|
|
1035
1047
|
function mapSel(sel) {
|
|
@@ -1224,11 +1236,24 @@ function shareServiceWorkerMain(portMap, tokenRoot, rewriteMappedLocalUrls) {
|
|
|
1224
1236
|
} catch (e) {}
|
|
1225
1237
|
return "";
|
|
1226
1238
|
}
|
|
1239
|
+
function loopback(h) {
|
|
1240
|
+
h = String(h || "")
|
|
1241
|
+
.replace(/^\[|\]$/g, "")
|
|
1242
|
+
.toLowerCase();
|
|
1243
|
+
return (
|
|
1244
|
+
h === "localhost" || h === "127.0.0.1" || h === "::1" || h === "0.0.0.0"
|
|
1245
|
+
);
|
|
1246
|
+
}
|
|
1227
1247
|
function prefixWith(url, prefix) {
|
|
1228
1248
|
if (!prefix) return url;
|
|
1229
1249
|
try {
|
|
1250
|
+
if (/^(https?:|wss?:)\/\//i.test(url)) {
|
|
1251
|
+
var abs = new URL(url);
|
|
1252
|
+
if (!loopback(abs.hostname)) return url;
|
|
1253
|
+
}
|
|
1230
1254
|
var u = new URL(url, self.location.href);
|
|
1231
1255
|
if (u.origin !== self.location.origin) return url;
|
|
1256
|
+
if (u.pathname === "/" || u.pathname === "") return url;
|
|
1232
1257
|
if (u.pathname.indexOf("/p/") === 0) return url;
|
|
1233
1258
|
if (u.pathname === prefix || u.pathname.indexOf(prefix + "/") === 0) return url;
|
|
1234
1259
|
u.pathname = u.pathname === "/" ? prefix : prefix + u.pathname;
|
|
@@ -1402,7 +1427,7 @@ export function processShareHttpResponse(opts) {
|
|
|
1402
1427
|
mutated = true;
|
|
1403
1428
|
}
|
|
1404
1429
|
}
|
|
1405
|
-
if (publicBase && rewriteTextBody) {
|
|
1430
|
+
if (publicBase && rewriteTextBody && !isScriptOrJsonBody(headers, path)) {
|
|
1406
1431
|
const prefixed = rewriteShareOriginPaths(text, publicBase);
|
|
1407
1432
|
if (prefixed !== text) {
|
|
1408
1433
|
text = prefixed;
|