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

no_proxy support #1176

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 64 additions & 11 deletions lib/install.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ var fs = require('graceful-fs')
, request = require('request')
, minimatch = require('minimatch')
, mkdir = require('mkdirp')
, url = require('url')
, processRelease = require('./process-release')
, win = process.platform == 'win32'

Expand Down Expand Up @@ -423,6 +424,44 @@ function install (gyp, argv, callback) {

}

function formatHostname (hostname) {
// canonicalize the hostname, so that 'oogle.com' won't match 'google.com'
return hostname.replace(/^\.*/, '.').toLowerCase()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This transforms google.com into .google.com. I infer that is intentional but can you update the comment to make that more explicit? This behavior also seems only lightly tested.

Aside: can you capitalize and punctuate comments?

}

function parseNoProxyZone (zone) {
zone = zone.trim().toLowerCase()

var zoneParts = zone.split(':', 2)
var zoneHost = formatHostname(zoneParts[0])
var zonePort = zoneParts[1]
var hasPort = zone.indexOf(':') > -1
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not wrong per se but can also be derived without re-scanning from zonePort !== undefined or zoneParts.length === 2.


return {hostname: zoneHost, port: zonePort, hasPort: hasPort}
}

function uriInNoProxy (uri, noProxy) {
var parsedUri = url.parse(uri);
var port = parsedUri.port || (parsedUri.protocol === 'https:' ? '443' : '80')
var hostname = formatHostname(parsedUri.hostname)
var noProxyList = noProxy.split(',')

// iterate through the noProxyList until it finds a match.
return noProxyList.map(parseNoProxyZone).some(function (noProxyZone) {
var isMatchedAt = hostname.indexOf(noProxyZone.hostname)
var hostnameMatched = (
isMatchedAt > -1 &&
(isMatchedAt === hostname.length - noProxyZone.hostname.length)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct me if I'm wrong but isn't this just a circuitous way of saying hostname === noProxyZone.hostname?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO it's a suffix match

)

if (noProxyZone.hasPort) {
return (port === noProxyZone.port) && hostnameMatched
}

return hostnameMatched
})
}

function download (gyp, env, url) {
log.http('GET', url)

Expand All @@ -438,18 +477,32 @@ function download (gyp, env, url) {
requestOpts.ca = readCAFile(cafile)
}

// basic support for a proxy server
var proxyUrl = gyp.opts.proxy
|| env.http_proxy
|| env.HTTP_PROXY
|| env.npm_config_proxy
if (proxyUrl) {
if (/^https?:\/\//i.test(proxyUrl)) {
log.verbose('download', 'using proxy url: "%s"', proxyUrl)
requestOpts.proxy = proxyUrl
} else {
log.warn('download', 'ignoring invalid "proxy" config setting: "%s"', proxyUrl)
var noProxyUrl = gyp.opts.no_proxy
|| env.no_proxy
|| env.NO_PROXY
|| env.npm_config_no_proxy
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should probably go; the npm pull request wasn't merged.

|| ''

if (noProxyUrl === '*' || (noProxyUrl !== '' && uriInNoProxy(url, noProxyUrl))) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Long line; can you keep it under 80 columns? The parens around the && aren't necessary.

log.warn('download', 'ignoring proxy for url: "%s"', url)
} else {

// basic support for a proxy server
var proxyUrl = gyp.opts.proxy
|| env.http_proxy
|| env.HTTP_PROXY
|| env.npm_config_proxy

if (proxyUrl) {
if (/^https?:\/\//i.test(proxyUrl)) {
log.verbose('download', 'using proxy url: "%s"', proxyUrl)
requestOpts.proxy = proxyUrl
} else {
log.warn('download', 'ignoring invalid "proxy" config setting: "%s"', proxyUrl)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto, long line.

}
}


}

var req = request(requestOpts)
Expand Down
63 changes: 63 additions & 0 deletions test/test-download-options.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
var test = require('tape')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add 'use strict';?

var requireInject = require('require-inject');
var install = requireInject('../lib/install', {
'request': function(opts) {
return {
opts: opts,
on: function () {}
};
}
})

test('add proxy property when proxy is specified', function (t) {
t.plan(2)

var url = 'http://www.xyz.com';
var gyp = {
opts: {
proxy: 'http://www.test.com'
}
}

var req = install.test.download(gyp, {}, url)

t.equal(req.opts.proxy, gyp.opts.proxy)
t.equal(req.opts.uri, url)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you drop the blank line here and below?

})

test('when no_proxy = * omit proxy property', function (t) {
t.plan(2)

var url = 'http://www.xyz.com';
var gyp = {
opts: {
proxy: 'http://www.test.com',
no_proxy: '*'
}
}

var req = install.test.download(gyp, {}, url)

t.equal(req.opts.proxy, undefined)
t.equal(req.opts.uri, url)

})

test('when no_proxy matches url omit proxy property', function (t) {
t.plan(2)

var url = 'http://www.xyz.com';
var gyp = {
opts: {
proxy: 'http://www.test.com',
no_proxy: 'xyz.com'
}
}

var req = install.test.download(gyp, {}, url)

t.equal(req.opts.proxy, undefined)
t.equal(req.opts.uri, url)

})