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.
		
		
		
		
		
			
		
			
				
					176 lines
				
				4.3 KiB
			
		
		
			
		
	
	
					176 lines
				
				4.3 KiB
			| 
								 
											3 years ago
										 
									 | 
							
								'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
							 |