UNPKG

@arcjet/ip

Version:

Arcjet utilities for finding the originating IP of a request

184 lines (183 loc) 4.93 kB
import { CloudflareOptions, cloudflare } from "./cloudflare.js"; //#region src/index.d.ts type Ipv4Tuple = [number, number, number, number]; type Ipv6Tuple = [number, number, number, number, number, number, number, number]; declare class Ipv4Cidr { type: "v4"; partSize: 8; parts: Readonly<Ipv4Tuple>; bits: number; constructor(parts: Ipv4Tuple, bits: number); contains(ip: Array<number>): boolean; } declare class Ipv6Cidr { type: "v6"; partSize: 16; parts: Readonly<Ipv6Tuple>; bits: number; constructor(parts: Ipv6Tuple, bits: number); contains(ip: Array<number>): boolean; } /** * Parse CIDR addresses and keep non-CIDR IP addresses. * * @param value * Value to parse. * @returns * Parsed {@linkcode Cidr} if range or given `value` if IP. */ declare function parseProxy(value: string): string | Cidr; /** * Parse a list of trusted proxies. * * CIDR range strings are parsed to {@linkcode Cidr} (so they match by range); * plain IP strings and {@linkcode ProxyService} objects (such as those created * by {@linkcode cloudflare}) are passed through unchanged. Use this to * normalize the `proxies` option before handing it to {@linkcode findIp}. * * @param proxies * Trusted proxies to parse. * @returns * Parsed proxies. */ declare function parseProxies(proxies: ReadonlyArray<string | ProxyService>): Array<string | Cidr | ProxyService>; /** * Socket-like interface. */ interface PartialSocket { remoteAddress?: string | null | undefined; } /** * Interface that looks like info. */ interface PartialInfo { remoteAddress?: string | null | undefined; } interface PartialIdentiy { sourceIp?: string | null | undefined; } /** * Interface that looks like a request context. */ interface PartialRequestContext { identity?: PartialIdentiy | null | undefined; } /** * Interface with `headers`. */ type HeaderLike = { /** * Headers. */ headers: Headers | Record<string, string[] | string | undefined>; }; /** * Interface that looks like a request, * of which `headers` is required and several other fields may exist. */ type RequestLike = { /** * Some platforms pass `info`. */ info?: PartialInfo | null | undefined; /** * Some platforms such as Cloudflare and Vercel provide `ip` directly on * `request`. */ ip?: unknown; /** * Some platforms pass info in `requestContext`. */ requestContext?: PartialRequestContext | null | undefined; /** * Some platforms pass a `socket`. */ socket?: PartialSocket | null | undefined; } & HeaderLike; /** * Platform name. */ type Platform = "cloudflare" | "firebase" | "fly-io" | "render" | "vercel"; /** * Format of a client IP header set by a proxy service. * * - `"ip"` — a single IP address (e.g. `CF-Connecting-IP`). * - `"ips"` — an `X-Forwarded-For`-style comma separated list, parsed * tail-to-head. */ type ClientIpFormat = "ip" | "ips"; /** * A client IP header set by a proxy service. */ interface ClientIpHeader { /** * Header name (lower-case). */ header: string; /** * How to parse the header value. */ format: ClientIpFormat; } /** * A trusted proxy service (such as Cloudflare) sitting in front of the * application. * * Identified by IP range, with the header(s) that carry the real client IP. * Create one with a helper such as {@linkcode cloudflare} and include it in the * `proxies` array. */ interface ProxyService { /** * Discriminant marking this entry as a proxy service. */ kind: "service"; /** * Name of the service (such as `"cloudflare"`). */ name: string; /** * IP addresses and CIDR ranges that identify this service. */ ranges: ReadonlyArray<string | Cidr>; /** * Header(s) this service uses to relay the real client IP, in priority order. */ clientIp: ReadonlyArray<ClientIpHeader>; } /** * Configuration. */ interface Options { /** * Platform the code is running on; * used to allow only known more trustworthy headers. */ platform?: Platform | null | undefined; /** * Trusted proxies. * * IP addresses and CIDR ranges are treated as trusted load balancers or * proxies and skipped when finding the client IP. Proxy services created with * a helper such as {@linkcode cloudflare} additionally declare which header * carries the real client IP. */ proxies?: ReadonlyArray<string | Cidr | ProxyService> | null | undefined; } /** * Find a client IP address on a request-like object. * * @param request * Request-like object. * @param [options] * Configuration (optional). * @returns * Found IP address; empty string if not found. */ declare function findIp(request: RequestLike, options?: Options | null | undefined): string; /** * One of the CIDR ranges. */ type Cidr = Ipv4Cidr | Ipv6Cidr; //#endregion export { Cidr, ClientIpFormat, ClientIpHeader, type CloudflareOptions, HeaderLike, Options, Platform, ProxyService, RequestLike, cloudflare, findIp as default, findIp, parseProxies, parseProxy };