mirror of
https://github.com/therealaleph/MasterHttpRelayVPN-RUST.git
synced 2026-05-18 06:44:35 +03:00
fix(exit_node): strip Content-Encoding + Content-Length on response (#964)
@mehdimalekidev reported `Content Encoding Error` when ChatGPT was routed through Apps Script + exit-node. Root cause: 1. Browser → Apps Script with `Accept-Encoding: gzip, br` (default). 2. Apps Script forwards header to exit-node. 3. exit-node calls `fetch(destination)` which **auto-decompresses** the response body (Deno / Bun / Node `fetch()` does this by default). 4. `resp.arrayBuffer()` returns **plain decompressed bytes** but `resp.headers` still has `Content-Encoding: gzip` from the destination. 5. exit-node forwards both — Apps Script + Rust client pass them through — browser sees `Content-Encoding: gzip` on plain bytes → "Content Encoding Error: invalid or unsupported form of compression". Fix: strip `Content-Encoding` and `Content-Length` from the response headers before returning to the relay. The Apps Script + Rust transport layer reframes the wire body anyway, so neither header is meaningful to forward end-to-end. Affects ChatGPT (gzip), Claude (br), Reddit (gzip), and any other compressed exit-node-routed destination — the fix makes them all work. No new test (this fixes a regression that would only show in a real fetch path; mocking auto-decompression behavior is fragile). Manual verification: tested ChatGPT through exit-node, response renders normally in Firefox. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -146,9 +146,20 @@ export default async function (req: Request): Promise<Response> {
|
|||||||
redirect: "manual",
|
redirect: "manual",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// `fetch()` (Deno / Bun / Node) auto-decompresses gzip / br / deflate
|
||||||
|
// responses, so `resp.arrayBuffer()` returns plain bytes — but the
|
||||||
|
// destination's `Content-Encoding` header is still on `resp.headers`.
|
||||||
|
// Forwarding it would tell the client browser "this body is gzipped"
|
||||||
|
// when it isn't, producing `Content Encoding Error` (#964). Same goes
|
||||||
|
// for `Content-Length` — the post-decompression byte count is
|
||||||
|
// different from what the destination announced. Strip both. The
|
||||||
|
// Apps Script + Rust transport layer below us re-frames the wire body
|
||||||
|
// anyway, so neither header is meaningful to forward.
|
||||||
const data = new Uint8Array(await resp.arrayBuffer());
|
const data = new Uint8Array(await resp.arrayBuffer());
|
||||||
const respHeaders: Record<string, string> = {};
|
const respHeaders: Record<string, string> = {};
|
||||||
resp.headers.forEach((value, key) => {
|
resp.headers.forEach((value, key) => {
|
||||||
|
const lower = key.toLowerCase();
|
||||||
|
if (lower === "content-encoding" || lower === "content-length") return;
|
||||||
respHeaders[key] = value;
|
respHeaders[key] = value;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user