@arraypress/hono-utils
v1.0.0
Published
Small Hono context helpers — client IP resolution with opt-in proxy trust, absolute URL building from the request's origin, and origin extraction. The glue every Workers/Hono app reinvents.
Maintainers
Readme
@arraypress/hono-utils
Three small Hono context helpers that every Workers/Hono app reinvents.
Install
npm install @arraypress/hono-utilsUsage
import { getClientIP, getOrigin, buildUrl } from '@arraypress/hono-utils';
app.post('/api/whatever', async (c) => {
const ip = getClientIP(c); // '203.0.113.5'
const origin = getOrigin(c); // 'https://store.com'
const verifyLink = buildUrl(c, '/verify', { token });
// ...
});Exports
getClientIP(c): string
Resolves the client IP with opt-in proxy-header trust:
CF-Connecting-IP— always trusted (Cloudflare edge sets it; origin code can't forge).X-Real-IP/X-Forwarded-For— only consulted whenTRUST_PROXY_HEADERS=1is set onc.env.
Returns '' when no trustworthy header is present. Callers decide whether to refuse the request or proceed without an IP (used by rate limiters, blocklists, audit logs).
Never trust proxy headers by default. A spoofed X-Forwarded-For would otherwise bypass every IP-based control. Set TRUST_PROXY_HEADERS=1 only when you control the proxy hop (Vercel behind their infra, nginx you operate) AND it strips client-supplied values before forwarding.
getOrigin(c): string
Returns protocol://host of the current request. No trailing slash. For composing absolute URLs to hand back to users.
buildUrl(c, path, params?): string
Absolute URL rooted at the current request's origin. Query params URL-encoded. Works across multiple domains (preview deployments, staging, custom domains) without configuration — the origin is read from the request, not from env.
buildUrl(c, '/account/verify', { token: 'abc 123' });
// → 'https://store.com/account/verify?token=abc+123'Why these live together
All three read from c.req.url + headers; all three are used in every route that composes absolute links or enforces per-IP limits. Splitting into three packages would just mean three import lines per route for no benefit.
License
MIT
