/// <reference types="node" />
import { URL } from "url";
import { BaseError } from "make-error-cause";
import { Socket, NetConnectOpts } from "net";
import { SecureContext, TLSSocket, ConnectionOptions as TlsConnectOpts } from "tls";
import { ClientHttp2Session } from "http2";
import { LookupOptions } from "dns";
import { Request, Response, CreateBody, ResponseOptions } from "servie/dist/node";
/**
 * Add HTTP signals to servie events.
 */
declare module "servie/dist/signal" {
    interface SignalEvents {
        error: [Error];
    }
}
/**
 * Address information from the HTTP request.
 */
export interface Connection {
    localPort: number;
    localAddress: string;
    remotePort: number;
    remoteAddress: string;
    encrypted: boolean;
}
/**
 * Extend response with URL.
 */
export interface HttpResponseOptions extends ResponseOptions {
    url: string;
    connection: Connection;
    httpVersion: string;
}
/**
 * HTTP responses implement a node.js body.
 */
export declare class HttpResponse extends Response implements HttpResponseOptions {
    url: string;
    httpVersion: string;
    connection: Connection;
    constructor(body: CreateBody, options: HttpResponseOptions);
}
export declare class Http2Response extends HttpResponse {
}
/**
 * Abstract connection manager.
 */
export interface ConnectionManager<T> {
    /**
     * Request a connection and initialize in `onReady` once available.
     */
    ready(key: string, onReady: (connection: T | undefined) => T | Promise<T>): Promise<T>;
    /**
     * Create a connection within the `create` callback for tracking.
     */
    creating(key: string, create: () => Promise<T>): Promise<T>;
    /**
     * Claims an existing connection as "in-use".
     */
    used(key: string, connection: T): void;
    /**
     * Removes a connection from "in-use" using the connection key and connection.
     * Return `true` when the connection has been deleted from the manager and the
     * connection must be destroyed.
     */
    freed(key: string, connection: T): boolean;
    /**
     * Gets any connection (or `undefined` when none exist) using the connection key.
     */
    get(key: string): T | undefined;
    /**
     * Gets a free connection (or `undefined` if none are free) using the connection key.
     */
    free(key: string): T | undefined;
    /**
     * Deletes a connection from free and in-use using the connection key.
     */
    delete(key: string, connection: T): void;
}
/**
 * Set of connections for HTTP pooling.
 */
export declare class SocketSet<T> {
    creating: number;
    free: Set<T>;
    sockets: Set<T>;
    pending: Array<(connection: T | undefined) => void>;
    size(): number;
    isEmpty(): boolean;
}
/**
 * Manage socket reuse.
 */
export declare class SocketConnectionManager<T extends Socket | TLSSocket> implements ConnectionManager<T> {
    maxFreeConnections: number;
    maxConnections: number;
    pools: Map<string, SocketSet<T>>;
    constructor(maxFreeConnections?: number, maxConnections?: number);
    /**
     * Creates a connection when available.
     */
    ready(key: string, onReady: (connection: T | undefined) => T | Promise<T>): Promise<T>;
    creating(key: string, onCreate: () => Promise<T>): Promise<T>;
    pool(key: string): SocketSet<T>;
    used(key: string, socket: T): void;
    freed(key: string, socket: T): boolean;
    private _delete;
    get(key: string): T | undefined;
    free(key: string): T | undefined;
    delete(key: string, socket: T): void;
}
export declare class Http2ConnectionManager implements ConnectionManager<ClientHttp2Session> {
    sessions: Map<string, ClientHttp2Session>;
    refs: WeakMap<ClientHttp2Session, number>;
    ready(key: string, onReady: (session: ClientHttp2Session | undefined) => ClientHttp2Session | Promise<ClientHttp2Session>): Promise<ClientHttp2Session>;
    creating(key: string, create: () => Promise<ClientHttp2Session>): Promise<ClientHttp2Session>;
    used(key: string, session: ClientHttp2Session): void;
    freed(key: string, session: ClientHttp2Session): boolean;
    get(key: string): ClientHttp2Session | undefined;
    free(key: string): ClientHttp2Session | undefined;
    delete(key: string, session: ClientHttp2Session): void;
}
export declare const defaultNetConnect: CreateNetConnection;
export declare const defaultTlsConnect: CreateTlsConnection;
export declare const defaultHttp2Connect: CreateHttp2Connection;
/**
 * Used as a cause for the connection error.
 */
export declare class CausedByEarlyCloseError extends Error {
    constructor();
}
/**
 * Used as a cause for the connection error.
 */
export declare class CausedByTimeoutError extends Error {
    constructor();
}
/**
 * Expose connection errors.
 */
export declare class ConnectionError extends BaseError {
    request: Request;
    code: string;
    constructor(request: Request, message: string, cause: Error);
}
/**
 * ALPN validation error.
 */
export declare class ALPNError extends Error {
    request: Request;
    code: string;
    constructor(request: Request, message: string);
}
/**
 * Configure HTTP version negotiation.
 */
export declare enum NegotiateHttpVersion {
    HTTP1_ONLY = 0,
    HTTP2_FOR_HTTPS = 1,
    HTTP2_ONLY = 2
}
export declare type CreateNetConnection = (options: NetConnectOpts) => Socket | Promise<Socket>;
export declare type CreateTlsConnection = (options: TlsConnectOpts) => TLSSocket | Promise<TLSSocket>;
export declare type CreateHttp2Connection = (authority: URL, socket: Socket | TLSSocket) => ClientHttp2Session | Promise<ClientHttp2Session>;
export declare type LookupFunction = (hostname: string, options: LookupOptions, callback: (err: Error | null, address: string, family: number) => void) => void;
/**
 * Node.js HTTP request options.
 */
export interface TransportOptions {
    keepAlive?: number;
    idleSocketTimeout?: number;
    idleRequestTimeout?: number;
    servername?: string;
    rejectUnauthorized?: boolean;
    negotiateHttpVersion?: NegotiateHttpVersion;
    ca?: string | Buffer | Array<string | Buffer>;
    cert?: string | Buffer;
    key?: string | Buffer;
    secureContext?: SecureContext;
    secureProtocol?: string;
    secureOptions?: number;
    tlsSockets?: ConnectionManager<TLSSocket>;
    netSockets?: ConnectionManager<Socket>;
    http2Sessions?: ConnectionManager<ClientHttp2Session>;
    lookup?: LookupFunction;
    createHttp2Connection?: CreateHttp2Connection;
    createNetConnection?: CreateNetConnection;
    createTlsConnection?: CreateTlsConnection;
}
/**
 * Custom abort error instance.
 */
export declare class AbortError extends Error {
    request: Request;
    code: string;
    constructor(request: Request, message: string);
}
/**
 * Forward request over HTTP1/1 or HTTP2, with TLS support.
 */
export declare function transport(options?: TransportOptions): (req: Request, next: () => Promise<Response>) => Promise<Response>;
