1 | 'use strict';
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 | var url = require('url');
|
8 | var LRU = require('lru-cache');
|
9 | var Agent = require('agent-base');
|
10 | var inherits = require('util').inherits;
|
11 | var debug = require('debug')('proxy-agent');
|
12 | var getProxyForUrl = require('proxy-from-env').getProxyForUrl;
|
13 |
|
14 | var http = require('http');
|
15 | var https = require('https');
|
16 | var PacProxyAgent = require('pac-proxy-agent');
|
17 | var HttpProxyAgent = require('http-proxy-agent');
|
18 | var HttpsProxyAgent = require('https-proxy-agent');
|
19 | var SocksProxyAgent = require('socks-proxy-agent');
|
20 |
|
21 |
|
22 |
|
23 |
|
24 |
|
25 | exports = module.exports = ProxyAgent;
|
26 |
|
27 |
|
28 |
|
29 |
|
30 |
|
31 |
|
32 |
|
33 |
|
34 | var cacheSize = 20;
|
35 |
|
36 |
|
37 |
|
38 |
|
39 |
|
40 | exports.cache = new LRU(cacheSize);
|
41 |
|
42 |
|
43 |
|
44 |
|
45 |
|
46 | exports.proxies = Object.create(null);
|
47 | exports.proxies.http = httpOrHttpsProxy;
|
48 | exports.proxies.https = httpOrHttpsProxy;
|
49 | exports.proxies.socks = SocksProxyAgent;
|
50 | exports.proxies.socks4 = SocksProxyAgent;
|
51 | exports.proxies.socks4a = SocksProxyAgent;
|
52 | exports.proxies.socks5 = SocksProxyAgent;
|
53 | exports.proxies.socks5h = SocksProxyAgent;
|
54 |
|
55 | PacProxyAgent.protocols.forEach(function (protocol) {
|
56 | exports.proxies['pac+' + protocol] = PacProxyAgent;
|
57 | });
|
58 |
|
59 | function httpOrHttps(opts, secureEndpoint) {
|
60 | if (secureEndpoint) {
|
61 |
|
62 | return https.globalAgent;
|
63 | } else {
|
64 |
|
65 | return http.globalAgent;
|
66 | }
|
67 | }
|
68 |
|
69 | function httpOrHttpsProxy(opts, secureEndpoint) {
|
70 | if (secureEndpoint) {
|
71 |
|
72 | return new HttpsProxyAgent(opts);
|
73 | } else {
|
74 |
|
75 | return new HttpProxyAgent(opts);
|
76 | }
|
77 | }
|
78 |
|
79 | function mapOptsToProxy(opts) {
|
80 |
|
81 | if (!opts) {
|
82 | return {
|
83 | uri: 'no proxy',
|
84 | fn: httpOrHttps
|
85 | };
|
86 | }
|
87 |
|
88 | if ('string' == typeof opts) opts = url.parse(opts);
|
89 |
|
90 | var proxies;
|
91 | if (opts.proxies) {
|
92 | proxies = Object.assign({}, exports.proxies, opts.proxies);
|
93 | } else {
|
94 | proxies = exports.proxies;
|
95 | }
|
96 |
|
97 |
|
98 | var protocol = opts.protocol;
|
99 | if (!protocol) {
|
100 | throw new TypeError('You must specify a "protocol" for the ' +
|
101 | 'proxy type (' + Object.keys(proxies).join(', ') + ')');
|
102 | }
|
103 |
|
104 |
|
105 | if (':' == protocol[protocol.length - 1]) {
|
106 | protocol = protocol.substring(0, protocol.length - 1);
|
107 | }
|
108 |
|
109 |
|
110 | var proxyFn = proxies[protocol];
|
111 | if ('function' != typeof proxyFn) {
|
112 | throw new TypeError('unsupported proxy protocol: "' + protocol + '"');
|
113 | }
|
114 |
|
115 |
|
116 |
|
117 |
|
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 |
|
133 |
|
134 |
|
135 |
|
136 |
|
137 |
|
138 |
|
139 |
|
140 |
|
141 |
|
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 | }
|
155 | }
|
156 | inherits(ProxyAgent, Agent);
|
157 |
|
158 |
|
159 |
|
160 |
|
161 |
|
162 | function connect (req, opts, fn) {
|
163 | var proxyOpts = this.proxy;
|
164 | var proxyUri = this.proxyUri;
|
165 | var proxyFn = this.proxyFn;
|
166 |
|
167 |
|
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 |
|
176 |
|
177 | var key = proxyUri;
|
178 | if (opts.secureEndpoint) key += ' secure';
|
179 |
|
180 |
|
181 | var agent = exports.cache.get(key);
|
182 | if (!agent) {
|
183 |
|
184 | agent = proxyFn(proxyOpts, opts.secureEndpoint);
|
185 | if (agent) {
|
186 | exports.cache.set(key, agent);
|
187 | }
|
188 | } else {
|
189 | debug('cache hit with key: %o', key);
|
190 | }
|
191 |
|
192 | if (!proxyOpts) {
|
193 | agent.addRequest(req, opts);
|
194 | } else {
|
195 |
|
196 | agent.callback(req, opts, fn);
|
197 | }
|
198 | }
|