/** * `Capture` — pure observation builder for a single `web.fetch` invocation. * The transport in `fetch-core.ts` feeds it DNS/TCP/TLS/header/redirect/ * cookie events; it accumulates them into the {@link WebFetchMetadata} * fields (timing, TLS info, headers, redirect chain, resolved IP/hostname, * cookies — each capped, see MAX_REDIRECT_HOPS/MAX_COOKIES_CAPTURED). * * Only the last hop's timing/DNS/TLS values are kept on redirect. No I/O * happens here — it's a pure data sink so the transport layer can be * tested independently. Redaction and the 64 KiB metadata budget are * applied later by `redact.ts` / `budget.ts`. */ import type { IncomingHttpHeaders } from "node:http"; import type { TLSSocket } from "node:tls"; import { type CookieInfo, type HeaderMap, type RedirectChain, type TimingInfo, type TlsInfo } from "./types.js"; /** * Snapshot of the structured fields the builder has accumulated when * `fetch-core.ts` finalises the response. The shape matches the slice of * {@link WebFetchMetadata} that depends on per-hop transport * observation; the fetch handler combines this with `requestedUrl`, * `finalUrl`, `mode`, `bytesReceived`, `truncated`, etc. before applying * `redact.applyToHeaders` / `redact.applyToCookies` and `budget.enforce`. */ export interface CapturedFields { resolvedIp: string; finalHostname: string; status: number; headers: HeaderMap; tls?: TlsInfo; timing: TimingInfo; redirectChain: RedirectChain; cookies: CookieInfo[]; } export declare class Capture { private dnsMs; private tcpMs; private tlsMs; private ttfbMs; private resolvedIp; private finalHostname; private status; private headers; private tls; private readonly redirectChain; private readonly cookies; private readonly isHttps; constructor(opts: { isHttps: boolean; finalHostname?: string; }); setHopContext(hostname: string): void; markDnsResolved(ms: number, ip: string): void; markTcpConnected(ms: number): void; markTlsHandshaked(ms: number, socket: TLSSocket): void; /** * Record the final-hop response: HTTP status, raw headers * (lowercased and joined into a {@link HeaderMap}), and TTFB. * * `Set-Cookie` is preserved in `headers` joined with `, ` like every * other repeated header so the audit/redact passes can act on it. * Per-cookie capture happens via {@link addSetCookieHeader}, which * `fetch-core.ts` calls once per `Set-Cookie` line observed. */ markResponse(status: number, rawHeaders: IncomingHttpHeaders, ttfbMs: number): void; addRedirectHop(url: string, status: number, location?: string): void; addSetCookieHeader(value: string): void; finalize(totalMs: number): CapturedFields; }