feat(health): local icon cache /api/icons/:slug.png (no CDN leak)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
31
lib/health/icons.js
Normal file
31
lib/health/icons.js
Normal file
@@ -0,0 +1,31 @@
|
||||
import { mkdir, readFile, writeFile } from 'node:fs/promises';
|
||||
import path from 'node:path';
|
||||
|
||||
let cacheDir = process.env.ICON_CACHE || '/var/lib/void/icons';
|
||||
let fetcher = defaultFetcher;
|
||||
export function _setCacheDir(d) { cacheDir = d; }
|
||||
export function _setFetcher(fn) { fetcher = fn || defaultFetcher; }
|
||||
|
||||
const VALID = /^[a-z0-9-]+$/;
|
||||
export function validSlug(slug) { return VALID.test(slug); }
|
||||
|
||||
async function defaultFetcher(slug) {
|
||||
const url = `https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons/png/${slug}.png`;
|
||||
const res = await fetch(url, { signal: AbortSignal.timeout(8000) });
|
||||
if (!res.ok) return null;
|
||||
return Buffer.from(await res.arrayBuffer());
|
||||
}
|
||||
|
||||
function isPng(buf) { return buf && buf.length > 8 && buf[0] === 0x89 && buf[1] === 0x50 && buf[2] === 0x4e && buf[3] === 0x47; }
|
||||
|
||||
// Returns a Buffer (cached or freshly fetched) or null if upstream has no icon.
|
||||
export async function getIcon(slug) {
|
||||
if (!validSlug(slug)) throw new Error('invalid slug');
|
||||
const file = path.join(cacheDir, `${slug}.png`);
|
||||
try { return await readFile(file); } catch { /* miss → fetch */ }
|
||||
const buf = await fetcher(slug);
|
||||
if (!isPng(buf)) return null;
|
||||
await mkdir(cacheDir, { recursive: true });
|
||||
await writeFile(file, buf);
|
||||
return buf;
|
||||
}
|
||||
Reference in New Issue
Block a user