Feat : Auto restart after crash

This commit is contained in:
decolua
2026-03-14 09:37:29 +07:00
parent 549223c8cf
commit adae2605bf
31 changed files with 340 additions and 189 deletions
+19 -14
View File
@@ -5,8 +5,8 @@ const isCloud = typeof caches !== "undefined" && typeof caches === "object";
const originalFetch = globalThis.fetch;
const proxyDispatchers = new Map();
// DNS cache: { [hostname]: { ip, expiry } }
const DNS_CACHE = {};
// DNS cache — use Map to avoid prototype pollution via malformed hostnames
const DNS_CACHE = new Map();
const MITM_BYPASS_HOSTS = ["cloudcode-pa.googleapis.com", "daily-cloudcode-pa.googleapis.com", "googleapis.com"];
const MITM_BYPASS_HEADER = "x-request-source";
const MITM_BYPASS_VALUE = "local";
@@ -24,7 +24,7 @@ function normalizeString(value) {
* Resolve real IP using Google DNS (bypass system DNS)
*/
async function resolveRealIP(hostname) {
const cached = DNS_CACHE[hostname];
const cached = DNS_CACHE.get(hostname);
if (cached && Date.now() < cached.expiry) return cached.ip;
try {
@@ -34,7 +34,7 @@ async function resolveRealIP(hostname) {
resolver.setServers(GOOGLE_DNS_SERVERS);
const resolve4 = promisify(resolver.resolve4.bind(resolver));
const addresses = await resolve4(hostname);
DNS_CACHE[hostname] = { ip: addresses[0], expiry: Date.now() + MEMORY_CONFIG.dnsCacheTtlMs };
DNS_CACHE.set(hostname, { ip: addresses[0], expiry: Date.now() + MEMORY_CONFIG.dnsCacheTtlMs });
return addresses[0];
} catch (error) {
console.warn(`[ProxyFetch] DNS resolve failed for ${hostname}:`, error.message);
@@ -53,23 +53,27 @@ function shouldBypassMitmDns(url, options) {
headers[MITM_BYPASS_HEADER.charAt(0).toUpperCase() + MITM_BYPASS_HEADER.slice(1)] === MITM_BYPASS_VALUE;
if (!hasLocalMarker) {
// Debug: log when bypass is not triggered
const hostname = new URL(url).hostname;
if (MITM_BYPASS_HOSTS.some(host => hostname.includes(host))) {
console.warn(`[ProxyFetch] MITM bypass NOT triggered for ${hostname} - missing header`);
}
try {
const hostname = new URL(url).hostname;
if (MITM_BYPASS_HOSTS.some(host => hostname.includes(host))) {
console.warn(`[ProxyFetch] MITM bypass NOT triggered for ${hostname} - missing header`);
}
} catch { /* invalid URL — skip debug log */ }
return false;
}
const hostname = new URL(url).hostname;
return MITM_BYPASS_HOSTS.some(host => hostname.includes(host));
try {
const hostname = new URL(url).hostname;
return MITM_BYPASS_HOSTS.some(host => hostname.includes(host));
} catch { return false; }
}
function shouldBypassByNoProxy(targetUrl, noProxyValue) {
const noProxy = normalizeString(noProxyValue);
if (!noProxy) return false;
const hostname = new URL(targetUrl).hostname.toLowerCase();
let hostname;
try { hostname = new URL(targetUrl).hostname.toLowerCase(); } catch { return false; }
const patterns = noProxy.split(",").map((p) => p.trim().toLowerCase()).filter(Boolean);
return patterns.some((pattern) => {
@@ -86,7 +90,8 @@ function getEnvProxyUrl(targetUrl) {
const noProxy = process.env.NO_PROXY || process.env.no_proxy;
if (shouldBypassByNoProxy(targetUrl, noProxy)) return null;
const protocol = new URL(targetUrl).protocol;
let protocol;
try { protocol = new URL(targetUrl).protocol; } catch { return null; }
if (protocol === "https:") {
return process.env.HTTPS_PROXY || process.env.https_proxy ||
@@ -152,7 +157,7 @@ async function getDispatcher(proxyUrl) {
async function createBypassRequest(parsedUrl, realIP, options) {
const https = await import("https");
const net = await import("net");
const { Readable } = require("stream");
const { Readable } = await import("stream");
return new Promise((resolve, reject) => {
const socket = new net.Socket();