You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
175 lines
4.3 KiB
175 lines
4.3 KiB
'use strict' |
|
|
|
var url = require('url') |
|
var tunnel = require('tunnel-agent') |
|
|
|
var defaultProxyHeaderWhiteList = [ |
|
'accept', |
|
'accept-charset', |
|
'accept-encoding', |
|
'accept-language', |
|
'accept-ranges', |
|
'cache-control', |
|
'content-encoding', |
|
'content-language', |
|
'content-location', |
|
'content-md5', |
|
'content-range', |
|
'content-type', |
|
'connection', |
|
'date', |
|
'expect', |
|
'max-forwards', |
|
'pragma', |
|
'referer', |
|
'te', |
|
'user-agent', |
|
'via' |
|
] |
|
|
|
var defaultProxyHeaderExclusiveList = [ |
|
'proxy-authorization' |
|
] |
|
|
|
function constructProxyHost (uriObject) { |
|
var port = uriObject.port |
|
var protocol = uriObject.protocol |
|
var proxyHost = uriObject.hostname + ':' |
|
|
|
if (port) { |
|
proxyHost += port |
|
} else if (protocol === 'https:') { |
|
proxyHost += '443' |
|
} else { |
|
proxyHost += '80' |
|
} |
|
|
|
return proxyHost |
|
} |
|
|
|
function constructProxyHeaderWhiteList (headers, proxyHeaderWhiteList) { |
|
var whiteList = proxyHeaderWhiteList |
|
.reduce(function (set, header) { |
|
set[header.toLowerCase()] = true |
|
return set |
|
}, {}) |
|
|
|
return Object.keys(headers) |
|
.filter(function (header) { |
|
return whiteList[header.toLowerCase()] |
|
}) |
|
.reduce(function (set, header) { |
|
set[header] = headers[header] |
|
return set |
|
}, {}) |
|
} |
|
|
|
function constructTunnelOptions (request, proxyHeaders) { |
|
var proxy = request.proxy |
|
|
|
var tunnelOptions = { |
|
proxy: { |
|
host: proxy.hostname, |
|
port: +proxy.port, |
|
proxyAuth: proxy.auth, |
|
headers: proxyHeaders |
|
}, |
|
headers: request.headers, |
|
ca: request.ca, |
|
cert: request.cert, |
|
key: request.key, |
|
passphrase: request.passphrase, |
|
pfx: request.pfx, |
|
ciphers: request.ciphers, |
|
rejectUnauthorized: request.rejectUnauthorized, |
|
secureOptions: request.secureOptions, |
|
secureProtocol: request.secureProtocol |
|
} |
|
|
|
return tunnelOptions |
|
} |
|
|
|
function constructTunnelFnName (uri, proxy) { |
|
var uriProtocol = (uri.protocol === 'https:' ? 'https' : 'http') |
|
var proxyProtocol = (proxy.protocol === 'https:' ? 'Https' : 'Http') |
|
return [uriProtocol, proxyProtocol].join('Over') |
|
} |
|
|
|
function getTunnelFn (request) { |
|
var uri = request.uri |
|
var proxy = request.proxy |
|
var tunnelFnName = constructTunnelFnName(uri, proxy) |
|
return tunnel[tunnelFnName] |
|
} |
|
|
|
function Tunnel (request) { |
|
this.request = request |
|
this.proxyHeaderWhiteList = defaultProxyHeaderWhiteList |
|
this.proxyHeaderExclusiveList = [] |
|
if (typeof request.tunnel !== 'undefined') { |
|
this.tunnelOverride = request.tunnel |
|
} |
|
} |
|
|
|
Tunnel.prototype.isEnabled = function () { |
|
var self = this |
|
var request = self.request |
|
// Tunnel HTTPS by default. Allow the user to override this setting. |
|
|
|
// If self.tunnelOverride is set (the user specified a value), use it. |
|
if (typeof self.tunnelOverride !== 'undefined') { |
|
return self.tunnelOverride |
|
} |
|
|
|
// If the destination is HTTPS, tunnel. |
|
if (request.uri.protocol === 'https:') { |
|
return true |
|
} |
|
|
|
// Otherwise, do not use tunnel. |
|
return false |
|
} |
|
|
|
Tunnel.prototype.setup = function (options) { |
|
var self = this |
|
var request = self.request |
|
|
|
options = options || {} |
|
|
|
if (typeof request.proxy === 'string') { |
|
request.proxy = url.parse(request.proxy) |
|
} |
|
|
|
if (!request.proxy || !request.tunnel) { |
|
return false |
|
} |
|
|
|
// Setup Proxy Header Exclusive List and White List |
|
if (options.proxyHeaderWhiteList) { |
|
self.proxyHeaderWhiteList = options.proxyHeaderWhiteList |
|
} |
|
if (options.proxyHeaderExclusiveList) { |
|
self.proxyHeaderExclusiveList = options.proxyHeaderExclusiveList |
|
} |
|
|
|
var proxyHeaderExclusiveList = self.proxyHeaderExclusiveList.concat(defaultProxyHeaderExclusiveList) |
|
var proxyHeaderWhiteList = self.proxyHeaderWhiteList.concat(proxyHeaderExclusiveList) |
|
|
|
// Setup Proxy Headers and Proxy Headers Host |
|
// Only send the Proxy White Listed Header names |
|
var proxyHeaders = constructProxyHeaderWhiteList(request.headers, proxyHeaderWhiteList) |
|
proxyHeaders.host = constructProxyHost(request.uri) |
|
|
|
proxyHeaderExclusiveList.forEach(request.removeHeader, request) |
|
|
|
// Set Agent from Tunnel Data |
|
var tunnelFn = getTunnelFn(request) |
|
var tunnelOptions = constructTunnelOptions(request, proxyHeaders) |
|
request.agent = tunnelFn(tunnelOptions) |
|
|
|
return true |
|
} |
|
|
|
Tunnel.defaultProxyHeaderWhiteList = defaultProxyHeaderWhiteList |
|
Tunnel.defaultProxyHeaderExclusiveList = defaultProxyHeaderExclusiveList |
|
exports.Tunnel = Tunnel
|
|
|