Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding interpretation of no_proxy #565

Closed
wants to merge 8 commits into from
Closed
22 changes: 2 additions & 20 deletions lib/adapters/http.js
Expand Up @@ -12,6 +12,7 @@ var zlib = require('zlib');
var pkg = require('./../../package.json');
var createError = require('../core/createError');
var enhanceError = require('../core/enhanceError');
var getProxy = require('./http.proxy');

/*eslint consistent-return:0*/
module.exports = function httpAdapter(config) {
Expand Down Expand Up @@ -81,26 +82,7 @@ module.exports = function httpAdapter(config) {
auth: auth
};

var proxy = config.proxy;
if (!proxy && proxy !== false) {
var proxyEnv = protocol.slice(0, -1) + '_proxy';
var proxyUrl = process.env[proxyEnv] || process.env[proxyEnv.toUpperCase()];
if (proxyUrl) {
var parsedProxyUrl = url.parse(proxyUrl);
proxy = {
host: parsedProxyUrl.hostname,
port: parsedProxyUrl.port
};

if (parsedProxyUrl.auth) {
var proxyUrlAuth = parsedProxyUrl.auth.split(':');
proxy.auth = {
username: proxyUrlAuth[0],
password: proxyUrlAuth[1]
};
}
}
}
var proxy = getProxy(config);

if (proxy) {
options.hostname = proxy.host;
Expand Down
42 changes: 42 additions & 0 deletions lib/adapters/http.proxy.js
@@ -0,0 +1,42 @@
'use strict';

var url = require('url');

var getProxyForUrl = require('proxy-from-env').getProxyForUrl;

/**
*
* @param {Object} config
* @param {string} config.url
* @param {Object=) config.proxy
* @param {string} config.proxy.host
* @param {number} config.proxy.port
* @return {object | undefined} proxy
* @return {string} proxy.host
* @return {number} proxy.number
* @return {object | undefined} proxy.auth
* @return {string} proxy.auth.username
* @return {string} proxy.auth.password
*/
module.exports = function getProxy(config) {
var proxy = config.proxy;
if (!proxy && proxy !== false) {
var envProxy = getProxyForUrl(config.url);
if (envProxy) {
var parsedProxyUrl = url.parse(envProxy);
proxy = {
host: parsedProxyUrl.hostname,
port: parsedProxyUrl.port
};

if (parsedProxyUrl.auth) {
var proxyUrlAuth = parsedProxyUrl.auth.split(':');
proxy.auth = {
username: proxyUrlAuth[0],
password: proxyUrlAuth[1]
};
}
}
}
return proxy || undefined;
};
3 changes: 2 additions & 1 deletion package.json
Expand Up @@ -74,7 +74,8 @@
"typings": "./index.d.ts",
"dependencies": {
"follow-redirects": "^1.2.5",
"is-buffer": "^1.1.5"
"is-buffer": "^1.1.5",
"proxy-from-env": "^1.0.0"
},
"bundlesize": [
{
Expand Down
52 changes: 49 additions & 3 deletions test/unit/adapters/http.js
Expand Up @@ -3,21 +3,27 @@ var http = require('http');
var url = require('url');
var zlib = require('zlib');
var fs = require('fs');
var adapter = require('../../../lib/adapters/http.js');
var server, proxy;

module.exports = {
tearDown: function (callback) {
server.close();
server = null;
if (server) {
server.close();
server = null;
}
if (proxy) {
proxy.close()
proxy.close();
proxy = null;
}

if (process.env.http_proxy) {
delete process.env.http_proxy;
}

delete process.env.no_proxy;
delete process.env.NO_PROXY;

callback();
},

Expand Down Expand Up @@ -355,6 +361,7 @@ module.exports = {
}).listen(4000, function() {
// set the env variable
process.env.http_proxy = 'http://localhost:4000/';
process.env.no_proxy = 'my.corp.com';

axios.get('http://localhost:4444/').then(function(res) {
test.equal(res.data, '45671234', 'should use proxy set by process.env.http_proxy');
Expand All @@ -364,6 +371,45 @@ module.exports = {
});
},

testHTTPNoProxyEnv: function(test) {
server = http.createServer(function(req, res) {
res.setHeader('Content-Type', 'text/html; charset=UTF-8');
res.end('4567');
}).listen(4444, function() {
proxy = http.createServer(function(request, response) {
var parsed = url.parse(request.url);
var opts = {
host: parsed.hostname,
port: parsed.port,
path: parsed.path
};

http.get(opts, function(res) {
var body = '';
res.on('data', function(data) {
body += data;
});
res.on('end', function() {
response.setHeader('Content-Type', 'text/html; charset=UTF-8');
response.end(body + '1234');
});
});
}).listen(4000, function() {
// set the env variable
process.env.http_proxy = 'http://127.0.0.1:4000/';
process.env.no_proxy = 'localhost';

axios.get('http://localhost:4444/').then(function(res) {
test.equal(res.data, '4567', 'should not use proxy set by process.env.http_proxy as of process.env.no_proxy');
test.done();
}, function() {
test.ok(false, 'error occured during request with no_proxy');
test.done();
});
});
});
},

testHTTPProxyAuth: function(test) {
server = http.createServer(function(req, res) {
res.end();
Expand Down
203 changes: 203 additions & 0 deletions test/unit/adapters/proxy.js
@@ -0,0 +1,203 @@
'use strict';

var getProxy = require('../../../lib/adapters/http.proxy');

function config(def) {
var cfg = {};
cfg.url = def && def.url || 'http://google.com';
cfg.proxy = def && def.proxy;
return cfg;
}


module.exports = {

setUp: function(done) {
delete process.env.http_proxy;
delete process.env.https_proxy;
delete process.env.no_proxy;
delete process.env.HTTP_PROXY;
delete process.env.HTTPS_PROXY;
delete process.env.NO_PROXY;
done();
},

isEmptyIfNotConfigured: function(test) {
test.equal(getProxy(config()), undefined);
test.done();
},

canReadProxyHostFromConfig: function(test) {
var cfg = config({proxy: {host: 'corpproxy.com'}});
var proxy = getProxy(cfg);
test.equal(proxy.host, 'corpproxy.com');
test.equal(proxy.port, undefined);
test.equal(proxy.auth, undefined);
test.done();
},

canReadProxyAndPortHostFromConfig: function(test) {
var cfg = config({proxy: {host: 'corpproxy.com', port: 80}});
var proxy = getProxy(cfg);
test.equal(proxy.host, 'corpproxy.com');
test.equal(proxy.port, 80);
test.equal(proxy.auth, undefined);
test.done();
},


canReadProxyAndAuthHostFromConfig: function(test) {
var cfg = config({proxy: {host: 'corpproxy.com', auth: {password: 'secret', username: 'bob'}}});
var proxy = getProxy(cfg);
test.equal(proxy.host, 'corpproxy.com');
test.equal(proxy.port, undefined);
test.deepEqual(proxy.auth, {password: 'secret', username: 'bob'});
test.done();
},

canReadProxyHostFromEnv: function(test) {
process.env.http_proxy = 'http://corpproxy.com/';
var proxy = getProxy(config());
test.equal(proxy.host, 'corpproxy.com');
test.equal(proxy.port, undefined);
test.equal(proxy.auth, undefined);
test.done();
},

canReadProxyHostAndPortFromEnv: function(test) {
process.env.http_proxy = 'http://corpproxy.com:77/';
var proxy = getProxy(config());
test.equal(proxy.host, 'corpproxy.com');
test.equal(proxy.port, 77);
test.equal(proxy.auth, undefined);
test.done();
},

canReadProxyHostAndPortAndAuthFromEnv: function(test) {
process.env.http_proxy = 'http://bob:secret@corpproxy.com:77/';
var proxy = getProxy(config());
test.equal(proxy.host, 'corpproxy.com');
test.equal(proxy.port, 77);
test.deepEqual(proxy.auth, {username: 'bob', password: 'secret'});
test.done();
},

proxyFromConfigOverridesProxyFromEnv: function(test) {
process.env.http_proxy = 'http://bob:secret@corpproxy.com:77/';
var proxy = getProxy(config({proxy: {host: 'other-host.com'}}));
test.equal(proxy.host, 'other-host.com');
test.equal(proxy.port, undefined);
test.equal(proxy.auth, undefined);
test.done();
},

proxyUnsetFromConfigOverridesProxyFromEnv: function(test) {
process.env.http_proxy = 'http://bob:secret@corpproxy.com:77/';
var proxy = getProxy(config({proxy: false}));
test.equal(proxy, undefined);
test.done();
},

readProxyFromCorrectEnv: function(test) {
process.env.https_proxy = 'http://corpproxy.com/';
test.equal(getProxy(config()), undefined);
process.env.http_proxy = 'http://other-proxy.com/';
test.equal(getProxy(config()).host, 'other-proxy.com');
test.equal(getProxy(config({url: 'https://google.com/'})).host, 'corpproxy.com');
delete process.env.https_proxy;
test.equal(getProxy(config({url: 'https://google.com/'})), undefined);
test.done();
},

canHandleCasingInProxyEnv: function(test) {
process.env.HTTPS_PROXY = 'http://corpproxy.com/';
test.equal(getProxy(config()), undefined);
process.env.HTTP_PROXY = 'http://other-proxy.com/';
test.equal(getProxy(config()).host, 'other-proxy.com');
test.equal(getProxy(config({url: 'https://google.com/'})).host, 'corpproxy.com');
delete process.env.HTTPS_PROXY;
test.equal(getProxy(config({url: 'https://google.com/'})), undefined);
test.done();
},

canHandleNoProxy: function(test) {
process.env.HTTPS_PROXY = 'http://corpproxy.com/';
process.env.NO_PROXY = 'google.com';
test.equal(getProxy(config({url: 'https://google.com'})), undefined);
test.equal(getProxy(config({url: 'https://google.com/page.php'})), undefined);
test.done();
},

canHandleNoNoProxy: function(test) {
process.env.HTTPS_PROXY = 'http://cc.com/';
process.env.NO_PROXY = 'google.com';
test.equal(getProxy(config({url: 'https://sbb.com'})).host, 'cc.com');
test.equal(getProxy(config({url: 'https://www.google.com/page.php'})).host, 'cc.com');
test.done();
},

canHandleMultipleNoProxy: function(test) {
process.env.HTTPS_PROXY = 'http://corpproxy.com/';
process.env.NO_PROXY = 'google.com, .amazon.de nzz.ch ';
test.equal(getProxy(config({url: 'https://google.com'})), undefined);
test.equal(getProxy(config({url: 'https://www.amazon.de/index.html'})), undefined);
test.equal(getProxy(config({url: 'https://nzz.ch/index.html'})), undefined);
test.done();
},

canHandlePortsInNoProxy: function(test) {
process.env.HTTPS_PROXY = 'http://cc.com/';
process.env.NO_PROXY = '*google.com:8080';
test.equal(getProxy(config({url: 'https://www2.google.com:8080/index.html'})), undefined);
test.equal(getProxy(config({url: 'https://google.com/index.html'})).host, 'cc.com');
test.equal(getProxy(config({url: 'https://nzz.ch/index.html'})).host, 'cc.com');
test.done();
},

canHandleStarInNoProxy: function(test) {
process.env.HTTPS_PROXY = 'http://cc.com/';
process.env.NO_PROXY = '*';
test.equal(getProxy(config({url: 'https://www2.google.com:8080/index.html'})), undefined);
test.equal(getProxy(config({url: 'https://google.com/index.html'})), undefined);
test.equal(getProxy(config({url: 'https://nzz.ch/index.html'})), undefined);
test.done();
},

testIsANoProxyHost: function(test) {
process.env.HTTPS_PROXY = 'http://cc.com/';
[
{h: 'bliss.mit.edu', no_p: undefined, res: false},
{h: 'bliss.mit.edu', no_p: 'localhost', res: false},
{h: 'bliss.mit.edu', no_p: 'localhost, my.corp.com', res: false},
{h: 'bliss.mit.edu', no_p: '.mit.edu', res: true},
{h: 'bliss.mit.edu', no_p: '.mit.edu,localhost', res: true},
{h: 'bliss.mit.edu', no_p: ' .mit.edu', res: true},
{h: 'bliss.mit.edu', no_p: '.mit.edu ', res: true},
{h: 'bliss.mit.edu', no_p: 'localhost, .mit.edu', res: true},
{h: 'bliss.mit.edu', no_p: '.edu', res: true},
{h: '127.0.0.1', no_p: '.0.0.1', res: true},
{h: '127.0.0.1', no_p: 'localhost', res: false}
].forEach(function(data) {
process.env.no_proxy = data.no_p;
var proxy = getProxy(config({url: 'https://' + data.h + '/index.html'}));
if (data.res) {
test.equal(proxy, undefined);
} else {
test.equal(proxy.host, 'cc.com');
}
delete process.env.no_proxy;

process.env.NO_PROXY = data.no_p;
var proxy2 = getProxy(config({url: 'https://' + data.h + '/index.html'}));
if (data.res) {
test.equal(proxy2, undefined);
} else {
test.equal(proxy2.host, 'cc.com');
}
delete process.env.NO_PROXY;
});

test.done();
}
};