/** * Module dependencies. */ var fs = require('fs'); var url = require('url'); var http = require('http'); var https = require('https'); var assert = require('assert'); var getRawBody = require('raw-body'); var Proxy = require('proxy'); var socks = require('socksv5'); var PacProxyAgent = require('../'); describe('PacProxyAgent', function () { // target servers var httpServer, httpPort; var httpsServer, httpsPort; // proxy servers var socksServer, socksPort; var proxyServer, proxyPort; var proxyHttpsServer, proxyHttpsPort; before(function (done) { // setup target HTTP server httpServer = http.createServer(); httpServer.listen(function () { httpPort = httpServer.address().port; done(); }); }); before(function (done) { // setup target SSL HTTPS server var options = { key: fs.readFileSync(__dirname + '/ssl-cert-snakeoil.key'), cert: fs.readFileSync(__dirname + '/ssl-cert-snakeoil.pem') }; httpsServer = https.createServer(options); httpsServer.listen(function () { httpsPort = httpsServer.address().port; done(); }); }); before(function (done) { // setup SOCKS proxy server socksServer = socks.createServer(function(info, accept, deny) { accept(); }); socksServer.listen(function() { socksPort = socksServer.address().port; done(); }); socksServer.useAuth(socks.auth.None()); }); before(function (done) { // setup HTTP proxy server proxyServer = Proxy(); proxyServer.listen(function () { proxyPort = proxyServer.address().port; done(); }); }); before(function (done) { // setup SSL HTTPS proxy server var options = { key: fs.readFileSync(__dirname + '/ssl-cert-snakeoil.key'), cert: fs.readFileSync(__dirname + '/ssl-cert-snakeoil.pem') }; proxyHttpsServer = Proxy(https.createServer(options)); proxyHttpsServer.listen(function () { proxyHttpsPort = proxyHttpsServer.address().port; done(); }); }); after(function (done) { socksServer.once('close', function () { done(); }); socksServer.close(); }); after(function (done) { httpServer.once('close', function () { done(); }); httpServer.close(); }); after(function (done) { httpsServer.once('close', function () { done(); }); httpsServer.close(); }); after(function (done) { proxyServer.once('close', function () { done(); }); proxyServer.close(); }); after(function (done) { proxyHttpsServer.once('close', function () { done(); }); proxyHttpsServer.close(); }); it('should allow a `sandbox` to be passed in', function (done) { this.slow(1000); function FindProxyForURL(url, host) { throw new Error(foo() + bar()); } function foo () { return 'hi'; } function asyncBar(fn) { setTimeout(function () { fn(null, 'fooooo'); }, 200); } asyncBar.async = true; var uri = 'data:,' + encodeURIComponent(FindProxyForURL.toString()); var agent = new PacProxyAgent(uri, { sandbox: { foo: foo, bar: asyncBar } }); var opts = url.parse('http://127.0.0.1:' + httpPort + '/test'); opts.agent = agent; var req = http.get(opts); req.once('error', function (err) { assert.equal(err.message, 'hifooooo'); done(); }); }); describe('constructor', function () { it('should throw an Error if no "proxy" argument is given', function () { assert.throws(function () { new PacProxyAgent(); }); }); it('should accept a "string" proxy argument', function () { var agent = new PacProxyAgent('pac+ftp://example.com/proxy.pac'); assert.equal('ftp://example.com/proxy.pac', agent.uri); }); it('should accept a `url.parse()` result object argument', function () { var opts = url.parse('pac+ftp://example.com/proxy.pac'); var agent = new PacProxyAgent(opts); assert.equal('ftp://example.com/proxy.pac', agent.uri); }); it('should accept a `uri` on the options object', function () { var agent = new PacProxyAgent({ uri: 'pac+ftp://example.com/proxy.pac' }); assert.equal('ftp://example.com/proxy.pac', agent.uri); }); }); describe('"http" module', function () { it('should work over an HTTP proxy', function (done) { httpServer.once('request', function (req, res) { res.end(JSON.stringify(req.headers)); }); function FindProxyForURL(url, host) { return "PROXY 127.0.0.1:PORT;" } var uri = 'data:,' + encodeURIComponent(FindProxyForURL.toString().replace('PORT', proxyPort)); var agent = new PacProxyAgent(uri); var opts = url.parse('http://127.0.0.1:' + httpPort + '/test'); opts.agent = agent; var req = http.get(opts, function (res) { getRawBody(res, 'utf8', function (err, buf) { if (err) return done(err); var data = JSON.parse(buf); assert.equal('127.0.0.1:' + httpPort, data.host); assert('via' in data); done(); }); }); req.once('error', done); }); it('should work over an HTTPS proxy', function (done) { httpServer.once('request', function (req, res) { res.end(JSON.stringify(req.headers)); }); function FindProxyForURL(url, host) { return "HTTPS 127.0.0.1:PORT;" } var uri = 'data:,' + encodeURIComponent(FindProxyForURL.toString().replace('PORT', proxyHttpsPort)); var proxy = url.parse(uri); proxy.rejectUnauthorized = false; var agent = new PacProxyAgent(proxy); var opts = url.parse('http://127.0.0.1:' + httpPort + '/test'); opts.agent = agent; var req = http.get(opts, function (res) { getRawBody(res, 'utf8', function (err, buf) { if (err) return done(err); var data = JSON.parse(buf); assert.equal('127.0.0.1:' + httpPort, data.host); assert('via' in data); done(); }); }); req.once('error', done); }); it('should work over a SOCKS proxy', function (done) { httpServer.once('request', function (req, res) { res.end(JSON.stringify(req.headers)); }); function FindProxyForURL(url, host) { return "SOCKS 127.0.0.1:PORT;" } var uri = 'data:,' + encodeURIComponent(FindProxyForURL.toString().replace('PORT', socksPort)); var agent = new PacProxyAgent(uri); var opts = url.parse('http://127.0.0.1:' + httpPort + '/test'); opts.agent = agent; var req = http.get(opts, function (res) { getRawBody(res, 'utf8', function (err, buf) { if (err) return done(err); var data = JSON.parse(buf); assert.equal('127.0.0.1:' + httpPort, data.host); done(); }); }); req.once('error', done); }); }); describe('"https" module', function () { it('should work over an HTTP proxy', function (done) { httpsServer.once('request', function (req, res) { res.end(JSON.stringify(req.headers)); }); function FindProxyForURL(url, host) { return "PROXY 127.0.0.1:PORT;" } var uri = 'data:,' + encodeURIComponent(FindProxyForURL.toString().replace('PORT', proxyPort)); var agent = new PacProxyAgent(uri); var opts = url.parse('https://127.0.0.1:' + httpsPort + '/test'); opts.agent = agent; opts.rejectUnauthorized = false; var req = https.get(opts, function (res) { getRawBody(res, 'utf8', function (err, buf) { if (err) return done(err); var data = JSON.parse(buf); assert.equal('127.0.0.1:' + httpsPort, data.host); done(); }); }); req.once('error', done); }); it('should work over an HTTPS proxy', function (done) { var gotReq = false; httpsServer.once('request', function (req, res) { gotReq = true; res.end(JSON.stringify(req.headers)); }); function FindProxyForURL(url, host) { return "HTTPS 127.0.0.1:PORT;" } var uri = 'data:,' + encodeURIComponent(FindProxyForURL.toString().replace('PORT', proxyHttpsPort)); var agent = new PacProxyAgent(uri, { rejectUnauthorized: false }); var opts = url.parse('https://127.0.0.1:' + httpsPort + '/test'); opts.agent = agent; opts.rejectUnauthorized = false; var req = https.get(opts, function (res) { getRawBody(res, 'utf8', function (err, buf) { if (err) return done(err); var data = JSON.parse(buf); assert.equal('127.0.0.1:' + httpsPort, data.host); assert(gotReq); done(); }); }); req.once('error', done); }); it('should work over a SOCKS proxy', function (done) { var gotReq = false; httpsServer.once('request', function (req, res) { gotReq = true; res.end(JSON.stringify(req.headers)); }); function FindProxyForURL(url, host) { return "SOCKS 127.0.0.1:PORT;" } var uri = 'data:,' + encodeURIComponent(FindProxyForURL.toString().replace('PORT', socksPort)); var agent = new PacProxyAgent(uri); var opts = url.parse('https://127.0.0.1:' + httpsPort + '/test'); opts.agent = agent; opts.rejectUnauthorized = false; var req = https.get(opts, function (res) { getRawBody(res, 'utf8', function (err, buf) { if (err) return done(err); var data = JSON.parse(buf); assert.equal('127.0.0.1:' + httpsPort, data.host); assert(gotReq); done(); }); }); req.once('error', done); }); }); });