/** * Where the abandon deadline starts. `first-byte` puts the cut mid-stream * whatever the route's latency; `request` puts it before the response exists, * which is a different leak path and not reachable from the other origin. */ export type AbandonOrigin = "first-byte" | "request"; export type AbandonPhaseOptions = { url: string; amount: number; connections: number; /** Destroy the socket this many ms after the origin below. */ abandonAfterMs: number; /** Defaults to `first-byte`. */ abandonFrom?: AbandonOrigin; headers?: Record; }; export type AbandonPhaseResult = { sent: number; abandoned: number; /** * Abandonments where the server had already started responding. Only these * exercise mid-stream teardown; cutting before the first byte tests a * different path (the server may never have begun rendering). */ abandonedMidStream: number; /** Abandonments where the first-byte budget expired in silence. */ abandonedBeforeResponse: number; completed: number; errors: number; }; /** * Sends requests and hangs up before the response arrives. * * autocannon cannot express this: its `timeout` is in whole seconds, so * against a route answering in milliseconds nothing is ever abandoned. Yet * several real leaks live exactly on that path — vercel/next.js#89091 traces * `ServerResponse` retention to an early disconnect, which only happens when * a client goes away mid-flight (closed tabs, load-balancer timeouts, bots). * * Raw sockets keep this honest: write the request, wait for the response to * start, then wait `abandonAfterMs` and destroy the socket mid-stream. With * `abandonFrom: "request"` the wait starts at the write instead, which is the * only way to cut a route that has not begun answering yet. */ export declare function runAbandonPhase(options: AbandonPhaseOptions): Promise;