Skip to content

Instantly share code, notes, and snippets.

@poveden
Created January 9, 2019 12:22
Show Gist options
  • Save poveden/8364a8a5a5050482ab56cad897d76b8e to your computer and use it in GitHub Desktop.
Save poveden/8364a8a5a5050482ab56cad897d76b8e to your computer and use it in GitHub Desktop.
Node.js proxy helper module
/**
* Outbound proxy helper library.
* @module lib/proxy-helper
*/
// Reference: http://stackoverflow.com/a/29738070/400347
"use strict";
let defaultOverrideHosts = ['localhost', '127.0.0.1'];
let url = require('url');
let tunnel = require('tunnel');
let logger = require('./logger');
let tunnels = [];
exports.setOutboundHttpProxy = function (proxyUrl, overrideHosts) {
let http = require('http');
setOutboundProxy(http, false, proxyUrl, overrideHosts);
};
exports.setOutboundHttpsProxy = function (proxyUrl, overrideHosts) {
let https = require('https');
setOutboundProxy(https, true, proxyUrl, overrideHosts);
};
function setOutboundProxy(library, isForHttpsRequests, proxyUrl, overrideHosts) {
if (!proxyUrl) { return; }
let skipHosts = (overrideHosts || defaultOverrideHosts).map(function (v) { return v.toLowerCase(); });
let tunnelingAgent = getTunnelingAgent(isForHttpsRequests, proxyUrl);
tunnels.push(tunnelingAgent);
let oldReq = library.request;
library.request = function (options, callback) {
if (tunnels.indexOf(options.agent) != -1 || skipHosts.indexOf(options.host.toLowerCase()) != -1) {
return oldReq.apply(library, arguments);
}
options.agent = tunnelingAgent;
if (options.port === null) { options.port = isForHttpsRequests ? 443 : 80; }
if (!options.protocol) { options.protocol = isForHttpsRequests ? 'https:' : 'http:'; }
logger.debug('Tunneling %s %s', options.method, url.format(options) + options.path);
return oldReq.call(null, options, callback);
};
logger.info('Tunneling %s over %s', (isForHttpsRequests ? 'HTTPS' : 'HTTP'), proxyUrl);
}
function getTunnelingAgent(isForHttpsRequests, proxyUrl) {
if (!proxyUrl) { return undefined; }
let proxy = url.parse(proxyUrl);
let options = {
proxy: {
host: proxy.hostname,
port: proxy.port
}
};
let isHttpsProxy = (proxy.protocol == 'https:');
if (isHttpsProxy) {
if (isForHttpsRequests) {
return tunnel.httpsOverHttps(options);
} else {
return tunnel.httpOverHttps(options);
}
} else {
if (isForHttpsRequests) {
return tunnel.httpsOverHttp(options);
} else {
return tunnel.httpOverHttp(options);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment