| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175 | '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 = defaultProxyHeaderWhiteListTunnel.defaultProxyHeaderExclusiveList = defaultProxyHeaderExclusiveListexports.Tunnel = Tunnel
 |