http/ip_canonical.ts view source
(ip: string): string Canonicalize an IP address string.
Returns the RFC 5952 canonical form for parseable IPv4 or IPv6
input. Returns the input unchanged (only lowercased) when the input
is non-IP ('unknown'), malformed ('attacker:controlled',
'::1\n'), or any string the strict char-set filter rejects.
Idempotent. canonicalize_ip(canonicalize_ip(x)) === canonicalize_ip(x)
for every input.
Order-safe for IPv4-mapped IPv6. The ::ffff: prefix strip
runs AFTER the canonical emit because the canonical form of an
IPv4-mapped IPv6 address is the dotted form (::ffff:127.0.0.1,
not ::ffff:7f00:1). Stripping before canonicalize would miss the
full-hex form. Closes the
normalize_ipv4_mapped_collapse_is_order_safe test from the Rust
port.
ip
stringreturns
string examples
canonicalize_ip('::0001') // โ '::1' canonicalize_ip('0:0:0:0:0:0:0:1') // โ '::1' canonicalize_ip('2001:0DB8::0001') // โ '2001:db8::1' canonicalize_ip('::ffff:127.0.0.1') // โ '127.0.0.1' canonicalize_ip('0:0:0:0:0:ffff:7f00:1') // โ '127.0.0.1' canonicalize_ip('::ffff:1') // โ '::ffff:1' (NOT IPv4-mapped โ group[5] is 0, not ffff) canonicalize_ip('127.0.0.1') // โ '127.0.0.1' canonicalize_ip('not-an-ip') // โ 'not-an-ip' (passes through) canonicalize_ip('::1\n') // โ '::1\n' (fails char-set; passes through) canonicalize_ip('203.0.113.1:8080') // โ '203.0.113.1:8080' (passes through; validate_ip_strict rejects)