Skip to content

Commit

Permalink
fix: no_proxy issue
Browse files Browse the repository at this point in the history
  • Loading branch information
Avishagp committed Sep 12, 2022
1 parent e5dee92 commit c8163df
Show file tree
Hide file tree
Showing 3 changed files with 159 additions and 42 deletions.
53 changes: 14 additions & 39 deletions lib/needle.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,20 @@
// MIT Licensed
//////////////////////////////////////////

var fs = require('fs'),
http = require('http'),
https = require('https'),
url = require('url'),
stream = require('stream'),
debug = require('debug')('needle'),
stringify = require('./querystring').build,
multipart = require('./multipart'),
auth = require('./auth'),
cookies = require('./cookies'),
parsers = require('./parsers'),
decoder = require('./decoder');
var fs = require('fs'),
http = require('http'),
https = require('https'),
url = require('url'),
stream = require('stream'),
debug = require('debug')('needle'),
stringify = require('./querystring').build,
multipart = require('./multipart'),
auth = require('./auth'),
cookies = require('./cookies'),
parsers = require('./parsers'),
decoder = require('./decoder'),
should_proxy_to = require('./proxy').should_proxy_to,
get_env_var = require('./proxy').get_env_var;

//////////////////////////////////////////
// variabilia
Expand Down Expand Up @@ -127,17 +129,6 @@ Object.keys(aliased.options).map(function(k) {
//////////////////////////////////////////
// helpers

function get_env_var(keys, try_lower) {
var val, i = -1, env = process.env;
while (!val && i < keys.length-1) {
val = env[keys[++i]];
if (!val && try_lower) {
val = env[keys[i].toLowerCase()];
}
}
return val;
}

function keys_by_type(type) {
return Object.keys(defaults).map(function(el) {
if (defaults[el] !== null && defaults[el].constructor == type)
Expand Down Expand Up @@ -190,22 +181,6 @@ function host_and_ports_match(url1, url2) {
== String(b.port || (b.protocol == 'https:' ? 443 : 80));
}

// returns false if a no_proxy host matches given url
function should_proxy_to(url) {
var no_proxy = get_env_var(['NO_PROXY'], true);
if (!no_proxy) return true;

var host, hosts = no_proxy.split(',');
for (var i in hosts) {
host = hosts[i];
if (host_and_ports_match(host, url)) {
return false;
}
}

return true;
}

function pump_streams(streams, cb) {
if (stream.pipeline)
return stream.pipeline.apply(null, streams.concat(cb));
Expand Down
44 changes: 44 additions & 0 deletions lib/proxy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
function get_env_var(keys, try_lower) {
var val, i = -1, env = process.env;
while (!val && i < keys.length-1) {
val = env[keys[++i]];
if (!val && try_lower) {
val = env[keys[i].toLowerCase()];
}
}
return val;
}

// returns false if a no_proxy host matches given url
function should_proxy_to(uri) {
const noProxy = get_env_var(["NO_PROXY"], true);
if (!noProxy) {
return true;
}

var urlMatchedNoProxyPattern = false
const requestUrl = new URL(uri);
const patternList = noProxy.split(/[\s,]+/);

// iterate over all NO_PROXY patterns and determine whether the given URL matches any of them
for (const pattern of patternList) {
if(pattern.trim().length == 0) {
continue
}

// replace leading dot by asterisk, escape dots and finally replace asterisk by .*
const preparedPattern = pattern.replace(/^\./, "*").replace(/[.]/g, '\\$&').replace(/\*/g, '.*')
const regex = new RegExp(preparedPattern)
const matches = (uri.match(regex)?.length > 0);
if (matches) {
// hostname + port of the request URL match a given NO_PROXY pattern
urlMatchedNoProxyPattern = true
break;
}
}

return !urlMatchedNoProxyPattern;
}

module.exports.should_proxy_to = should_proxy_to;
module.exports.get_env_var = get_env_var;
104 changes: 101 additions & 3 deletions test/proxy_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ var helpers = require('./helpers'),
should = require('should'),
sinon = require('sinon'),
http = require('http'),
needle = require('./../');
needle = require('./../'),
should_proxy_to = require('./../lib/proxy').should_proxy_to;

var port = 7707;
var url = 'localhost:' + port;
Expand Down Expand Up @@ -137,9 +138,9 @@ describe('proxy option', function() {
}))
})

it('proxies request if matching host in list but different port', function(done) {
it('does not proxy request if matching host in list and just has a different port', function(done) {
process.env.NO_PROXY = 'localhost';
send_request({ proxy: nonexisting_host + ':123/done' }, proxied(nonexisting_host, '123', function() {
send_request({ proxy: nonexisting_host + ':123/done' }, not_proxied(function() {
delete process.env.NO_PROXY;
done();
}))
Expand All @@ -152,6 +153,103 @@ describe('proxy option', function() {
done();
}))
})

describe('should_proxy_to()', function() {

const noProxy = ".ic1.mycorp,localhost,127.0.0.1,*.mycorp.org";
const noProxyWithPorts = " ,.mycorp.org:1234,.ic1.mycorp,localhost,127.0.0.1";
const URI = "http://registry.random.opr.mycorp.org";
const URIWithPort = "http://registry.random.opr.mycorp.org:9874";
const URIWithPort1234 = "http://registry.random.opr.mycorp.org:1234";
const URIlocalhost = "http://localhost";
const URIip = "http://127.0.0.1";

it("shall return true if NO_PROXY is undefined", function(done) {
process.env.NO_PROXY = undefined;
should_proxy_to(URI).should.true()
delete process.env.NO_PROXY;
done();
});

it("shall return true if NO_PROXY is empty", function(done) {
process.env.NO_PROXY = "";
should_proxy_to(URI).should.true()
delete process.env.NO_PROXY;
done();
});

it("shall return false if NO_PROXY is a wildcard", function(done) {
process.env.NO_PROXY = "*";
should_proxy_to(URI).should.false()
delete process.env.NO_PROXY;
done();
});

it("shall return true if the host matches and the ports don't (URI doesn't have port specified)", function(done) {
process.env.NO_PROXY = noProxyWithPorts;
should_proxy_to(URI).should.true()
delete process.env.NO_PROXY;
done();
});

it("shall return true if the host matches and the ports don't (both have a port specified but just different values)", function(done) {
process.env.NO_PROXY = noProxyWithPorts;
should_proxy_to(URIWithPort).should.true()
delete process.env.NO_PROXY;
done();
});

it("shall return false if the host matches and the ports don't (no_proxy pattern doesn't have a port)", function(done) {
process.env.NO_PROXY = noProxy;
should_proxy_to(URIWithPort).should.false()
delete process.env.NO_PROXY;
done();
});

it("shall return false if host matches", function(done) {
process.env.NO_PROXY = noProxy;
should_proxy_to(URI).should.false()
delete process.env.NO_PROXY;
done();
});

it("shall return false if the host and port matches", function(done) {
process.env.NO_PROXY = noProxyWithPorts;
should_proxy_to(URIWithPort1234).should.false()
delete process.env.NO_PROXY;
done();
});

it("shall return false if the host matches (localhost)", function(done) {
process.env.NO_PROXY = noProxy;
should_proxy_to(URIlocalhost).should.false()
delete process.env.NO_PROXY;
done();
});

it("shall return false if the host matches (ip)", function(done) {
process.env.NO_PROXY = noProxy;
should_proxy_to(URIip).should.false()
delete process.env.NO_PROXY;
done();
});

it("shall return false if the host matches (ip)", function(done) {
process.env.NO_PROXY = noProxy.replace(/,g/, " ");
should_proxy_to(URIip).should.false()
delete process.env.NO_PROXY;
done();
});

it("shall return false if the host matches (ip)", function(done) {
process.env.NO_PROXY = noProxy.replace(/,g/, " ");
should_proxy_to(URIip).should.false()
delete process.env.NO_PROXY;
done();
});

})

})

describe('and proxy url contains user:pass', function() {
Expand Down

0 comments on commit c8163df

Please sign in to comment.