UNPKG

do-node-balancer

Version:
125 lines (112 loc) 2.78 kB
const httpProxy = require('http-proxy'); const DigitalOcean = require('./digitalocean'); const https = require('https'); const assert = require('assert'); const request = require('./request.js'); const joi = require('joi'); module.exports = ({ doToken, doTags, options }) => { const opts = { maxFailCount: 5, doUpdateTime: 1000 * 60 * 10, ...options, }; const doRequest = request(doToken); const doProvider = DigitalOcean({ joi, doTags, doRequest, opts, }); const agent = new https.Agent({ maxSockets: 1000, keepAlive: true, keepAliveMsecs: 3000, }); const proxy = httpProxy.createProxy({ agent, ws: true, }); function displayErrorPage(res) { if (opts.failurePage) { res.write(opts.failurePage); return res.end(); } return res.end('Something went wrong -- proxy error'); } proxy.on('error', (e, req, res) => { // Do not report failures for now, this needs to be thought through // doProvider.reportFailure(req.target); console.log('Proxy error event', e); displayErrorPage(res); }); const balance = (req, res, params) => { const par = params || {}; assert((par instanceof Object), 'params must be an object or unspecified'); const { tags, port, address } = params; const host = address || doProvider.getServer(tags); if (!host) { res.end('Something went wrong -- host not found'); return; } const MAX_ATTEMPTS = 3; let attempt = 1; req.url = req.originalUrl; req.target = { host, tags, port, protocol: 'https:', }; const webOpts = { target: req.target, secure: true, }; const redirect = () => { // Proxy 'error' event listener won't fire if we provide an error callback here. proxy.web(req, res, webOpts, (err) => { console.log('Web error callback', err); if (attempt >= MAX_ATTEMPTS) { console.log(MAX_ATTEMPTS, 'attempts exceeded. Display error.'); displayErrorPage(res); } else { console.log('Retrying...'); attempt += 1; setTimeout(redirect, 1500); } }); }; redirect(); }; const balanceUpgrade = (req, socket, upgradeHead, params) => { const par = params || {}; assert((par instanceof Object), 'params must be an object or unspecified'); const { tags, port, address } = params; const host = address || doProvider.getServer(tags); if (!host) { return socket.end('Something went wrong -- no host found'); } req.target = { host, tags, port, protocol: 'wss:', }; return proxy.ws(req, socket, upgradeHead, { target: req.target, secure: true, }); }; function getStats() { return doProvider.getServerList(); } function updateServers() { return doProvider.updateServers(); } return { getStats, balance, balanceUpgrade, updateServers, }; };