Initial commit
[yaffs-website] / node_modules / request / lib / tunnel.js
1 'use strict'
2
3 var url = require('url')
4   , tunnel = require('tunnel-agent')
5
6 var defaultProxyHeaderWhiteList = [
7   'accept',
8   'accept-charset',
9   'accept-encoding',
10   'accept-language',
11   'accept-ranges',
12   'cache-control',
13   'content-encoding',
14   'content-language',
15   'content-location',
16   'content-md5',
17   'content-range',
18   'content-type',
19   'connection',
20   'date',
21   'expect',
22   'max-forwards',
23   'pragma',
24   'referer',
25   'te',
26   'user-agent',
27   'via'
28 ]
29
30 var defaultProxyHeaderExclusiveList = [
31   'proxy-authorization'
32 ]
33
34 function constructProxyHost(uriObject) {
35   var port = uriObject.port
36     , protocol = uriObject.protocol
37     , proxyHost = uriObject.hostname + ':'
38
39   if (port) {
40     proxyHost += port
41   } else if (protocol === 'https:') {
42     proxyHost += '443'
43   } else {
44     proxyHost += '80'
45   }
46
47   return proxyHost
48 }
49
50 function constructProxyHeaderWhiteList(headers, proxyHeaderWhiteList) {
51   var whiteList = proxyHeaderWhiteList
52     .reduce(function (set, header) {
53       set[header.toLowerCase()] = true
54       return set
55     }, {})
56
57   return Object.keys(headers)
58     .filter(function (header) {
59       return whiteList[header.toLowerCase()]
60     })
61     .reduce(function (set, header) {
62       set[header] = headers[header]
63       return set
64     }, {})
65 }
66
67 function constructTunnelOptions (request, proxyHeaders) {
68   var proxy = request.proxy
69
70   var tunnelOptions = {
71     proxy : {
72       host      : proxy.hostname,
73       port      : +proxy.port,
74       proxyAuth : proxy.auth,
75       headers   : proxyHeaders
76     },
77     headers            : request.headers,
78     ca                 : request.ca,
79     cert               : request.cert,
80     key                : request.key,
81     passphrase         : request.passphrase,
82     pfx                : request.pfx,
83     ciphers            : request.ciphers,
84     rejectUnauthorized : request.rejectUnauthorized,
85     secureOptions      : request.secureOptions,
86     secureProtocol     : request.secureProtocol
87   }
88
89   return tunnelOptions
90 }
91
92 function constructTunnelFnName(uri, proxy) {
93   var uriProtocol = (uri.protocol === 'https:' ? 'https' : 'http')
94   var proxyProtocol = (proxy.protocol === 'https:' ? 'Https' : 'Http')
95   return [uriProtocol, proxyProtocol].join('Over')
96 }
97
98 function getTunnelFn(request) {
99   var uri = request.uri
100   var proxy = request.proxy
101   var tunnelFnName = constructTunnelFnName(uri, proxy)
102   return tunnel[tunnelFnName]
103 }
104
105
106 function Tunnel (request) {
107   this.request = request
108   this.proxyHeaderWhiteList = defaultProxyHeaderWhiteList
109   this.proxyHeaderExclusiveList = []
110   if (typeof request.tunnel !== 'undefined') {
111     this.tunnelOverride = request.tunnel
112   }
113 }
114
115 Tunnel.prototype.isEnabled = function () {
116   var self = this
117     , request = self.request
118   // Tunnel HTTPS by default. Allow the user to override this setting.
119
120   // If self.tunnelOverride is set (the user specified a value), use it.
121   if (typeof self.tunnelOverride !== 'undefined') {
122     return self.tunnelOverride
123   }
124
125   // If the destination is HTTPS, tunnel.
126   if (request.uri.protocol === 'https:') {
127     return true
128   }
129
130   // Otherwise, do not use tunnel.
131   return false
132 }
133
134 Tunnel.prototype.setup = function (options) {
135   var self = this
136     , request = self.request
137
138   options = options || {}
139
140   if (typeof request.proxy === 'string') {
141     request.proxy = url.parse(request.proxy)
142   }
143
144   if (!request.proxy || !request.tunnel) {
145     return false
146   }
147
148   // Setup Proxy Header Exclusive List and White List
149   if (options.proxyHeaderWhiteList) {
150     self.proxyHeaderWhiteList = options.proxyHeaderWhiteList
151   }
152   if (options.proxyHeaderExclusiveList) {
153     self.proxyHeaderExclusiveList = options.proxyHeaderExclusiveList
154   }
155
156   var proxyHeaderExclusiveList = self.proxyHeaderExclusiveList.concat(defaultProxyHeaderExclusiveList)
157   var proxyHeaderWhiteList = self.proxyHeaderWhiteList.concat(proxyHeaderExclusiveList)
158
159   // Setup Proxy Headers and Proxy Headers Host
160   // Only send the Proxy White Listed Header names
161   var proxyHeaders = constructProxyHeaderWhiteList(request.headers, proxyHeaderWhiteList)
162   proxyHeaders.host = constructProxyHost(request.uri)
163
164   proxyHeaderExclusiveList.forEach(request.removeHeader, request)
165
166   // Set Agent from Tunnel Data
167   var tunnelFn = getTunnelFn(request)
168   var tunnelOptions = constructTunnelOptions(request, proxyHeaders)
169   request.agent = tunnelFn(tunnelOptions)
170
171   return true
172 }
173
174 Tunnel.defaultProxyHeaderWhiteList = defaultProxyHeaderWhiteList
175 Tunnel.defaultProxyHeaderExclusiveList = defaultProxyHeaderExclusiveList
176 exports.Tunnel = Tunnel