@@ -9,7 +9,10 @@ var LRU = require('lru-cache');
9
9
var Agent = require ( 'agent-base' ) ;
10
10
var inherits = require ( 'util' ) . inherits ;
11
11
var debug = require ( 'debug' ) ( 'proxy-agent' ) ;
12
+ var getProxyForUrl = require ( 'proxy-from-env' ) . getProxyForUrl ;
12
13
14
+ var HttpAgent = require ( 'http' ) . Agent ;
15
+ var HttpsAgent = require ( 'https' ) . Agent ;
13
16
var PacProxyAgent = require ( 'pac-proxy-agent' ) ;
14
17
var HttpProxyAgent = require ( 'http-proxy-agent' ) ;
15
18
var HttpsProxyAgent = require ( 'https-proxy-agent' ) ;
@@ -53,7 +56,17 @@ PacProxyAgent.protocols.forEach(function (protocol) {
53
56
exports . proxies [ 'pac+' + protocol ] = PacProxyAgent ;
54
57
} ) ;
55
58
56
- function httpOrHttpsProxy ( opts , secureEndpoint ) {
59
+ function httpOrHttps ( opts , secureEndpoint ) {
60
+ if ( secureEndpoint ) {
61
+ // HTTPS
62
+ return new HttpsAgent ( ) ;
63
+ } else {
64
+ // HTTP
65
+ return new HttpAgent ( )
66
+ }
67
+ }
68
+
69
+ function httpOrHttpsProxy ( opts , secureEndpoint ) {
57
70
if ( secureEndpoint ) {
58
71
// HTTPS
59
72
return new HttpsProxyAgent ( opts ) ;
@@ -63,25 +76,16 @@ function httpOrHttpsProxy (opts, secureEndpoint) {
63
76
}
64
77
}
65
78
66
- /**
67
- * Attempts to get an `http.Agent` instance based off of the given proxy URI
68
- * information, and the `secure` flag.
69
- *
70
- * An LRU cache is used, to prevent unnecessary creation of proxy
71
- * `http.Agent` instances.
72
- *
73
- * @param {String } uri proxy url
74
- * @param {Boolean } secure true if this is for an HTTPS request, false for HTTP
75
- * @return {http.Agent }
76
- * @api public
77
- */
79
+ function mapOptsToProxy ( opts ) {
80
+ // NO_PROXY case
81
+ if ( ! opts ) {
82
+ return {
83
+ uri : 'no proxy' ,
84
+ fn : httpOrHttps
85
+ } ;
86
+ }
78
87
79
- function ProxyAgent ( opts ) {
80
- if ( ! ( this instanceof ProxyAgent ) ) return new ProxyAgent ( opts ) ;
81
88
if ( 'string' == typeof opts ) opts = url . parse ( opts ) ;
82
- if ( ! opts ) throw new TypeError ( 'an HTTP(S) proxy server `host` and `protocol` must be specified!' ) ;
83
- debug ( 'creating new ProxyAgent instance: %o' , opts ) ;
84
- Agent . call ( this , connect ) ;
85
89
86
90
var proxies ;
87
91
if ( opts . proxies ) {
@@ -108,18 +112,46 @@ function ProxyAgent (opts) {
108
112
throw new TypeError ( 'unsupported proxy protocol: "' + protocol + '"' ) ;
109
113
}
110
114
111
- this . proxy = opts ;
112
115
// format the proxy info back into a URI, since an opts object
113
116
// could have been passed in originally. This generated URI is used
114
117
// as part of the "key" for the LRU cache
115
- this . proxyUri = url . format ( {
116
- protocol : protocol + ':' ,
117
- slashes : true ,
118
- auth :opts . auth ,
119
- hostname : opts . hostname || opts . host ,
120
- port : opts . port
121
- } ) ;
122
- this . proxyFn = proxyFn ;
118
+ return {
119
+ opts : opts ,
120
+ uri : url . format ( {
121
+ protocol : protocol + ':' ,
122
+ slashes : true ,
123
+ auth : opts . auth ,
124
+ hostname : opts . hostname || opts . host ,
125
+ port : opts . port
126
+ } ) ,
127
+ fn : proxyFn ,
128
+ }
129
+ }
130
+
131
+ /**
132
+ * Attempts to get an `http.Agent` instance based off of the given proxy URI
133
+ * information, and the `secure` flag.
134
+ *
135
+ * An LRU cache is used, to prevent unnecessary creation of proxy
136
+ * `http.Agent` instances.
137
+ *
138
+ * @param {String } uri proxy url
139
+ * @param {Boolean } secure true if this is for an HTTPS request, false for HTTP
140
+ * @return {http.Agent }
141
+ * @api public
142
+ */
143
+
144
+ function ProxyAgent ( opts ) {
145
+ if ( ! ( this instanceof ProxyAgent ) ) return new ProxyAgent ( opts ) ;
146
+ debug ( 'creating new ProxyAgent instance: %o' , opts ) ;
147
+ Agent . call ( this , connect ) ;
148
+
149
+ if ( opts ) {
150
+ var proxy = mapOptsToProxy ( opts ) ;
151
+ this . proxy = proxy . opts ;
152
+ this . proxyUri = proxy . uri ;
153
+ this . proxyFn = proxy . fn ;
154
+ }
123
155
}
124
156
inherits ( ProxyAgent , Agent ) ;
125
157
@@ -128,22 +160,37 @@ inherits(ProxyAgent, Agent);
128
160
*/
129
161
130
162
function connect ( req , opts , fn ) {
163
+ var proxyOpts = this . proxy ;
164
+ var proxyUri = this . proxyUri ;
165
+ var proxyFn = this . proxyFn ;
166
+
167
+ // if we did not instantiate with a proxy, set one per request
168
+ if ( ! proxyOpts ) {
169
+ var urlOpts = getProxyForUrl ( opts ) ;
170
+ var proxy = mapOptsToProxy ( urlOpts , opts ) ;
171
+ proxyOpts = proxy . opts ;
172
+ proxyUri = proxy . uri ;
173
+ proxyFn = proxy . fn ;
174
+ }
175
+
131
176
// create the "key" for the LRU cache
132
- var key = this . proxyUri ;
177
+ var key = proxyUri ;
133
178
if ( opts . secureEndpoint ) key += ' secure' ;
134
179
135
180
// attempt to get a cached `http.Agent` instance first
136
181
var agent = exports . cache . get ( key ) ;
137
182
if ( ! agent ) {
138
183
// get an `http.Agent` instance from protocol-specific agent function
139
- agent = this . proxyFn ( this . proxy , opts . secureEndpoint ) ;
184
+ agent = proxyFn ( proxyOpts , opts . secureEndpoint ) ;
140
185
if ( agent ) exports . cache . set ( key , agent ) ;
141
186
} else {
142
187
debug ( 'cache hit with key: %o' , key ) ;
143
188
}
144
189
145
- // XXX: agent.callback() is an agent-base-ism
146
- // TODO: add support for generic `http.Agent` instances by calling
147
- // agent.addRequest(), but with support for <= 0.10.x and >= 0.12.x
148
- agent . callback ( req , opts , fn ) ;
190
+ if ( ! proxyOpts ) {
191
+ agent . addRequest ( req , opts ) ;
192
+ } else {
193
+ // XXX: agent.callback() is an agent-base-ism
194
+ agent . callback ( req , opts , fn ) ;
195
+ }
149
196
}
0 commit comments