UNPKG

3.12 kBJavaScriptView Raw
1
2/**
3 * Module dependencies.
4 */
5
6var url = require('url');
7var LRU = require('lru-cache');
8var HttpProxyAgent = require('http-proxy-agent');
9var HttpsProxyAgent = require('https-proxy-agent');
10var SocksProxyAgent = require('socks-proxy-agent');
11
12/**
13 * Module exports.
14 */
15
16exports = module.exports = proxy;
17
18/**
19 * Number of `http.Agent` instances to cache.
20 *
21 * This value was arbitrarily chosen... a better
22 * value could be conceived with some benchmarks.
23 */
24
25var cacheSize = 20;
26
27/**
28 * Cache for `http.Agent` instances.
29 */
30
31exports.cache = new LRU(cacheSize);
32
33/**
34 * The built-in proxy types.
35 */
36
37exports.proxies = {
38 http: httpOrHttpsProxy,
39 https: httpOrHttpsProxy,
40 socks: socksProxy
41};
42
43/**
44 * Attempts to get an `http.Agent` instance based off of the given proxy URI
45 * information, and the `secure` flag.
46 *
47 * An LRU cache is used, to prevent unnecessary creation of proxy
48 * `http.Agent` instances.
49 *
50 * @param {String} uri proxy url
51 * @param {Boolean} secure true if this is for an HTTPS request, false for HTTP
52 * @return {http.Agent}
53 * @api public
54 */
55
56function proxy (uri, secure) {
57
58 // parse the URI into an opts object if it's a String
59 var proxyParsed = uri;
60 if ('string' == typeof uri) {
61 proxyParsed = url.parse(uri);
62 }
63
64 // get the requested proxy "protocol"
65 var protocol = proxyParsed.protocol;
66 if (!protocol) {
67 var types = [];
68 for (var type in proxies) types.push(type);
69 throw new TypeError('you must specify a string "protocol" for the proxy type (' + types.join(', ') + ')');
70 }
71
72 // strip the trailing ":" if present
73 if (':' == protocol[protocol.length - 1]) {
74 protocol = protocol.substring(0, protocol.length - 1);
75 }
76
77 // get the proxy `http.Agent` creation function
78 var proxyFn = exports.proxies[protocol];
79 if ('function' != typeof proxyFn) {
80 throw new TypeError('unsupported proxy protocol: "' + protocol + '"');
81 }
82
83 // format the proxy info back into a URI, since an opts object
84 // could have been passed in originally. This generated URI is used
85 // as part of the "key" for the LRU cache
86 var proxyUri = url.format({
87 protocol: protocol + ':',
88 slashes: true,
89 hostname: proxyParsed.hostname || proxyParsed.host,
90 port: proxyParsed.port
91 });
92
93 // create the "key" for the LRU cache
94 var key = proxyUri;
95 if (secure) key += ' secure';
96
97 // attempt to get a cached `http.Agent` instance first
98 var agent = exports.cache.get(key);
99 if (!agent) {
100 // get an `http.Agent` instance from protocol-specific agent function
101 agent = proxyFn(proxyParsed, secure);
102 if (agent) exports.cache.set(key, agent);
103 } else {
104 //console.error('cache hit! %j', key);
105 }
106
107 return agent;
108}
109
110/**
111 * Default "http" and "https" proxy URI handlers.
112 *
113 * @api protected
114 */
115
116function httpOrHttpsProxy (proxy, secure) {
117 if (secure) {
118 // HTTPS
119 return new HttpsProxyAgent(proxy);
120 } else {
121 // HTTP
122 return new HttpProxyAgent(proxy);
123 }
124}
125
126/**
127 * Default "socks" proxy URI handler.
128 *
129 * @api protected
130 */
131
132function socksProxy (proxy, secure) {
133 return new SocksProxyAgent(proxy, secure);
134}