fix: wayback-save fire-and-forget + CDX polling statt Body-Wait
This commit is contained in:
@@ -259,7 +259,7 @@ router.get('/wayback', authenticate, async (req, res) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// ── POST /api/tools/paywallkiller/wayback-save ────────────────────────────
|
// ── POST /api/tools/paywallkiller/wayback-save ────────────────────────────
|
||||||
// Erstellt einen neuen Wayback-Snapshot und wartet auf das Ergebnis
|
// Schießt Save-Request ab (fire-and-forget), pollt dann CDX auf Ergebnis
|
||||||
router.post('/wayback-save', authenticate, async (req, res) => {
|
router.post('/wayback-save', authenticate, async (req, res) => {
|
||||||
const { url } = req.body;
|
const { url } = req.body;
|
||||||
if (!url || typeof url !== 'string') return res.status(400).json({ error: 'url fehlt' });
|
if (!url || typeof url !== 'string') return res.status(400).json({ error: 'url fehlt' });
|
||||||
@@ -267,33 +267,67 @@ router.post('/wayback-save', authenticate, async (req, res) => {
|
|||||||
let targetUrl = url.trim();
|
let targetUrl = url.trim();
|
||||||
if (!targetUrl.startsWith('http')) targetUrl = 'https://' + targetUrl;
|
if (!targetUrl.startsWith('http')) targetUrl = 'https://' + targetUrl;
|
||||||
|
|
||||||
// Save API aufrufen: GET https://web.archive.org/save/URL
|
const https = require('https');
|
||||||
// Antwort: 302 Redirect auf https://web.archive.org/web/TIMESTAMP/URL
|
|
||||||
try {
|
|
||||||
const saveUrl = `https://web.archive.org/save/${targetUrl}`;
|
|
||||||
const saveResult = await fetchPage(saveUrl); // fetchPage folgt Redirects
|
|
||||||
|
|
||||||
// Nach Redirect landet man auf web.archive.org/web/TIMESTAMP/URL
|
// ── Hilfsfunktion: CDX prüfen ──────────────────────────────────────────
|
||||||
const final = saveResult.finalUrl || '';
|
async function checkCdx() {
|
||||||
const match = final.match(/web\.archive\.org\/web\/(\d{14})\//);
|
|
||||||
if (match) {
|
|
||||||
return res.json({ success: true, waybackUrl: final, timestamp: match[1] });
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fallback: CDX nochmal prüfen (Save kann asynchron sein)
|
|
||||||
await new Promise(r => setTimeout(r, 3000));
|
|
||||||
const cdxUrl = `https://web.archive.org/cdx/search/cdx?url=${encodeURIComponent(targetUrl)}&output=json&limit=1&fl=timestamp&filter=statuscode:200&fastLatest=true`;
|
const cdxUrl = `https://web.archive.org/cdx/search/cdx?url=${encodeURIComponent(targetUrl)}&output=json&limit=1&fl=timestamp&filter=statuscode:200&fastLatest=true`;
|
||||||
const cdxResult = await fetchPage(cdxUrl);
|
try {
|
||||||
if (cdxResult.statusCode === 200) {
|
const r = await fetchPage(cdxUrl);
|
||||||
let data;
|
if (r.statusCode === 200 && r.body) {
|
||||||
try { data = JSON.parse(cdxResult.body); } catch { data = null; }
|
const data = JSON.parse(r.body);
|
||||||
if (Array.isArray(data) && data.length >= 2 && data[1]?.[0]) {
|
if (Array.isArray(data) && data.length >= 2 && data[1]?.[0]) {
|
||||||
const timestamp = data[1][0];
|
return `https://web.archive.org/web/${data[1][0]}/${targetUrl}`;
|
||||||
return res.json({ success: true, waybackUrl: `https://web.archive.org/web/${timestamp}/${targetUrl}`, timestamp });
|
}
|
||||||
|
}
|
||||||
|
} catch {}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Save-Request fire-and-forget (kein Warten auf Body) ───────────────
|
||||||
|
function fireSaveRequest() {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
const saveUrl = new URL(`https://web.archive.org/save/${targetUrl}`);
|
||||||
|
const req = https.get({
|
||||||
|
hostname: saveUrl.hostname,
|
||||||
|
path: saveUrl.pathname + saveUrl.search,
|
||||||
|
headers: {
|
||||||
|
'User-Agent': 'Mozilla/5.0 (compatible; WaybackSave/1.0)',
|
||||||
|
'Accept': 'text/html',
|
||||||
|
},
|
||||||
|
timeout: 8000,
|
||||||
|
}, (res) => {
|
||||||
|
// Nur Headers lesen, Body sofort verwerfen
|
||||||
|
const location = res.headers.location || '';
|
||||||
|
res.resume(); // Body ignorieren
|
||||||
|
resolve(location);
|
||||||
|
});
|
||||||
|
req.on('error', () => resolve(''));
|
||||||
|
req.on('timeout', () => { req.destroy(); resolve(''); });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Save abschießen
|
||||||
|
const location = await fireSaveRequest();
|
||||||
|
|
||||||
|
// Direkt aus Location-Header auslesen wenn vorhanden
|
||||||
|
const directMatch = location.match(/\/web\/(\d{14})\//);
|
||||||
|
if (directMatch) {
|
||||||
|
const waybackUrl = location.startsWith('http') ? location : `https://web.archive.org${location}`;
|
||||||
|
return res.json({ success: true, waybackUrl, timestamp: directMatch[1] });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Polling: bis zu 6x alle 5s CDX abfragen (max 30s warten)
|
||||||
|
for (let i = 0; i < 6; i++) {
|
||||||
|
await new Promise(r => setTimeout(r, 5000));
|
||||||
|
const found = await checkCdx();
|
||||||
|
if (found) {
|
||||||
|
return res.json({ success: true, waybackUrl: found });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return res.status(502).json({ error: 'Snapshot konnte nicht erstellt werden. Die Seite blockiert möglicherweise die Wayback Machine.' });
|
return res.status(502).json({ error: 'Archivierung läuft noch oder wurde blockiert. Versuche es in einer Minute erneut.' });
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
return res.status(500).json({ error: 'Save fehlgeschlagen: ' + err.message });
|
return res.status(500).json({ error: 'Save fehlgeschlagen: ' + err.message });
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user