114 lines
8.8 KiB
JavaScript
114 lines
8.8 KiB
JavaScript
import fs from 'fs';
|
|
import path from 'path';
|
|
import { analyticsEmitter } from '../lib/analytics-emitter.js';
|
|
// import { isBotRequest, isAIRequest } from '../products/serving/bots.js';
|
|
const ANALYTICS_FILE = path.resolve(process.cwd(), 'logs/analytics.jsonl');
|
|
// Extensions to ignore
|
|
const IGNORED_EXTENSIONS = new Set([
|
|
'.js', '.css', '.png', '.jpg', '.jpeg', '.gif', '.ico', '.svg', '.woff', '.woff2', '.ttf', '.eot', '.map'
|
|
]);
|
|
export const REVERSE_DEFAULT = { continent: 'unknown', countryName: 'unknown', city: 'unknown' };
|
|
const GEO_CACHE_FILE = path.resolve(process.cwd(), 'cache/geoip.json');
|
|
// Simple in-memory cache to reduce disk I/O, initialized on first use
|
|
let geoCache = null;
|
|
const loadGeoCache = () => {
|
|
if (geoCache)
|
|
return geoCache;
|
|
try {
|
|
if (fs.existsSync(GEO_CACHE_FILE)) {
|
|
const data = fs.readFileSync(GEO_CACHE_FILE, 'utf-8');
|
|
geoCache = JSON.parse(data);
|
|
}
|
|
else {
|
|
geoCache = {};
|
|
}
|
|
}
|
|
catch (e) {
|
|
console.error('Error loading geo cache', e);
|
|
geoCache = {};
|
|
}
|
|
return geoCache;
|
|
};
|
|
const saveGeoCache = (ip, data) => {
|
|
if (!geoCache)
|
|
geoCache = {};
|
|
geoCache[ip] = data;
|
|
// Ensure directory exists
|
|
const dir = path.dirname(GEO_CACHE_FILE);
|
|
if (!fs.existsSync(dir)) {
|
|
fs.mkdirSync(dir, { recursive: true });
|
|
}
|
|
// Write to file (async to not block)
|
|
fs.promises.writeFile(GEO_CACHE_FILE, JSON.stringify(geoCache, null, 2)).catch(err => {
|
|
console.error('Error saving geo cache', err);
|
|
});
|
|
};
|
|
export const reverse = async (ip, opts) => {
|
|
return REVERSE_DEFAULT;
|
|
/*
|
|
const cache = loadGeoCache();
|
|
if (cache && cache[ip]) {
|
|
return cache[ip];
|
|
}
|
|
|
|
const config = CONFIG_DEFAULT() as any
|
|
try {
|
|
const q = `https://api-bdc.net/data/ip-geolocation?ip=${ip}&localityLanguage=en&key=${config.bigdata.key}`
|
|
const ret = await axios.get(q) || { data: REVERSE_DEFAULT }
|
|
const data = ret.data || REVERSE_DEFAULT
|
|
saveGeoCache(ip, data);
|
|
return data;
|
|
} catch (e: any) {
|
|
logger.error('Error reverse geocoding', e.message)
|
|
return REVERSE_DEFAULT
|
|
}
|
|
*/
|
|
};
|
|
export async function analyticsMiddleware(c, next) {
|
|
await next(); // Execute the request first (non-blocking for the response?)
|
|
// Wait, "await next()" blocks the middleware until the downstream handlers finish.
|
|
// If we want to capture the status code, we need to wait.
|
|
// The user asked for "non blocking analytics middleware".
|
|
// Usually this means the *write* operation shouldn't block the response.
|
|
// So we can do the logging logic *after* `await next()`, but ensuring the file write is not awaited or is fire-and-forget.
|
|
try {
|
|
const url = new URL(c.req.url);
|
|
const pathname = url.pathname;
|
|
const extension = path.extname(pathname).toLowerCase();
|
|
// Filter static assets
|
|
if (IGNORED_EXTENSIONS.has(extension)) {
|
|
return;
|
|
}
|
|
// Additional check for common static paths if they don't have extensions
|
|
if (pathname.startsWith('/assets/') || pathname.startsWith('/static/')) {
|
|
return;
|
|
}
|
|
const ip = c.req.header('x-forwarded-for') || c.req.header('cf-connecting-ip') || '92.176.215.140';
|
|
const geo = REVERSE_DEFAULT; // || ip !== 'unknown' ? await reverse(ip, CONFIG_DEFAULT()) : REVERSE_DEFAULT
|
|
const userAgent = c.req.header('user-agent');
|
|
const entry = {
|
|
timestamp: new Date().toISOString(),
|
|
method: c.req.method,
|
|
path: pathname,
|
|
status: c.res.status,
|
|
ip,
|
|
userAgent,
|
|
// isBot: isBotRequest(userAgent),
|
|
// isAI: isAIRequest(userAgent),
|
|
referer: c.req.header('referer'),
|
|
userId: c.get('userId'),
|
|
geo
|
|
};
|
|
const line = JSON.stringify(entry) + '\n';
|
|
// Emit event for real-time streaming
|
|
analyticsEmitter.emit('log', entry);
|
|
// Fire and forget write
|
|
fs.promises.appendFile(ANALYTICS_FILE, line).catch(err => {
|
|
console.error('Failed to write to analytics file:', err);
|
|
});
|
|
}
|
|
catch (err) {
|
|
console.error('Error in analytics middleware:', err);
|
|
}
|
|
}
|
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYW5hbHl0aWNzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL21pZGRsZXdhcmUvYW5hbHl0aWNzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUNBLE9BQU8sRUFBRSxNQUFNLElBQUksQ0FBQztBQUNwQixPQUFPLElBQUksTUFBTSxNQUFNLENBQUM7QUFFeEIsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sNkJBQTZCLENBQUM7QUFFL0QsMkVBQTJFO0FBRTNFLE1BQU0sY0FBYyxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLEdBQUcsRUFBRSxFQUFFLHNCQUFzQixDQUFDLENBQUM7QUFFM0UsdUJBQXVCO0FBQ3ZCLE1BQU0sa0JBQWtCLEdBQUcsSUFBSSxHQUFHLENBQUM7SUFDL0IsS0FBSyxFQUFFLE1BQU0sRUFBRSxNQUFNLEVBQUUsTUFBTSxFQUFFLE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFBRSxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sRUFBRSxNQUFNLEVBQUUsTUFBTTtDQUM1RyxDQUFDLENBQUM7QUFDSCxNQUFNLENBQUMsTUFBTSxlQUFlLEdBQUcsRUFBRSxTQUFTLEVBQUUsU0FBUyxFQUFFLFdBQVcsRUFBRSxTQUFTLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRSxDQUFBO0FBOENoRyxNQUFNLGNBQWMsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxHQUFHLEVBQUUsRUFBRSxrQkFBa0IsQ0FBQyxDQUFDO0FBRXZFLHNFQUFzRTtBQUN0RSxJQUFJLFFBQVEsR0FBK0IsSUFBSSxDQUFDO0FBRWhELE1BQU0sWUFBWSxHQUFHLEdBQUcsRUFBRTtJQUN0QixJQUFJLFFBQVE7UUFBRSxPQUFPLFFBQVEsQ0FBQztJQUM5QixJQUFJLENBQUM7UUFDRCxJQUFJLEVBQUUsQ0FBQyxVQUFVLENBQUMsY0FBYyxDQUFDLEVBQUUsQ0FBQztZQUNoQyxNQUFNLElBQUks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
|