Analyse: Skript nur für aktive Websites, leeres Skript sonst, siteKey in der Skript-URL

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
ClaudeandClaude Opus 5.5 committed 2026-10-01 18:50:26 +00:00
1 parent 97890a8eee
commit c6824f83a6
5 files changed
+76 -10

No files matched your search

+23 -1
View File
@@ -9,7 +9,10 @@ import crypto from 'node:crypto';
const DEFAULT_DIR = join(dirname(fileURLToPath(import.meta.url)), '..', 'client', 'dist');
const FILES = { '/a/w.js': 'w.js', '/a/h.js': 'h.js' };
export function createAssets({ distDir = DEFAULT_DIR, log = console } = {}) {
const RE_KEY = /^[a-z0-9]{16,40}$/;
const EMPTY = Buffer.from('/* WEBklar Analyse: aus */\n');
export function createAssets({ distDir = DEFAULT_DIR, log = console, isActive = () => true } = {}) {
const assets = new Map();
for (const [path, file] of Object.entries(FILES)) {
try {
@@ -28,6 +31,25 @@ export function createAssets({ distDir = DEFAULT_DIR, log = console } = {}) {
res.end();
return true;
}
if (pathname === '/a/w.js') {
let key = '';
try { key = new URL(req.url, 'http://x').searchParams.get('s') || ''; } catch { /* leer */ }
let on = false;
try { on = RE_KEY.test(key) && !!isActive(key); } catch (e) { log.error('Analytics: isActive:', e.message); }
if (!on) {
res.writeHead(200, {
'Content-Type': 'text/javascript; charset=utf-8',
'Cache-Control': 'public, max-age=60',
Vary: 'Accept-Encoding',
'X-Content-Type-Options': 'nosniff',
'Cross-Origin-Resource-Policy': 'cross-origin',
'Access-Control-Allow-Origin': '*',
'Content-Length': EMPTY.length,
});
res.end(req.method === 'HEAD' ? undefined : EMPTY);
return true;
}
}
const a = assets.get(pathname);
if (!a) {
res.writeHead(503, { 'Content-Type': 'application/json', 'Cache-Control': 'no-store' });
+1 -1
View File
@@ -61,7 +61,7 @@ function validateSite(b) {
function createHandlerServer({ config, db, role, geo, salt, now, onSitesChanged }) {
const ingest = role === 'public' ? createIngest({ db, geo, salt: salt || createSalt({ now }), now }) : null;
const heat = role === 'public' ? createHeat({ db, config, now }) : null;
const assets = role === 'public' ? createAssets({ distDir: config.distDir }) : null;
const assets = role === 'public' ? createAssets({ distDir: config.distDir, isActive: (k) => !!db.prepare('SELECT 1 FROM sites WHERE siteKey = ? AND active = 1').get(k) }) : null;
const clock = now || Date.now;
const server = http.createServer(async (req, res) => {
try {