var httpProxy = require('../lib/http-proxy'), expect = require('expect.js'), http = require('http'), ws = require('ws') io = require('socket.io'), ioClient = require('socket.io-client'); // // Expose a port number generator. // thanks to @3rd-Eden // var initialPort = 1024, gen = {}; Object.defineProperty(gen, 'port', { get: function get() { return initialPort++; } }); describe('lib/http-proxy.js', function() { describe('#createProxyServer', function() { it.skip('should throw without options', function() { var error; try { httpProxy.createProxyServer(); } catch(e) { error = e; } expect(error).to.be.an(Error); }) it('should return an object otherwise', function() { var obj = httpProxy.createProxyServer({ target: 'http://www.google.com:80' }); expect(obj.web).to.be.a(Function); expect(obj.ws).to.be.a(Function); expect(obj.listen).to.be.a(Function); }); }); describe('#createProxyServer with forward options and using web-incoming passes', function () { it('should pipe the request using web-incoming#stream method', function (done) { var ports = { source: gen.port, proxy: gen.port }; var proxy = httpProxy.createProxyServer({ forward: 'http://127.0.0.1:' + ports.source }).listen(ports.proxy); var source = http.createServer(function(req, res) { expect(req.method).to.eql('GET'); expect(req.headers.host.split(':')[1]).to.eql(ports.proxy); source.close(); proxy.close(); done(); }); source.listen(ports.source); http.request('http://127.0.0.1:' + ports.proxy, function() {}).end(); }) }); describe('#createProxyServer using the web-incoming passes', function () { it('should make the request on pipe and finish it', function(done) { var ports = { source: gen.port, proxy: gen.port }; var proxy = httpProxy.createProxyServer({ target: 'http://127.0.0.1:' + ports.source }).listen(ports.proxy); var source = http.createServer(function(req, res) { expect(req.method).to.eql('POST'); expect(req.headers['x-forwarded-for']).to.eql('127.0.0.1'); expect(req.headers.host.split(':')[1]).to.eql(ports.proxy); source.close(); proxy.close(); done(); }); source.listen(ports.source); http.request({ hostname: '127.0.0.1', port: ports.proxy, method: 'POST', headers: { 'x-forwarded-for': '127.0.0.1' } }, function() {}).end(); }); }); describe('#createProxyServer using the web-incoming passes', function () { it('should make the request, handle response and finish it', function(done) { var ports = { source: gen.port, proxy: gen.port }; var proxy = httpProxy.createProxyServer({ target: 'http://127.0.0.1:' + ports.source }).listen(ports.proxy); var source = http.createServer(function(req, res) { expect(req.method).to.eql('GET'); expect(req.headers.host.split(':')[1]).to.eql(ports.proxy); res.writeHead(200, {'Content-Type': 'text/plain'}) res.end('Hello from ' + source.address().port); }); source.listen(ports.source); http.request({ hostname: '127.0.0.1', port: ports.proxy, method: 'GET' }, function(res) { expect(res.statusCode).to.eql(200); res.on('data', function (data) { expect(data.toString()).to.eql('Hello from ' + ports.source); }); res.on('end', function () { source.close(); proxy.close(); done(); }); }).end(); }); }); describe('#createProxyServer() method with error response', function () { it('should make the request and emit the error event', function(done) { var ports = { source: gen.port, proxy: gen.port }; var proxy = httpProxy.createProxyServer({ target: 'http://127.0.0.1:' + ports.source }); proxy.on('error', function (err) { expect(err).to.be.an(Error); expect(err.code).to.be('ECONNREFUSED'); proxy.close(); done(); }) proxy.listen(ports.proxy); http.request({ hostname: '127.0.0.1', port: ports.proxy, method: 'GET', }, function() {}).end(); }); }); describe('#createProxyServer setting the correct timeout value', function () { it('should hang up the socket at the timeout', function (done) { this.timeout(30); var ports = { source: gen.port, proxy: gen.port }; var proxy = httpProxy.createProxyServer({ target: 'http://127.0.0.1:' + ports.source, timeout: 3 }).listen(ports.proxy); proxy.on('error', function (e) { expect(e).to.be.an(Error); expect(e.code).to.be.eql('ECONNRESET'); }); var source = http.createServer(function(req, res) { setTimeout(function () { res.end('At this point the socket should be closed'); }, 5) }); source.listen(ports.source); var testReq = http.request({ hostname: '127.0.0.1', port: ports.proxy, method: 'GET', }, function() {}); testReq.on('error', function (e) { expect(e).to.be.an(Error); expect(e.code).to.be.eql('ECONNRESET'); proxy.close(); source.close(); done(); }); testReq.end(); }) }) // describe('#createProxyServer using the web-incoming passes', function () { // it('should emit events correclty', function(done) { // var proxy = httpProxy.createProxyServer({ // target: 'http://127.0.0.1:8080' // }), // proxyServer = proxy.listen('8081'), // source = http.createServer(function(req, res) { // expect(req.method).to.eql('GET'); // expect(req.headers.host.split(':')[1]).to.eql('8081'); // res.writeHead(200, {'Content-Type': 'text/plain'}) // res.end('Hello from ' + source.address().port); // }), // events = []; // source.listen('8080'); // proxy.ee.on('http-proxy:**', function (uno, dos, tres) { // events.push(this.event); // }) // http.request({ // hostname: '127.0.0.1', // port: '8081', // method: 'GET', // }, function(res) { // expect(res.statusCode).to.eql(200); // res.on('data', function (data) { // expect(data.toString()).to.eql('Hello from 8080'); // }); // res.on('end', function () { // expect(events).to.contain('http-proxy:outgoing:web:begin'); // expect(events).to.contain('http-proxy:outgoing:web:end'); // source.close(); // proxyServer.close(); // done(); // }); // }).end(); // }); // }); describe('#createProxyServer using the ws-incoming passes', function () { it('should proxy the websockets stream', function (done) { var ports = { source: gen.port, proxy: gen.port }; var proxy = httpProxy.createProxyServer({ target: 'ws://127.0.0.1:' + ports.source, ws: true }), proxyServer = proxy.listen(ports.proxy), destiny = new ws.Server({ port: ports.source }, function () { var client = new ws('ws://127.0.0.1:' + ports.proxy); client.on('open', function () { client.send('hello there'); }); client.on('message', function (msg) { expect(msg).to.be('Hello over websockets'); client.close(); proxyServer.close(); destiny.close(); done(); }); }); destiny.on('connection', function (socket) { socket.on('message', function (msg) { expect(msg).to.be('hello there'); socket.send('Hello over websockets'); }); }); }); it('should emit error on proxy error', function (done) { var ports = { source: gen.port, proxy: gen.port }; var proxy = httpProxy.createProxyServer({ // note: we don't ever listen on this port target: 'ws://127.0.0.1:' + ports.source, ws: true }), proxyServer = proxy.listen(ports.proxy), client = new ws('ws://127.0.0.1:' + ports.proxy); client.on('open', function () { client.send('hello there'); }); client.on('error', function (err) { expect(err).to.be.an(Error); expect(err.code).to.be('ECONNRESET'); }); proxy.on('error', function (err) { expect(err).to.be.an(Error); expect(err.code).to.be('ECONNREFUSED'); proxyServer.close(); done(); }); }); it('should close client socket if upstream is closed before upgrade', function (done) { var ports = { source: gen.port, proxy: gen.port }; var server = http.createServer(); server.on('upgrade', function (req, socket, head) { var response = [ 'HTTP/1.1 404 Not Found', 'Content-type: text/html', '', '' ]; socket.write(response.join('\r\n')); socket.end(); }); server.listen(ports.source); var proxy = httpProxy.createProxyServer({ // note: we don't ever listen on this port target: 'ws://127.0.0.1:' + ports.source, ws: true }), proxyServer = proxy.listen(ports.proxy), client = new ws('ws://127.0.0.1:' + ports.proxy); client.on('open', function () { client.send('hello there'); }); client.on('error', function (err) { expect(err).to.be.an(Error); expect(err.code).to.be('ECONNRESET'); proxyServer.close(); done(); }); }); it('should proxy a socket.io stream', function (done) { var ports = { source: gen.port, proxy: gen.port }; var proxy = httpProxy.createProxyServer({ target: 'ws://127.0.0.1:' + ports.source, ws: true }); proxyServer = proxy.listen(ports.proxy); var server = http.createServer(); destiny = io.listen(server); function startSocketIo() { var client = ioClient.connect('ws://127.0.0.1:' + ports.proxy); client.on('connect', function () { client.emit('incoming', 'hello there'); }); client.on('outgoing', function (data) { expect(data).to.be('Hello over websockets'); proxyServer.close(); server.close(); done(); }); } server.listen(ports.source); server.on('listening', startSocketIo); destiny.sockets.on('connection', function (socket) { socket.on('incoming', function (msg) { expect(msg).to.be('hello there'); socket.emit('outgoing', 'Hello over websockets'); }); }) }); }) });