Files

122 lines
4.0 KiB
JavaScript

(function (root) {
'use strict';
var S = root.AutoMirrorShared;
var C = root.AutoMirrorCache;
var D = root.AutoMirrorDiagnostics;
function probeCandidate(rule, host, sourceUrlObj, callback) {
var url = S.buildTargetUrl(rule, host, sourceUrlObj);
var done = false;
var timeout = Math.max(1000, Number(rule.timeoutMs || 3000));
var controller = typeof AbortController !== 'undefined' ? new AbortController() : null;
var timer = controller ? root.setTimeout(function () {
controller.abort();
}, timeout) : null;
function finish(ok, status) {
if (done) return;
done = true;
if (timer) root.clearTimeout(timer);
callback({
host: host,
url: url,
ok: ok,
status: status || 0
});
}
try {
fetch(url, {
method: 'GET',
cache: 'no-store',
credentials: 'omit',
redirect: 'follow',
headers: {
'Cache-Control': 'no-cache',
'Pragma': 'no-cache'
},
signal: controller ? controller.signal : undefined
}).then(function (response) {
response.text().then(function (text) {
var statusOk = response.status >= 200 && response.status < 400;
var textOk = !S.responseLooksBlocked(rule, text || '');
finish(statusOk && textOk, response.status);
}).catch(function () {
finish(false, response.status || 0);
});
}).catch(function () {
finish(false, 0);
});
} catch (e) {
finish(false, 0);
}
}
function findWorkingByProbe(rule, sourceUrlObj, triedHosts, callback) {
C.getCachedHost(rule, function (cachedHost) {
var currentHost = S.normalizeHost(sourceUrlObj.hostname);
var candidates = S.buildCandidates(rule, currentHost, cachedHost).filter(function (host) {
return !triedHosts[host];
});
D.appendDebugLog('debug', 'candidates.built', {
rule: rule.name || rule.id || 'unknown',
currentHost: currentHost,
cachedHost: cachedHost || '',
count: candidates.length,
first: candidates.slice(0, 12),
last: candidates.slice(Math.max(0, candidates.length - 5))
});
if (!candidates.length) {
callback(null);
return;
}
var index = 0;
var active = 0;
var finished = false;
var parallel = Math.max(1, Number(rule.parallelChecks || 8));
function launchMore() {
if (finished) return;
while (active < parallel && index < candidates.length) {
var host = candidates[index];
index += 1;
active += 1;
probeCandidate(rule, host, sourceUrlObj, function (result) {
active -= 1;
triedHosts[result.host] = true;
if (finished) return;
if (result.ok) {
finished = true;
callback(result.host);
return;
}
if (index >= candidates.length && active === 0) {
finished = true;
callback(null);
return;
}
launchMore();
});
}
}
launchMore();
});
}
root.AutoMirrorProbe = {
probeCandidate: probeCandidate,
findWorkingByProbe: findWorkingByProbe
};
})(typeof globalThis !== 'undefined' ? globalThis : this);