/** * Abort-complete HTTP transport for decision providers. * * The global `fetch` cannot be trusted with a sub-second, one-shot CLI * budget: aborting it rejects the promise, but a request still in its CONNECT * phase keeps its handle — `TCPConnectWrap` for an unanswered SYN, the TLS * socket for a stalled handshake, `GetAddrInfoReqWrap` for a slow DNS lookup * on the libuv threadpool. The CLI's success path relies on the event loop * draining, so each of those kept `cleo add` alive until the 3 s teardown * backstop (measured 4.4 s end to end, T12492). * * This transport owns every handle it creates, and releases all of them when * the signal fires: * * - DNS goes through a dedicated `dns.Resolver` (c-ares) whose `cancel()` * ends in-flight queries. IP literals skip DNS; `localhost` and other * hosts-file names are answered from the hosts file, in file order. * - `.local` (mDNS) names are refused outright unless the hosts file maps * them: c-ares answers NXDOMAIN, and the system resolver would then wait * seconds on multicast, uncancellably. * - When c-ares cannot answer (NXDOMAIN, SERVFAIL, REFUSED, timeout — e.g. a * VPN's split DNS that only the system resolver knows), `dns.lookup` is the * fallback. It is the ONE step that cannot be cancelled: a hung * `getaddrinfo` holds the process until it returns. That residual risk is * disclosed in the T12492 changeset. * - Every resolved address is tried in order (IPv4 first, then IPv6) until a * connection is made; a refused or unreachable address moves on to the next. * - Requests use `agent: false` — no pooled keep-alive socket survives the * call — and `req.destroy()` on abort tears down a socket in any phase. * - TLS verifies the certificate against the ORIGINAL hostname * (`servername`), not the resolved address. * - Every listener converts a throw into a rejection: a response the WHATWG * `Response` cannot represent (status outside 200–599) is a rejected call, * never an uncaught exception that kills the CLI mid-write. * - The transport never consults `HTTPS_PROXY` / `NODE_USE_ENV_PROXY`. * * Provider-neutral: it knows no endpoint paths or wire shapes. * * @task T12492 */ /** Request options accepted by {@link decideFetch}. */ export interface DecideFetchInit { /** HTTP method. */ readonly method: 'GET' | 'POST'; /** Request headers. */ readonly headers: Readonly>; /** Request body. */ readonly body?: string; /** Cancels DNS, connect, request and response; every handle is released. */ readonly signal: AbortSignal; } /** Signature of {@link decideFetch}; `globalThis.fetch` satisfies it too (tests inject stubs). */ export type DecideFetch = (url: string, init: DecideFetchInit) => Promise; /** * Perform one HTTP(S) request and buffer the response. * * Rejects — never throws out of a callback — on abort, on any network or * protocol failure, and on a status outside 200–599. By the time an abort * rejects, the DNS query, socket and request have been destroyed (except a * system-resolver fallback already in flight; see the module docs). * * @param url - Absolute `http:` or `https:` URL. * @param init - Method, headers, body and the (required) abort signal. * @returns The buffered response. */ export declare function decideFetch(url: string, init: DecideFetchInit): Promise; //# sourceMappingURL=transport.d.ts.map