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:
1 parent
d53e10f62d
commit
d1c01e0848
3 files changed
+48
-50
No files matched your search
+17
-30
@@ -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);
|
||||
|
||||
|
||||
Reference in new issue
Block a user