/** * Header reading for the device API. * * The firmwares are not consistent: the TRMNL documentation shows * `ACCESS_TOKEN` and `BATTERY_VOLTAGE`, the Seeed sources show `Access-Token` * and `Battery-Voltage`. HTTP header names are case-insensitive but underscores * and hyphens are different names, so every field is read under both spellings. * Being liberal here costs nothing; being wrong costs a blank shop window. */ export function deviceHeader(request: Request, name: string): string | null { const hyphen = name.replace(/_/g, '-'); const underscore = name.replace(/-/g, '_'); return request.headers.get(hyphen) ?? request.headers.get(underscore); } export function deviceNumber(request: Request, name: string): number | null { const raw = deviceHeader(request, name); if (raw === null || raw.trim() === '') { return null; } const value = Number(raw); return Number.isFinite(value) ? value : null; } /** The caller's address, as seen through whatever proxy is in front of us. */ export function clientIp(request: Request): string { const forwarded = request.headers.get('x-forwarded-for'); if (forwarded) { return forwarded.split(',')[0]?.trim() ?? 'unknown'; } return request.headers.get('x-real-ip') ?? 'unknown'; }