UNPKG

whistle

Version:

HTTP, HTTPS, Websocket debugging proxy

130 lines (117 loc) 2.67 kB
var dns = require('dns'); var updateQueue = []; var dnsCache = {}; var callbacks = {}; var reqCount = 10; var fastReqCount = 20; var TIMEOUT = 6000; var UPDATE_INTERVAL = 1000; function lookupDNS(hostname, callback) { var list = callbacks[hostname]; if (list) { list.push(callback); return; } callbacks[hostname] = list = [callback]; var done; function execCallback(err, ip) { var host; if (err) { host = dnsCache[hostname]; } else { host = dnsCache[hostname] = { ip: ip, hostname: hostname, time: Date.now() }; } addUpdateQueue(host); if (done) { return; } done = true; callbacks[hostname] = null; list.forEach(function(callback) { callback(err, ip); }); } var timeout = setTimeout(function() { execCallback(new Error('Timeout')); }, TIMEOUT); try { dns.lookup(hostname, function (err, ip, type) { clearTimeout(timeout); err ? execCallback(err) : execCallback(null, ip || (!type || type == 4 ? '127.0.0.1' : '0:0:0:0:0:0:0:1')); }); } catch(err) {//如果断网,可能直接抛异常,https代理没有用到error-handler execCallback(err); } } function addUpdateQueue(host, fast) { if (!host) { return; } var len = updateQueue.length; if (len > 24000) { updateQueue.splice(7000, len - 12000); dnsCache = {}; updateQueue.forEach(function(item) { dnsCache[item.hostname] = item; }); } updateQueue[fast ? 'push' : 'unshift'](host); if (reqCount <= 0) { return; } --reqCount; if (fast) { updateQueue.pop(); updateHost(host); } else { setTimeout(function() { var host = updateQueue.pop(); if (host) { updateHost(host); } else { ++reqCount; } }, UPDATE_INTERVAL); } } function updateHost(host, fast) { lookupDNS(host.hostname, function(err, ip) { if (fast) { ++fastReqCount; } else { ++reqCount; } }); } function fastUpdateHost(host) { if (Date.now() - host.time < TIMEOUT) { return; } var index = updateQueue.indexOf(host); if (index == -1) { return; } updateQueue.splice(index, 1); if (fastReqCount <= 0) { addUpdateQueue(host, true); } else { --fastReqCount; updateHost(host, true); } } module.exports = function lookup(hostname, callback, allowDnsCache) { var host = allowDnsCache ? dnsCache[hostname] : null; if (host) { callback(null, host.ip); fastUpdateHost(host); return host.ip; } lookupDNS(hostname, function(err, ip) { err ? lookupDNS(hostname, callback) : callback(err, ip); }); };