Bild-Proxy (same-origin, defeats hotlink protection) + klareres Reset-Feedback
This commit is contained in:
@@ -30,6 +30,12 @@ function saveState(state) {
|
||||
}
|
||||
let state = loadState();
|
||||
|
||||
// In-memory image cache for the proxy
|
||||
const imgCache = new Map();
|
||||
function hostAllowed(host) {
|
||||
return /(^|\.)urlaub\.check24\.de$/.test(host) || host === 'files.ahoi-schiff.de';
|
||||
}
|
||||
|
||||
const MIME = { '.html': 'text/html; charset=utf-8', '.js': 'text/javascript; charset=utf-8',
|
||||
'.css': 'text/css; charset=utf-8', '.json': 'application/json', '.svg': 'image/svg+xml',
|
||||
'.png': 'image/png', '.jpg': 'image/jpeg', '.ico': 'image/x-icon', '.webmanifest': 'application/manifest+json' };
|
||||
@@ -72,6 +78,34 @@ const server = http.createServer(async (req, res) => {
|
||||
}
|
||||
if (p === '/health') { return sendJSON(res, 200, { ok: true }); }
|
||||
|
||||
// ---- Image proxy (defeats hotlink/referrer protection, same-origin = always loads) ----
|
||||
if (p === '/img' && req.method === 'GET') {
|
||||
const u = url.searchParams.get('u');
|
||||
let host;
|
||||
try { host = new URL(u).host; } catch (e) { res.writeHead(400); return res.end('bad url'); }
|
||||
if (!hostAllowed(host)) { res.writeHead(403); return res.end('host not allowed'); }
|
||||
if (imgCache.has(u)) {
|
||||
const c = imgCache.get(u);
|
||||
res.writeHead(200, { 'Content-Type': c.type, 'Cache-Control': 'public, max-age=604800' });
|
||||
return res.end(c.buf);
|
||||
}
|
||||
try {
|
||||
const referer = host.endsWith('ahoi-schiff.de') ? 'https://www.ahoi-schiff.de/' : 'https://urlaub.check24.de/';
|
||||
const ac = new AbortController();
|
||||
const t = setTimeout(() => ac.abort(), 8000);
|
||||
const r = await fetch(u, { signal: ac.signal, headers: {
|
||||
'Referer': referer, 'User-Agent': 'Mozilla/5.0 (compatible; HeidrichReise/1.0)', 'Accept': 'image/*'
|
||||
}});
|
||||
clearTimeout(t);
|
||||
if (!r.ok) { res.writeHead(502); return res.end('upstream ' + r.status); }
|
||||
const type = r.headers.get('content-type') || 'image/jpeg';
|
||||
const buf = Buffer.from(await r.arrayBuffer());
|
||||
if (imgCache.size < 300) imgCache.set(u, { buf, type });
|
||||
res.writeHead(200, { 'Content-Type': type, 'Cache-Control': 'public, max-age=604800' });
|
||||
return res.end(buf);
|
||||
} catch (e) { res.writeHead(502); return res.end('proxy error'); }
|
||||
}
|
||||
|
||||
// ---- Static ----
|
||||
let file = p === '/' ? '/index.html' : decodeURIComponent(p);
|
||||
const full = path.join(PUBLIC, path.normalize(file).replace(/^(\.\.[\/\\])+/, ''));
|
||||
|
||||
Reference in New Issue
Block a user