mirror of
https://github.com/therealaleph/MasterHttpRelayVPN-RUST.git
synced 2026-05-17 21:24:48 +03:00
Fixes #1047. `_doSingle`'s normal-relay path (cache disabled or cache miss on non-cachable request) ran `UrlFetchApp.fetch` → `getContent` → `base64Encode` with no error wrapper. Any throw — most commonly when the response body approaches Apps Script's ~50 MB ceiling and `base64Encode` blows the V8 heap, also URL-too-long / payload-too-large / quota exhaustion / 6-minute execution timeout — propagated unhandled, and Apps Script served its default `<title>Web App</title>` HTML error page in place of the JSON envelope. The Rust client (`parse_relay_json` in `domain_fronter.rs`) then failed to find JSON and surfaced the cryptic `bad response: no json in: <!DOCTYPE html>...` with no signal as to the actual cause. The reporter's symptom — a single failing host (`shc-dist.lostsig.co`, sonichacking.org) serving large ROM-hack binaries — matches this exactly. Every other download worked because they were all under the body-size ceiling. ## Fix Wrap the normal-relay block in `_doSingle` with `try { ... } catch (err) { return _json({ e: "fetch failed: " + String(err) }); }`. Mirrors the per-item try/catch already present in `_doBatch`. Turns the silent HTML crash into a structured `FronterError::Relay("fetch failed: …")` on the client side that pinpoints the real underlying error. Cache path intentionally untouched: - `_fetchAndCache` already wraps its own fetch in try/catch and returns `null` on any failure (so `_doSingle` falls through cleanly to the normal relay). - The cached-read path is bounded to ≤ `CACHE_MAX_BODY_BYTES` (35 KB) so it cannot trip the size limits that caused this bug. ## Verified locally on top of v1.9.22 - `node --check assets/apps_script/Code.gs`: clean ✅ - `cargo test --lib --release`: 209/209 ✅ (sanity — no Rust change) Reviewed via Anthropic Claude. Co-Authored-By: dazzling-no-more <noreply@github.com> Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -189,13 +189,27 @@ function _doSingle(req) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ── Normal relay (cache disabled or unavailable) ────────
|
// ── Normal relay (cache disabled or unavailable) ────────
|
||||||
var opts = _buildOpts(req);
|
// Wrap the fetch + body encode in try/catch so any failure surfaces as
|
||||||
var resp = UrlFetchApp.fetch(req.u, opts);
|
// a JSON error envelope the Rust client can parse. Without this, throws
|
||||||
return _json({
|
// from UrlFetchApp.fetch (URL too long, payload too large, quota
|
||||||
s: resp.getResponseCode(),
|
// exhausted, 6-minute execution timeout) or from base64Encode (response
|
||||||
h: _respHeaders(resp),
|
// body near Apps Script's ~50 MB ceiling can blow the V8 heap during
|
||||||
b: Utilities.base64Encode(resp.getContent()),
|
// encode) propagate unhandled, and Apps Script serves its default
|
||||||
});
|
// `<title>Web App</title>` HTML error page — which the client then
|
||||||
|
// reports as "Relay failed: bad response: no json in: <title>Web App>..."
|
||||||
|
// and the user has no signal as to the actual cause. Mirrors the
|
||||||
|
// per-item try/catch in _doBatch below.
|
||||||
|
try {
|
||||||
|
var opts = _buildOpts(req);
|
||||||
|
var resp = UrlFetchApp.fetch(req.u, opts);
|
||||||
|
return _json({
|
||||||
|
s: resp.getResponseCode(),
|
||||||
|
h: _respHeaders(resp),
|
||||||
|
b: Utilities.base64Encode(resp.getContent()),
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
return _json({ e: "fetch failed: " + String(err) });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── Batch Request ──────────────────────────────────────────
|
// ── Batch Request ──────────────────────────────────────────
|
||||||
|
|||||||
Reference in New Issue
Block a user