import type { Context } from "hono"; import { getConnInfo } from "hono/bun"; /** * Best-effort client IP. * Prefer x-forwarded-for (set when behind a proxy), fall back to the raw socket * address from Bun. In local dev (frontend:5173 → backend:3000, no proxy) this * is typically 127.0.0.1 / ::1. */ export function getClientIp(c: Context): string { const fwd = c.req.header("x-forwarded-for"); if (fwd) { const first = fwd.split(",")[0]?.trim(); if (first) return first; } try { const addr = getConnInfo(c).remote.address; if (addr) return addr; } catch { /* getConnInfo only works under the Bun adapter */ } return "127.0.0.1"; } /** * Is this IP the local machine? Drives the README rule "si localhost: pas de * paywall (tout gratuit)". Covers IPv4 loopback, IPv6 loopback, and the * IPv4-mapped-IPv6 form Bun sometimes reports. */ export function isLocalhost(ip: string): boolean { return ( ip === "127.0.0.1" || ip === "::1" || ip === "::ffff:127.0.0.1" || ip === "localhost" || ip.startsWith("127.") ); }