UNPKG

hagent

Version:

HTTP agent for whistle

145 lines (125 loc) 3.27 kB
var https = require('https'); var getServer = require('./get-server').create(createHttpsServer, 41500); var MAX_SERVERS = 220; var TIMEOUT = 6000; var DELAY = 100; var NUM_RE = /^\d+$/; function createHttpsServer(options, listener) { var server = https.createServer(options); if (typeof listener === 'function') { server.on('request', listener); } else if (listener) { Object.keys(listener).forEach(function(name) { server.on(name, listener[name]); }); } return server; } function ServerAgent() { this._cache = {}; this._serverCount = 0; } var proto = ServerAgent.prototype; proto.existsServer = function(hostname) { return this._cache[hostname]; }; proto.createServer = function createServer(hostname, listener, callback, timeout, requestTimeout) { var self = this; var cache = self._cache; var promise = cache[hostname]; var resolve; if (!promise) { cache[hostname] = promise = new Promise(function(rsl) { // eslint-disable-line resolve = rsl; }); } promise.then(callback); if (!resolve) { return ; } self.freeServer(); var cert = self.createCertificate(hostname); getServer(cert, listener, function(server, port) { var removeServer = function() { self.removeServer(hostname); }; server.on('error', removeServer); promise.server = server; promise.cert = cert; var timer = setTimeout(removeServer, TIMEOUT); server.once('tlsClientError', removeServer); server.once('secureConnection', function() { clearTimeout(timer); }); if (NUM_RE.test(timeout)) { server.timeout = timeout; } if (NUM_RE.test(requestTimeout)) { server.requestTimeout = requestTimeout; } resolve(port); }); self._serverCount++; return self; }; proto.removeServer = function removeServer(hostname) { var self = this; var cache = self._cache; var promise = cache[hostname]; if (!promise) { return; } delete cache[hostname]; --self._serverCount; setTimeout(function() { try { promise.server.close(); } catch(e) {} //重复关闭会导致异常 }, TIMEOUT); }; proto.freeServer = function() { var self = this; if (self._serverCount < MAX_SERVERS) { return; } var cache = self._cache; for (var i in cache) { destroy(i); } function destroy(hostname) { var promise = cache[hostname]; if (promise._pending) { return; } promise._pending = true; promise.then(function(port) { var server = promise.server; server.getConnections(function(err, count) { promise._pending = false; if (!err && !count && self._serverCount > MAX_SERVERS) { delete cache[hostname]; --self._serverCount; try { server.close(); } catch(e) {} //重复关闭会导致异常 } }); }); } }; proto.destroy = function destroy() { var cache = this._cache; this._cache = {}; this._serverCount = 0; for (var i in cache) { var promise = cache[i]; promise.then(function() { setTimeout(function() { try { promise.server.close(); } catch(e) {} //重复关闭会导致异常 }, DELAY); }); } }; module.exports = ServerAgent;