fix: harden connection, payload, and persisted state handling (#1354)

* fix: clean up Cloudflare tunnel timeouts

* fix: couple tunnel socket lifecycle

* fix: validate Docker console messages

* fix: bound homepage proxy responses

* fix: bound reconnect and response failures

* fix: harden persisted and socket state

* fix: support local connections to shared hosts
This commit is contained in:
ZacharyZcR
2026-08-28 10:36:39 +08:00
committed by GitHub
parent 703e8cd037
commit c129666d7f
28 changed files with 689 additions and 157 deletions
+21 -2
View File
@@ -536,6 +536,16 @@ function httpFetch(url, options = {}) {
// Node's http/https modules never auto-decompress, so an unhandled
// content-encoding here silently turns the body into garbage bytes.
let stream = res;
const maxResponseBytes = options.maxResponseBytes || 10 * 1024 * 1024;
let responseBytes = 0;
let settled = false;
const fail = (error) => {
if (settled) return;
settled = true;
stream.destroy();
req.destroy();
reject(error);
};
const encoding = (res.headers["content-encoding"] || "")
.toLowerCase()
.trim();
@@ -552,8 +562,17 @@ function httpFetch(url, options = {}) {
return;
}
stream.on("data", (chunk) => chunks.push(chunk));
stream.on("data", (chunk) => {
responseBytes += chunk.length;
if (responseBytes > maxResponseBytes) {
fail(new Error(`Response exceeds ${maxResponseBytes} bytes`));
return;
}
chunks.push(chunk);
});
stream.on("end", () => {
if (settled) return;
settled = true;
const data = Buffer.concat(chunks).toString("utf8");
resolve({
ok: res.statusCode >= 200 && res.statusCode < 300,
@@ -562,7 +581,7 @@ function httpFetch(url, options = {}) {
json: () => Promise.resolve(JSON.parse(data)),
});
});
stream.on("error", reject);
stream.on("error", fail);
});
req.on("error", reject);