@maintainer-pro/ai-bridge 0.1.16 → 0.1.18
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 +382 -74
- package/src/share-rewrite.mjs +404 -40
package/src/share-rewrite.mjs
CHANGED
|
@@ -79,7 +79,8 @@ export function prepareShareHttpRequest(
|
|
|
79
79
|
headers,
|
|
80
80
|
publicBase,
|
|
81
81
|
acceptEncodingHint,
|
|
82
|
-
path
|
|
82
|
+
path,
|
|
83
|
+
portUrls
|
|
83
84
|
) {
|
|
84
85
|
const out = { ...headers };
|
|
85
86
|
const acceptEncoding = String(
|
|
@@ -116,6 +117,13 @@ export function prepareShareHttpRequest(
|
|
|
116
117
|
/* ignore */
|
|
117
118
|
}
|
|
118
119
|
}
|
|
120
|
+
if (portUrls && typeof portUrls === "object") {
|
|
121
|
+
for (const key of Object.keys(out)) {
|
|
122
|
+
const lower = key.toLowerCase();
|
|
123
|
+
if (lower === "host" || lower === "content-length") continue;
|
|
124
|
+
out[key] = rewriteMappedLocalUrls(out[key], portUrls);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
119
127
|
return { headers: out, acceptEncoding, ifNoneMatch };
|
|
120
128
|
}
|
|
121
129
|
|
|
@@ -123,14 +131,23 @@ export function shouldRewriteBody(headers) {
|
|
|
123
131
|
const enc = headerGet(headers, "content-encoding").toLowerCase();
|
|
124
132
|
if (enc && enc !== "identity") return false;
|
|
125
133
|
const ct = headerGet(headers, "content-type").toLowerCase();
|
|
126
|
-
|
|
134
|
+
if (/event-stream|octet-stream|image\/|audio\/|video\/|font\/|wasm/.test(ct)) {
|
|
135
|
+
return false;
|
|
136
|
+
}
|
|
137
|
+
return /html|javascript|ecmascript|css|json|svg|xml|text\/|urlencoded|x-component|x-ref|\brsc\b/.test(
|
|
127
138
|
ct
|
|
128
139
|
);
|
|
129
140
|
}
|
|
130
141
|
|
|
131
142
|
/** Redirects have no Content-Type, but Location still has to stay under the share prefix. */
|
|
132
143
|
export function shouldProcessShareResponse(headers) {
|
|
133
|
-
|
|
144
|
+
if (headerGet(headers, "location")) return true;
|
|
145
|
+
if (shouldRewriteBody(headers)) return true;
|
|
146
|
+
const ct = headerGet(headers, "content-type").toLowerCase();
|
|
147
|
+
if (ct) return false;
|
|
148
|
+
const len = Number(headerGet(headers, "content-length") || 0);
|
|
149
|
+
if (len > 2 * 1024 * 1024) return false;
|
|
150
|
+
return true;
|
|
134
151
|
}
|
|
135
152
|
|
|
136
153
|
function isImmutableAssetPath(path) {
|
|
@@ -155,7 +172,8 @@ function isNoStorePath(path) {
|
|
|
155
172
|
/\/@vite(?:\/|$)/.test(p) ||
|
|
156
173
|
/\/@react-refresh/.test(p) ||
|
|
157
174
|
/\/@fs\//.test(p) ||
|
|
158
|
-
/\/@id\//.test(p)
|
|
175
|
+
/\/@id\//.test(p) ||
|
|
176
|
+
/\/__mp\//.test(p)
|
|
159
177
|
);
|
|
160
178
|
}
|
|
161
179
|
|
|
@@ -240,30 +258,199 @@ function notModifiedResult(headers, etag) {
|
|
|
240
258
|
return { status: 304, headers: out, body: Buffer.alloc(0) };
|
|
241
259
|
}
|
|
242
260
|
|
|
243
|
-
function
|
|
244
|
-
|
|
245
|
-
|
|
261
|
+
function isLoopbackHost(host) {
|
|
262
|
+
const name = String(host || "").toLowerCase().replace(/^\[|\]$/g, "");
|
|
263
|
+
return (
|
|
264
|
+
name === "127.0.0.1" ||
|
|
265
|
+
name === "localhost" ||
|
|
266
|
+
name === "::1" ||
|
|
267
|
+
name === "0.0.0.0"
|
|
268
|
+
);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
function mappedUrlForPort(portUrls, port) {
|
|
272
|
+
if (!portUrls || !port) return "";
|
|
273
|
+
const dest = portUrls[port] || portUrls[String(port)];
|
|
274
|
+
return dest ? String(dest).replace(/\/$/, "") : "";
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
function isProbablyUtf8Text(buf) {
|
|
278
|
+
if (!Buffer.isBuffer(buf) || !buf.length || buf.length > 8 * 1024 * 1024) {
|
|
279
|
+
return false;
|
|
280
|
+
}
|
|
281
|
+
const sample = buf.subarray(0, Math.min(buf.length, 4096));
|
|
282
|
+
if (sample.includes(0)) return false;
|
|
283
|
+
return true;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* Replace app-list origins (`localhost:8080`, LAN IPs, hostnames) with the
|
|
288
|
+
* share URL for that port. Self-contained so the browser shim/SW can embed it.
|
|
289
|
+
*
|
|
290
|
+
* @param {string} text
|
|
291
|
+
* @param {Record<string, string> | null | undefined} portUrls
|
|
292
|
+
*/
|
|
293
|
+
export function rewriteMappedLocalUrls(text, portUrls) {
|
|
294
|
+
if (!text || !portUrls) return text;
|
|
295
|
+
const ports = Object.keys(portUrls)
|
|
296
|
+
.map((key) => Number(key))
|
|
297
|
+
.filter((port) => Number.isInteger(port) && port > 0 && port <= 65535)
|
|
298
|
+
.sort((a, b) => b - a);
|
|
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:]+\\])";
|
|
308
|
+
let out = String(text);
|
|
309
|
+
for (let i = 0; i < ports.length; i++) {
|
|
310
|
+
const port = ports[i];
|
|
311
|
+
const dest = String(portUrls[port] || portUrls[String(port)] || "").replace(
|
|
312
|
+
/\/$/,
|
|
313
|
+
""
|
|
314
|
+
);
|
|
315
|
+
if (!dest) continue;
|
|
316
|
+
const destWs = dest.replace(/^http/i, "ws");
|
|
317
|
+
const destEsc = dest.replace(/\//g, "\\/");
|
|
318
|
+
const destWsEsc = destWs.replace(/\//g, "\\/");
|
|
319
|
+
const tail = "(?!\\d)";
|
|
320
|
+
const swap = function (matched, replacement) {
|
|
321
|
+
if (!matched) return matched;
|
|
322
|
+
if (dest.indexOf(matched) === 0 || destWs.indexOf(matched) === 0) {
|
|
323
|
+
return matched;
|
|
324
|
+
}
|
|
325
|
+
return replacement;
|
|
326
|
+
};
|
|
327
|
+
out = out.replace(new RegExp("https?://" + localHost + ":" + port + tail, "gi"), function (m) {
|
|
328
|
+
return swap(m, dest);
|
|
329
|
+
});
|
|
330
|
+
out = out.replace(new RegExp("wss?://" + localHost + ":" + port + tail, "gi"), function (m) {
|
|
331
|
+
return swap(m, destWs);
|
|
332
|
+
});
|
|
333
|
+
out = out.replace(new RegExp("https?:\\\\/\\\\/" + localHost + ":" + port + tail, "gi"), function (m) {
|
|
334
|
+
return swap(m, destEsc);
|
|
335
|
+
});
|
|
336
|
+
out = out.replace(new RegExp("wss?:\\\\/\\\\/" + localHost + ":" + port + tail, "gi"), function (m) {
|
|
337
|
+
return swap(m, destWsEsc);
|
|
338
|
+
});
|
|
339
|
+
out = out.replace(new RegExp("//" + localHost + ":" + port + tail, "gi"), function (m) {
|
|
340
|
+
return swap(m, dest.replace(/^https?:/i, ""));
|
|
341
|
+
});
|
|
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
|
+
out = out.replace(
|
|
349
|
+
new RegExp("(?<![\\w./])" + localHost + ":" + port + tail, "gi"),
|
|
350
|
+
function (m) {
|
|
351
|
+
return swap(m, dest);
|
|
352
|
+
}
|
|
353
|
+
);
|
|
354
|
+
}
|
|
355
|
+
return out;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
/**
|
|
359
|
+
* @param {Buffer | string | null | undefined} body
|
|
360
|
+
* @param {Record<string, string>} headers
|
|
361
|
+
* @param {Record<string, string> | null | undefined} portUrls
|
|
362
|
+
*/
|
|
363
|
+
export function rewriteShareRequestBody(body, headers, portUrls) {
|
|
364
|
+
if (!body || !portUrls || !Object.keys(portUrls).length) return body;
|
|
365
|
+
const buf = Buffer.isBuffer(body) ? body : Buffer.from(body);
|
|
366
|
+
if (!buf.length) return buf;
|
|
367
|
+
if (!shouldRewriteBody(headers) && !isProbablyUtf8Text(buf)) return buf;
|
|
368
|
+
const text = buf.toString("utf8");
|
|
369
|
+
const next = rewriteMappedLocalUrls(text, portUrls);
|
|
370
|
+
if (next === text) return buf;
|
|
371
|
+
return Buffer.from(next, "utf8");
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
export function shareTokenRoot(publicBase) {
|
|
246
375
|
const prefix = proxyPathPrefix(publicBase);
|
|
376
|
+
if (!prefix) return "";
|
|
377
|
+
const parts = prefix.split("/").filter(Boolean);
|
|
378
|
+
if (parts[0] === "p" && parts[1]) return `/${parts[0]}/${parts[1]}/`;
|
|
379
|
+
return prefix.endsWith("/") ? prefix : `${prefix}/`;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
export function shareShimScript(pathPrefix, portUrls) {
|
|
383
|
+
return `(${shareProxyShim.toString()})(${JSON.stringify(pathPrefix || "")},${JSON.stringify(portUrls || {})},${rewriteMappedLocalUrls.toString()});`;
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
export function shareServiceWorkerScript(portUrls, tokenRoot) {
|
|
387
|
+
return `(${shareServiceWorkerMain.toString()})(${JSON.stringify(portUrls || {})},${JSON.stringify(tokenRoot || "/")},${rewriteMappedLocalUrls.toString()});`;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
function rewriteHeaderUrls(headers, publicBase, port, portUrls) {
|
|
391
|
+
if (headers.location) {
|
|
392
|
+
headers.location = rewriteLocation(
|
|
393
|
+
headers.location,
|
|
394
|
+
publicBase,
|
|
395
|
+
port,
|
|
396
|
+
portUrls
|
|
397
|
+
);
|
|
398
|
+
}
|
|
399
|
+
if (headers.link) {
|
|
400
|
+
headers.link = rewriteLinkHeader(headers.link, publicBase);
|
|
401
|
+
}
|
|
402
|
+
if (headers["access-control-allow-origin"]) {
|
|
403
|
+
headers["access-control-allow-origin"] = rewriteAllowOrigin(
|
|
404
|
+
headers["access-control-allow-origin"],
|
|
405
|
+
publicBase
|
|
406
|
+
);
|
|
407
|
+
}
|
|
408
|
+
if (!(portUrls && Object.keys(portUrls).length)) return;
|
|
409
|
+
for (const key of Object.keys(headers)) {
|
|
410
|
+
const lower = key.toLowerCase();
|
|
411
|
+
if (lower === "set-cookie" || lower === "content-length" || lower === "content-encoding") {
|
|
412
|
+
continue;
|
|
413
|
+
}
|
|
414
|
+
headers[key] = rewriteMappedLocalUrls(headers[key], portUrls);
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
function rewriteLocation(value, publicBase, port, portUrls) {
|
|
419
|
+
if (!publicBase && !(portUrls && Object.keys(portUrls).length)) return value;
|
|
247
420
|
try {
|
|
248
421
|
const u = new URL(value, `http://127.0.0.1:${Number(port) || 0}`);
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
422
|
+
if (!isLoopbackHost(u.hostname)) {
|
|
423
|
+
return rewriteMappedLocalUrls(String(value), portUrls);
|
|
424
|
+
}
|
|
425
|
+
const locPort = Number(u.port) || Number(port) || 0;
|
|
426
|
+
const mapped =
|
|
427
|
+
mappedUrlForPort(portUrls, locPort) ||
|
|
428
|
+
String(publicBase || "").replace(/\/$/, "");
|
|
429
|
+
if (!mapped) return value;
|
|
430
|
+
const prefix = proxyPathPrefix(mapped);
|
|
256
431
|
let path = u.pathname || "/";
|
|
257
432
|
if (prefix && (path === prefix || path.startsWith(`${prefix}/`))) {
|
|
258
433
|
path = path.slice(prefix.length) || "/";
|
|
259
434
|
}
|
|
260
|
-
return `${
|
|
435
|
+
if (path === "/") return `${mapped}${u.search}${u.hash}`;
|
|
436
|
+
return `${mapped}${path}${u.search}${u.hash}`;
|
|
261
437
|
} catch {
|
|
262
438
|
/* keep */
|
|
263
439
|
}
|
|
264
440
|
return value;
|
|
265
441
|
}
|
|
266
442
|
|
|
443
|
+
function rewriteAllowOrigin(value, publicBase) {
|
|
444
|
+
if (!value || value === "*" || !publicBase) return value;
|
|
445
|
+
try {
|
|
446
|
+
const u = new URL(value);
|
|
447
|
+
if (!isLoopbackHost(u.hostname)) return value;
|
|
448
|
+
return new URL(publicBase).origin;
|
|
449
|
+
} catch {
|
|
450
|
+
return value;
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
|
|
267
454
|
function rewriteLinkHeader(value, publicBase) {
|
|
268
455
|
const prefix = proxyPathPrefix(publicBase);
|
|
269
456
|
if (!prefix || !value) return value;
|
|
@@ -686,11 +873,22 @@ function injectMaintainerProEmbed(html, aiPublicBase) {
|
|
|
686
873
|
}
|
|
687
874
|
|
|
688
875
|
/**
|
|
689
|
-
*
|
|
690
|
-
* only touch same-origin Vite/Next assets. Other hosts are left unchanged.
|
|
876
|
+
* Intercept every browser request and map listed app ports onto share URLs.
|
|
691
877
|
*/
|
|
692
|
-
function shareProxyShim(p) {
|
|
693
|
-
if (!p) return;
|
|
878
|
+
function shareProxyShim(p, portMap, rewriteMappedLocalUrls) {
|
|
879
|
+
if (!p || window.__MP_SHARE_SHIM__) return;
|
|
880
|
+
window.__MP_SHARE_SHIM__ = 1;
|
|
881
|
+
window.__MP_PORT_MAP__ = portMap || {};
|
|
882
|
+
function rewriteText(text) {
|
|
883
|
+
if (typeof text !== "string" || !text || typeof rewriteMappedLocalUrls !== "function") {
|
|
884
|
+
return text;
|
|
885
|
+
}
|
|
886
|
+
try {
|
|
887
|
+
return rewriteMappedLocalUrls(text, portMap);
|
|
888
|
+
} catch (e) {
|
|
889
|
+
return text;
|
|
890
|
+
}
|
|
891
|
+
}
|
|
694
892
|
function collapse(path) {
|
|
695
893
|
var d = p + p;
|
|
696
894
|
while (path.indexOf(d) === 0) path = p + path.slice(d.length);
|
|
@@ -718,8 +916,34 @@ function shareProxyShim(p) {
|
|
|
718
916
|
}
|
|
719
917
|
return path;
|
|
720
918
|
}
|
|
919
|
+
function mapLocal(v) {
|
|
920
|
+
if (typeof v !== "string" || !v) return v;
|
|
921
|
+
if (
|
|
922
|
+
v.indexOf("blob:") === 0 ||
|
|
923
|
+
v.indexOf("data:") === 0 ||
|
|
924
|
+
v.indexOf("javascript:") === 0
|
|
925
|
+
) {
|
|
926
|
+
return v;
|
|
927
|
+
}
|
|
928
|
+
var raw = v;
|
|
929
|
+
if (
|
|
930
|
+
v.indexOf("://") < 0 &&
|
|
931
|
+
/^(localhost|127\.0\.0\.1|\[::1\]|0\.0\.0\.0):\d+/i.test(v)
|
|
932
|
+
) {
|
|
933
|
+
raw = "http://" + v;
|
|
934
|
+
}
|
|
935
|
+
var next = rewriteText(raw);
|
|
936
|
+
if (next !== raw) return next;
|
|
937
|
+
try {
|
|
938
|
+
var u = new URL(v, location.href);
|
|
939
|
+
var resolved = rewriteText(u.href);
|
|
940
|
+
if (resolved !== u.href) return resolved;
|
|
941
|
+
} catch (e) {}
|
|
942
|
+
return v;
|
|
943
|
+
}
|
|
721
944
|
function addNav(v) {
|
|
722
945
|
if (typeof v !== "string" || !v) return v;
|
|
946
|
+
v = mapLocal(v);
|
|
723
947
|
if (v.charAt(0) === "/" && v.charAt(1) !== "/") return prefixPath(v);
|
|
724
948
|
try {
|
|
725
949
|
var nav = new URL(v, location.href);
|
|
@@ -731,6 +955,8 @@ function shareProxyShim(p) {
|
|
|
731
955
|
}
|
|
732
956
|
function addNet(v) {
|
|
733
957
|
if (typeof v !== "string" || !v) return v;
|
|
958
|
+
var mapped = mapLocal(v);
|
|
959
|
+
if (mapped !== v) return mapped;
|
|
734
960
|
try {
|
|
735
961
|
if (/^[a-zA-Z][a-zA-Z0-9+.-]*:/.test(v) || v.indexOf("//") === 0) {
|
|
736
962
|
var net = new URL(v, location.href);
|
|
@@ -776,11 +1002,22 @@ function shareProxyShim(p) {
|
|
|
776
1002
|
patchQS(Element.prototype, "querySelectorAll");
|
|
777
1003
|
var sa = Element.prototype.setAttribute;
|
|
778
1004
|
Element.prototype.setAttribute = function (n, v) {
|
|
779
|
-
|
|
1005
|
+
var name = String(n || "").toLowerCase();
|
|
1006
|
+
if (
|
|
1007
|
+
(name === "src" ||
|
|
1008
|
+
name === "href" ||
|
|
1009
|
+
name === "action" ||
|
|
1010
|
+
name === "poster" ||
|
|
1011
|
+
name === "data-src") &&
|
|
1012
|
+
typeof v === "string"
|
|
1013
|
+
) {
|
|
1014
|
+
v = addNav(v);
|
|
1015
|
+
}
|
|
780
1016
|
return sa.call(this, n, v);
|
|
781
1017
|
};
|
|
782
1018
|
function patchUrlProp(ctor, prop) {
|
|
783
1019
|
try {
|
|
1020
|
+
if (!ctor || !ctor.prototype) return;
|
|
784
1021
|
var d = Object.getOwnPropertyDescriptor(ctor.prototype, prop);
|
|
785
1022
|
if (!d || !d.set) return;
|
|
786
1023
|
Object.defineProperty(ctor.prototype, prop, {
|
|
@@ -795,6 +1032,13 @@ function shareProxyShim(p) {
|
|
|
795
1032
|
}
|
|
796
1033
|
patchUrlProp(HTMLScriptElement, "src");
|
|
797
1034
|
patchUrlProp(HTMLLinkElement, "href");
|
|
1035
|
+
patchUrlProp(HTMLAnchorElement, "href");
|
|
1036
|
+
patchUrlProp(HTMLImageElement, "src");
|
|
1037
|
+
patchUrlProp(HTMLIFrameElement, "src");
|
|
1038
|
+
patchUrlProp(HTMLFormElement, "action");
|
|
1039
|
+
patchUrlProp(HTMLSourceElement, "src");
|
|
1040
|
+
patchUrlProp(HTMLVideoElement, "src");
|
|
1041
|
+
patchUrlProp(HTMLAudioElement, "src");
|
|
798
1042
|
var f = window.fetch;
|
|
799
1043
|
window.fetch = function (input, init) {
|
|
800
1044
|
if (typeof input === "string") input = addNet(input);
|
|
@@ -803,6 +1047,9 @@ function shareProxyShim(p) {
|
|
|
803
1047
|
} else if (typeof URL !== "undefined" && input instanceof URL) {
|
|
804
1048
|
input = new URL(addNet(input.href));
|
|
805
1049
|
}
|
|
1050
|
+
if (init && typeof init.body === "string") {
|
|
1051
|
+
init = Object.assign({}, init, { body: rewriteText(init.body) });
|
|
1052
|
+
}
|
|
806
1053
|
return f.call(this, input, init);
|
|
807
1054
|
};
|
|
808
1055
|
var xo = XMLHttpRequest.prototype.open;
|
|
@@ -810,6 +1057,11 @@ function shareProxyShim(p) {
|
|
|
810
1057
|
if (typeof u === "string") arguments[1] = addNet(u);
|
|
811
1058
|
return xo.apply(this, arguments);
|
|
812
1059
|
};
|
|
1060
|
+
var xs = XMLHttpRequest.prototype.send;
|
|
1061
|
+
XMLHttpRequest.prototype.send = function (body) {
|
|
1062
|
+
if (typeof body === "string") arguments[0] = rewriteText(body);
|
|
1063
|
+
return xs.apply(this, arguments);
|
|
1064
|
+
};
|
|
813
1065
|
var ps = history.pushState.bind(history);
|
|
814
1066
|
history.pushState = function (s, t, u) {
|
|
815
1067
|
if (typeof u === "string") u = addNav(u);
|
|
@@ -823,6 +1075,7 @@ function shareProxyShim(p) {
|
|
|
823
1075
|
var WS = window.WebSocket;
|
|
824
1076
|
function WrappedWS(url, protocols) {
|
|
825
1077
|
if (typeof url === "string") url = addNet(url);
|
|
1078
|
+
else if (typeof URL !== "undefined" && url instanceof URL) url = addNet(url.href);
|
|
826
1079
|
return protocols !== undefined ? new WS(url, protocols) : new WS(url);
|
|
827
1080
|
}
|
|
828
1081
|
WrappedWS.prototype = WS.prototype;
|
|
@@ -831,6 +1084,30 @@ function shareProxyShim(p) {
|
|
|
831
1084
|
WrappedWS.CLOSING = WS.CLOSING;
|
|
832
1085
|
WrappedWS.CLOSED = WS.CLOSED;
|
|
833
1086
|
window.WebSocket = WrappedWS;
|
|
1087
|
+
if (window.EventSource) {
|
|
1088
|
+
var ES = window.EventSource;
|
|
1089
|
+
function WrappedES(url, config) {
|
|
1090
|
+
if (typeof url === "string") url = addNet(url);
|
|
1091
|
+
return config !== undefined ? new ES(url, config) : new ES(url);
|
|
1092
|
+
}
|
|
1093
|
+
WrappedES.prototype = ES.prototype;
|
|
1094
|
+
WrappedES.CONNECTING = ES.CONNECTING;
|
|
1095
|
+
WrappedES.OPEN = ES.OPEN;
|
|
1096
|
+
WrappedES.CLOSED = ES.CLOSED;
|
|
1097
|
+
window.EventSource = WrappedES;
|
|
1098
|
+
}
|
|
1099
|
+
if (navigator.sendBeacon) {
|
|
1100
|
+
var sb = navigator.sendBeacon.bind(navigator);
|
|
1101
|
+
navigator.sendBeacon = function (url, data) {
|
|
1102
|
+
if (typeof data === "string") data = rewriteText(data);
|
|
1103
|
+
return sb(addNet(String(url)), data);
|
|
1104
|
+
};
|
|
1105
|
+
}
|
|
1106
|
+
var wo = window.open;
|
|
1107
|
+
window.open = function (url) {
|
|
1108
|
+
if (typeof url === "string") arguments[0] = addNav(url);
|
|
1109
|
+
return wo.apply(this, arguments);
|
|
1110
|
+
};
|
|
834
1111
|
try {
|
|
835
1112
|
var la = location.assign.bind(location);
|
|
836
1113
|
location.assign = function (u) {
|
|
@@ -856,19 +1133,102 @@ function shareProxyShim(p) {
|
|
|
856
1133
|
});
|
|
857
1134
|
}
|
|
858
1135
|
} catch (e) {}
|
|
1136
|
+
try {
|
|
1137
|
+
var tokenRoot = p.replace(/\/[^/]+$/, "/");
|
|
1138
|
+
if (navigator.serviceWorker && tokenRoot.indexOf("/p/") === 0) {
|
|
1139
|
+
navigator.serviceWorker.register(p + "/__mp/sw.js", { scope: tokenRoot });
|
|
1140
|
+
}
|
|
1141
|
+
} catch (e) {}
|
|
1142
|
+
}
|
|
1143
|
+
|
|
1144
|
+
function shareServiceWorkerMain(portMap, tokenRoot, rewriteMappedLocalUrls) {
|
|
1145
|
+
self.addEventListener("install", function (event) {
|
|
1146
|
+
event.waitUntil(self.skipWaiting());
|
|
1147
|
+
});
|
|
1148
|
+
self.addEventListener("activate", function (event) {
|
|
1149
|
+
event.waitUntil(self.clients.claim());
|
|
1150
|
+
});
|
|
1151
|
+
function rewriteText(text) {
|
|
1152
|
+
if (typeof text !== "string" || !text) return text;
|
|
1153
|
+
try {
|
|
1154
|
+
return rewriteMappedLocalUrls(text, portMap);
|
|
1155
|
+
} catch (e) {
|
|
1156
|
+
return text;
|
|
1157
|
+
}
|
|
1158
|
+
}
|
|
1159
|
+
function mapUrl(v) {
|
|
1160
|
+
if (typeof v !== "string" || !v) return v;
|
|
1161
|
+
if (v.indexOf("/__mp/") !== -1) return v;
|
|
1162
|
+
return rewriteText(v);
|
|
1163
|
+
}
|
|
1164
|
+
self.addEventListener("fetch", function (event) {
|
|
1165
|
+
var req = event.request;
|
|
1166
|
+
if (req.url.indexOf("/__mp/") !== -1) return;
|
|
1167
|
+
event.respondWith(
|
|
1168
|
+
(async function () {
|
|
1169
|
+
var url = mapUrl(req.url);
|
|
1170
|
+
var method = req.method;
|
|
1171
|
+
var headers = new Headers(req.headers);
|
|
1172
|
+
var body;
|
|
1173
|
+
if (method !== "GET" && method !== "HEAD") {
|
|
1174
|
+
try {
|
|
1175
|
+
var ct = headers.get("content-type") || "";
|
|
1176
|
+
if (/json|text|xml|urlencoded|javascript/.test(ct) || !ct) {
|
|
1177
|
+
var text = await req.clone().text();
|
|
1178
|
+
var next = rewriteText(text);
|
|
1179
|
+
if (next !== text) body = next;
|
|
1180
|
+
}
|
|
1181
|
+
} catch (e) {}
|
|
1182
|
+
}
|
|
1183
|
+
var init = {
|
|
1184
|
+
method: method,
|
|
1185
|
+
headers: headers,
|
|
1186
|
+
credentials: req.credentials,
|
|
1187
|
+
redirect: req.redirect,
|
|
1188
|
+
referrer: req.referrer,
|
|
1189
|
+
};
|
|
1190
|
+
if (req.mode && req.mode !== "navigate") init.mode = req.mode;
|
|
1191
|
+
if (body !== undefined) init.body = body;
|
|
1192
|
+
else if (method !== "GET" && method !== "HEAD") {
|
|
1193
|
+
try {
|
|
1194
|
+
init.body = await req.blob();
|
|
1195
|
+
} catch (e) {}
|
|
1196
|
+
}
|
|
1197
|
+
var res = await fetch(new Request(url, init));
|
|
1198
|
+
var resType = res.headers.get("content-type") || "";
|
|
1199
|
+
if (
|
|
1200
|
+
!/html|javascript|ecmascript|json|css|xml|svg|text|urlencoded/.test(resType)
|
|
1201
|
+
) {
|
|
1202
|
+
return res;
|
|
1203
|
+
}
|
|
1204
|
+
var resText = await res.text();
|
|
1205
|
+
var mapped = rewriteText(resText);
|
|
1206
|
+
var outHeaders = new Headers(res.headers);
|
|
1207
|
+
outHeaders.delete("content-length");
|
|
1208
|
+
outHeaders.delete("content-encoding");
|
|
1209
|
+
return new Response(mapped, {
|
|
1210
|
+
status: res.status,
|
|
1211
|
+
statusText: res.statusText,
|
|
1212
|
+
headers: outHeaders,
|
|
1213
|
+
});
|
|
1214
|
+
})()
|
|
1215
|
+
);
|
|
1216
|
+
});
|
|
859
1217
|
}
|
|
860
1218
|
|
|
861
1219
|
function injectNextProxyShim(html, publicBase) {
|
|
862
1220
|
const prefix = proxyPathPrefix(publicBase);
|
|
863
|
-
if (
|
|
864
|
-
!prefix ||
|
|
865
|
-
html.includes("data-mp-proxy-next") ||
|
|
866
|
-
(!isNextDocument(html) && !isViteDocument(html))
|
|
867
|
-
) {
|
|
1221
|
+
if (!prefix || html.includes("data-mp-proxy-next")) {
|
|
868
1222
|
return html;
|
|
869
1223
|
}
|
|
870
|
-
const script = `<script data-mp-proxy-next
|
|
871
|
-
|
|
1224
|
+
const script = `<script data-mp-proxy-next src="${prefix}/__mp/shim.js"><\/script>`;
|
|
1225
|
+
if (/<head[^>]*>/i.test(html)) {
|
|
1226
|
+
return html.replace(/<head([^>]*)>/i, `<head$1>${script}`);
|
|
1227
|
+
}
|
|
1228
|
+
if (/<body[^>]*>/i.test(html)) {
|
|
1229
|
+
return html.replace(/<body([^>]*)>/i, `<body$1>${script}`);
|
|
1230
|
+
}
|
|
1231
|
+
return `${script}${html}`;
|
|
872
1232
|
}
|
|
873
1233
|
|
|
874
1234
|
/**
|
|
@@ -885,6 +1245,7 @@ function injectNextProxyShim(html, publicBase) {
|
|
|
885
1245
|
* acceptEncoding?: string,
|
|
886
1246
|
* ifNoneMatch?: string,
|
|
887
1247
|
* port?: number,
|
|
1248
|
+
* portUrls?: Record<string, string>,
|
|
888
1249
|
* }} opts
|
|
889
1250
|
* @returns {{ status: number, headers: Record<string, string>, body: Buffer }}
|
|
890
1251
|
*/
|
|
@@ -896,6 +1257,8 @@ export function processShareHttpResponse(opts) {
|
|
|
896
1257
|
const acceptEncoding = String(opts?.acceptEncoding || "");
|
|
897
1258
|
const ifNoneMatch = String(opts?.ifNoneMatch || "");
|
|
898
1259
|
const port = Number(opts?.port) || 0;
|
|
1260
|
+
const portUrls =
|
|
1261
|
+
opts?.portUrls && typeof opts.portUrls === "object" ? opts.portUrls : {};
|
|
899
1262
|
let status =
|
|
900
1263
|
typeof opts?.status === "number" && opts.status >= 100 ? opts.status : 200;
|
|
901
1264
|
const headers = lowerHeaders(opts?.headers || {});
|
|
@@ -903,12 +1266,7 @@ export function processShareHttpResponse(opts) {
|
|
|
903
1266
|
? opts.body
|
|
904
1267
|
: Buffer.from(opts?.body || "");
|
|
905
1268
|
|
|
906
|
-
|
|
907
|
-
headers.location = rewriteLocation(headers.location, publicBase, port);
|
|
908
|
-
}
|
|
909
|
-
if (headers.link) {
|
|
910
|
-
headers.link = rewriteLinkHeader(headers.link, publicBase);
|
|
911
|
-
}
|
|
1269
|
+
rewriteHeaderUrls(headers, publicBase, port, portUrls);
|
|
912
1270
|
|
|
913
1271
|
const cachedKey = rewriteCacheKey(publicBase, path);
|
|
914
1272
|
const hit =
|
|
@@ -933,10 +1291,20 @@ export function processShareHttpResponse(opts) {
|
|
|
933
1291
|
|
|
934
1292
|
let text = payload.toString("utf8");
|
|
935
1293
|
let mutated = false;
|
|
936
|
-
|
|
1294
|
+
const rewriteTextBody =
|
|
1295
|
+
shouldRewriteBody(headers) ||
|
|
1296
|
+
(!headerGet(headers, "content-type") && isProbablyUtf8Text(payload));
|
|
1297
|
+
if (publicBase && rewriteTextBody) {
|
|
937
1298
|
text = prefixRootPaths(text, publicBase, headers["content-type"] || "");
|
|
938
1299
|
mutated = true;
|
|
939
1300
|
}
|
|
1301
|
+
if (Object.keys(portUrls).length && rewriteTextBody) {
|
|
1302
|
+
const mapped = rewriteMappedLocalUrls(text, portUrls);
|
|
1303
|
+
if (mapped !== text) {
|
|
1304
|
+
text = mapped;
|
|
1305
|
+
mutated = true;
|
|
1306
|
+
}
|
|
1307
|
+
}
|
|
940
1308
|
if (aiPublicBase) {
|
|
941
1309
|
const withShareUrls = rewriteLocalSidecarUrls(text, aiPublicBase, publicBase);
|
|
942
1310
|
if (withShareUrls !== text) {
|
|
@@ -951,12 +1319,8 @@ export function processShareHttpResponse(opts) {
|
|
|
951
1319
|
mutated = true;
|
|
952
1320
|
}
|
|
953
1321
|
}
|
|
954
|
-
if (
|
|
955
|
-
publicBase
|
|
956
|
-
isHtmlDocument(headers, text) &&
|
|
957
|
-
(isNextDocument(text) || isViteDocument(text))
|
|
958
|
-
) {
|
|
959
|
-
const next = injectNextProxyShim(text, publicBase);
|
|
1322
|
+
if (publicBase && isHtmlDocument(headers, text)) {
|
|
1323
|
+
const next = injectNextProxyShim(text, publicBase, portUrls);
|
|
960
1324
|
if (next !== text) {
|
|
961
1325
|
text = next;
|
|
962
1326
|
mutated = true;
|