Ctrl K
ComunidadGuías…

server/body-deadline.ts

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
import { userError } from "./user-errors.ts";
import type { IncomingMessage, ServerResponse } from "node:http";

export const BODY_DEADLINE_MS = 55_000;
/** The slowest upload still let through: past this pace a large body is cut off, never held open. */
const MIN_BODY_BYTES_PER_SECOND = 128 * 1024;
const UNKNOWN_LENGTH_BYTES = 32 * 1024 * 1024;
const TIMED_OUT_BODY = JSON.stringify({ ...userError("serverError.request.bodyTimeout") });
const TIMED_OUT = `HTTP/1.1 408 Request Timeout\r\nConnection: close\r\nContent-Type: application/json\r\nContent-Length: ${Buffer.byteLength(TIMED_OUT_BODY)}\r\n\r\n${TIMED_OUT_BODY}`;

/** Ends a request whose body has not all arrived in time, as Node's own `requestTimeout` does: a 408 written on the
 * socket, then the connection closed. A request without a body (a stream, a long poll) is never timed. */
export function holdBodyDeadline(req: IncomingMessage, res: ServerResponse, baseMs = BODY_DEADLINE_MS): void {
  const declared = Number(req.headers["content-length"] ?? 0);
  const chunked = req.headers["transfer-encoding"] !== undefined;
  if (req.complete || (!chunked && !(declared > 0))) return;
  const bytes = chunked ? UNKNOWN_LENGTH_BYTES : declared;
  const timer = setTimeout(() => {
    if (req.complete) return;
    const socket = req.socket;
    if (!res.headersSent && socket.writable) socket.end(TIMED_OUT, () => socket.destroy());
    else socket.destroy();
  }, baseMs + Math.ceil((bytes / MIN_BODY_BYTES_PER_SECOND) * 1000));
  timer.unref();
  req.once("end", () => clearTimeout(timer));
  req.once("close", () => clearTimeout(timer));
}