Fix FS drops connection if download is too slow

Only happens in HTTPS because seemingly somewhere in the stack up to
50mb of data is being buffered potentially triggering a timeout at a
higher level if not drained fast enough.

This commit also includes other streams related improvements.
This commit is contained in:
Zaid Abdulla committed 2022-11-01 09:13:36 -07:00
1 parent d53e10f62d
commit d1c01e0848
3 files changed
+48 -50

No files matched your search

+17 -30
View File
@@ -48,7 +48,7 @@ import {
CpeFault,
} from "./types";
import { IncomingMessage, ServerResponse } from "http";
import { Readable } from "stream";
import { pipeline, Readable } from "stream";
import { promisify } from "util";
import { decode, encodingExists } from "iconv-lite";
import { parseXmlDeclaration } from "./xml-parser";
@@ -1451,10 +1451,14 @@ async function listenerAsync(
if (httpRequest.headers["content-encoding"]) {
switch (httpRequest.headers["content-encoding"]) {
case "gzip":
stream = httpRequest.pipe(zlib.createGunzip());
stream = pipeline(stream, zlib.createGunzip(), () => {
// Errors are also raised by the async iterator
});
break;
case "deflate":
stream = httpRequest.pipe(zlib.createInflate());
stream = pipeline(stream, zlib.createInflate(), () => {
// Errors are also raised by the async iterator
});
break;
default:
httpResponse.writeHead(415, { Connection: "close" });
@@ -1463,34 +1467,17 @@ async function listenerAsync(
}
}
const body = await new Promise<Buffer>((resolve, reject) => {
const chunks: Buffer[] = [];
let bytes = 0;
const chunks: Buffer[] = [];
try {
for await (const chunk of stream) chunks.push(chunk);
// In Node versions prior to 15, the stream will not emit an error if the
// connection is closed before the stream is finished.
if (!stream.readableEnded) throw new Error("Connection closed");
} catch (err) {
return;
}
stream.on("data", (chunk) => {
chunks.push(chunk);
bytes += chunk.length;
});
stream.on("end", () => {
const _body = Buffer.allocUnsafe(bytes);
let offset = 0;
for (const chunk of chunks) {
chunk.copy(_body, offset, 0, chunk.length);
offset += chunk.length;
}
resolve(_body);
});
stream.on("error", reject);
httpRequest.on("aborted", () => {
resolve(null);
});
});
// Request aborted
if (!body) return;
const body = Buffer.concat(chunks);
let sessionContext = currentSessions.get(httpRequest.socket);