6 var fs = require('fs');
7 var url = require('url');
8 var http = require('http');
9 var https = require('https');
10 var assert = require('assert');
11 var Proxy = require('proxy');
12 var HttpProxyAgent = require('../');
14 describe('HttpProxyAgent', function () {
25 before(function (done) {
26 // setup HTTP proxy server
28 proxy.listen(function () {
29 proxyPort = proxy.address().port;
34 before(function (done) {
35 // setup target HTTP server
36 server = http.createServer();
37 server.listen(function () {
38 serverPort = server.address().port;
43 before(function (done) {
44 // setup SSL HTTP proxy server
46 key: fs.readFileSync(__dirname + '/ssl-cert-snakeoil.key'),
47 cert: fs.readFileSync(__dirname + '/ssl-cert-snakeoil.pem')
49 sslProxy = Proxy(https.createServer(options));
50 sslProxy.listen(function () {
51 sslProxyPort = sslProxy.address().port;
56 // shut down test HTTP server
57 after(function (done) {
58 proxy.once('close', function () { done(); });
62 after(function (done) {
63 server.once('close', function () { done(); });
67 after(function (done) {
68 sslProxy.once('close', function () { done(); });
72 describe('constructor', function () {
73 it('should throw an Error if no "proxy" argument is given', function () {
74 assert.throws(function () {
78 it('should accept a "string" proxy argument', function () {
79 var agent = new HttpProxyAgent('http://127.0.0.1:' + proxyPort);
80 assert.equal('127.0.0.1', agent.proxy.host);
81 assert.equal(proxyPort, agent.proxy.port);
83 it('should accept a `url.parse()` result object argument', function () {
84 var opts = url.parse('http://127.0.0.1:' + proxyPort);
85 var agent = new HttpProxyAgent(opts);
86 assert.equal('127.0.0.1', agent.proxy.host);
87 assert.equal(proxyPort, agent.proxy.port);
89 describe('secureProxy', function () {
90 it('should default to `false`', function () {
91 var agent = new HttpProxyAgent({ port: proxyPort });
92 assert.equal(false, agent.secureProxy);
94 it('should be `false` when "http:" protocol is used', function () {
95 var agent = new HttpProxyAgent({ port: proxyPort, protocol: 'http:' });
96 assert.equal(false, agent.secureProxy);
98 it('should be `true` when "https:" protocol is used', function () {
99 var agent = new HttpProxyAgent({ port: proxyPort, protocol: 'https:' });
100 assert.equal(true, agent.secureProxy);
102 it('should be `true` when "https" protocol is used', function () {
103 var agent = new HttpProxyAgent({ port: proxyPort, protocol: 'https' });
104 assert.equal(true, agent.secureProxy);
109 describe('"http" module', function () {
110 it('should work over an HTTP proxy', function (done) {
111 // set HTTP "request" event handler for this test
112 server.once('request', function (req, res) {
113 res.end(JSON.stringify(req.headers));
116 var proxy = process.env.HTTP_PROXY || process.env.http_proxy || 'http://127.0.0.1:' + proxyPort;
117 var agent = new HttpProxyAgent(proxy);
119 var opts = url.parse('http://127.0.0.1:' + serverPort);
122 http.get(opts, function (res) {
124 res.setEncoding('utf8');
125 res.on('data', function (b) {
128 res.on('end', function () {
129 data = JSON.parse(data);
130 assert.equal('127.0.0.1:' + serverPort, data.host);
131 assert('via' in data);
136 it('should work over an HTTPS proxy', function (done) {
137 // set HTTP "request" event handler for this test
138 server.once('request', function (req, res) {
139 res.end(JSON.stringify(req.headers));
142 var proxy = process.env.HTTPS_PROXY || process.env.https_proxy || 'https://127.0.0.1:' + sslProxyPort;
143 proxy = url.parse(proxy);
144 proxy.rejectUnauthorized = false;
145 var agent = new HttpProxyAgent(proxy);
146 assert.equal(true, agent.secureProxy);
148 var opts = url.parse('http://127.0.0.1:' + serverPort);
151 http.get(opts, function (res) {
153 res.setEncoding('utf8');
154 res.on('data', function (b) {
157 res.on('end', function () {
158 data = JSON.parse(data);
159 assert.equal('127.0.0.1:' + serverPort, data.host);
160 assert('via' in data);
165 it('should proxy the query string of the request path', function (done) {
166 // set HTTP "request" event handler for this test
167 server.once('request', function (req, res) {
168 res.end(JSON.stringify({
173 var proxy = process.env.HTTP_PROXY || process.env.http_proxy || 'http://127.0.0.1:' + proxyPort;
174 var agent = new HttpProxyAgent(proxy);
176 var opts = url.parse('http://127.0.0.1:' + serverPort + '/test?foo=bar&1=2');
179 http.get(opts, function (res) {
181 res.setEncoding('utf8');
182 res.on('data', function (b) {
185 res.on('end', function () {
186 data = JSON.parse(data);
187 assert.equal('/test?foo=bar&1=2', data.url);
192 it('should receive the 407 authorization code on the `http.ClientResponse`', function (done) {
193 // set a proxy authentication function for this test
194 proxy.authenticate = function (req, fn) {
195 // reject all requests
199 var proxyUri = process.env.HTTP_PROXY || process.env.http_proxy || 'http://127.0.0.1:' + proxyPort;
200 var agent = new HttpProxyAgent(proxyUri);
203 // `host` and `port` don't really matter since the proxy will reject anyways
204 opts.host = '127.0.0.1';
208 http.get(opts, function (res) {
209 assert.equal(407, res.statusCode);
210 assert('proxy-authenticate' in res.headers);
211 delete proxy.authenticate;
215 it('should send the "Proxy-Authorization" request header', function (done) {
216 // set a proxy authentication function for this test
217 proxy.authenticate = function (req, fn) {
218 // username:password is "foo:bar"
219 fn(null, req.headers['proxy-authorization'] == 'Basic Zm9vOmJhcg==');
222 // set HTTP "request" event handler for this test
223 server.once('request', function (req, res) {
224 res.end(JSON.stringify(req.headers));
227 var proxyUri = process.env.HTTP_PROXY || process.env.http_proxy || 'http://127.0.0.1:' + proxyPort;
228 var proxyOpts = url.parse(proxyUri);
229 proxyOpts.auth = 'foo:bar';
230 var agent = new HttpProxyAgent(proxyOpts);
232 var opts = url.parse('http://127.0.0.1:' + serverPort);
235 http.get(opts, function (res) {
237 res.setEncoding('utf8');
238 res.on('data', function (b) {
241 res.on('end', function () {
242 data = JSON.parse(data);
243 assert.equal('127.0.0.1:' + serverPort, data.host);
244 assert('via' in data);
245 delete proxy.authenticate;
250 it('should emit an "error" event on the `http.ClientRequest` if the proxy does not exist', function (done) {
251 // port 4 is a reserved, but "unassigned" port
252 var proxyUri = 'http://127.0.0.1:4';
253 var agent = new HttpProxyAgent(proxyUri);
255 var opts = url.parse('http://nodejs.org');
258 var req = http.get(opts);
259 req.once('error', function (err) {
260 assert.equal('ECONNREFUSED', err.code);
265 it('should work after the first tick of the `http.ClientRequest` instance', function (done) {
266 // set HTTP "request" event handler for this test
267 server.once('request', function (req, res) {
268 res.end(JSON.stringify(req.url));
271 var proxy = process.env.HTTP_PROXY || process.env.http_proxy || 'http://127.0.0.1:' + proxyPort;
272 var agent = new HttpProxyAgent(proxy);
274 var opts = url.parse('http://127.0.0.1:' + serverPort + '/test');
277 // defer the "connect()" function logic, since calling .end() before the
278 // "socket" event can cause weirdness since the HTTP header will have been
279 // cached and the HttpProxyAgent `req.path` patches won't be respected
280 var callback = agent.callback;
281 agent.callback = function (req, opts, fn) {
282 setTimeout(function () {
283 agent.callback = callback;
284 agent.callback(req, opts, fn);
288 http.get(opts, function (res) {
290 res.setEncoding('utf8');
291 res.on('data', function (b) {
294 res.on('end', function () {
295 data = JSON.parse(data);
296 assert.equal('/test', data);