From 396acf3bbbe00a192cb0ea0a9ccf91b1d8d2850b Mon Sep 17 00:00:00 2001 From: Fuwn <50817549+Fuwn@users.noreply.github.com> Date: Sat, 24 Jan 2026 13:09:50 +0000 Subject: Initial commit Created from https://vercel.com/new --- src/lib/ip.ts | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 src/lib/ip.ts (limited to 'src/lib/ip.ts') diff --git a/src/lib/ip.ts b/src/lib/ip.ts new file mode 100644 index 0000000..5cd7757 --- /dev/null +++ b/src/lib/ip.ts @@ -0,0 +1,60 @@ +export const IP_ADDRESS_HEADERS = [ + 'true-client-ip', // CDN + 'cf-connecting-ip', // Cloudflare + 'fastly-client-ip', // Fastly + 'x-nf-client-connection-ip', // Netlify + 'do-connecting-ip', // Digital Ocean + 'x-real-ip', // Reverse proxy + 'x-appengine-user-ip', // Google App Engine + 'x-forwarded-for', + 'forwarded', + 'x-client-ip', + 'x-cluster-client-ip', + 'x-forwarded', +]; + +export function getIpAddress(headers: Headers) { + const customHeader = process.env.CLIENT_IP_HEADER; + + if (customHeader && headers.get(customHeader)) { + return headers.get(customHeader); + } + + const header = IP_ADDRESS_HEADERS.find(name => { + return headers.get(name); + }); + + const ip = headers.get(header); + + if (header === 'x-forwarded-for') { + return ip?.split(',')?.[0]?.trim(); + } + + if (header === 'forwarded') { + const match = ip.match(/for=(\[?[0-9a-fA-F:.]+\]?)/); + + if (match) { + return match[1]; + } + } + + return ip; +} + +export function stripPort(ip: string) { + if (ip.startsWith('[')) { + const endBracket = ip.indexOf(']'); + if (endBracket !== -1) { + return ip.slice(0, endBracket + 1); + } + } + + const idx = ip.lastIndexOf(':'); + if (idx !== -1) { + if (ip.includes('.') || /^[a-zA-Z0-9.-]+$/.test(ip.slice(0, idx))) { + return ip.slice(0, idx); + } + } + + return ip; +} -- cgit v1.2.3