var http = require('http'); var https = require('https'); var net = require('net'); var fs = require('fs'); var path = require('path'); var should = require('should'); var tunnel = require('../index'); function readPem(file) { return fs.readFileSync(path.join('test/keys', file + '.pem')); } var serverKey = readPem('server1-key'); var serverCert = readPem('server1-cert'); var serverCA = readPem('ca1-cert'); var clientKey = readPem('client1-key'); var clientCert = readPem('client1-cert'); var clientCA = readPem('ca3-cert'); describe('HTTPS over HTTP', function() { it('should finish without error', function(done) { var serverPort = 3002; var proxyPort = 3003; var poolSize = 3; var N = 10; var serverConnect = 0; var proxyConnect = 0; var clientConnect = 0; var server; var proxy; var agent; server = https.createServer({ key: serverKey, cert: serverCert, ca: [clientCA], requestCert: true, rejectUnauthorized: true }, function(req, res) { tunnel.debug('SERVER: got request'); ++serverConnect; res.writeHead(200); res.end('Hello' + req.url); tunnel.debug('SERVER: sending response'); }); server.listen(serverPort, setupProxy); function setupProxy() { proxy = http.createServer(function(req, res) { should.fail(); }); proxy.on('upgrade', onConnect); // for v0.6 proxy.on('connect', onConnect); // for v0.7 or later function onConnect(req, clientSocket, head) { tunnel.debug('PROXY: got CONNECT request'); req.method.should.equal('CONNECT'); req.url.should.equal('localhost:' + serverPort); req.headers.should.not.have.property('transfer-encoding'); ++proxyConnect; var serverSocket = net.connect(serverPort, function() { tunnel.debug('PROXY: replying to client CONNECT request'); clientSocket.write('HTTP/1.1 200 Connection established\r\n\r\n'); clientSocket.pipe(serverSocket); serverSocket.write(head); serverSocket.pipe(clientSocket); // workaround, see joyent/node#2524 serverSocket.on('end', function() { clientSocket.end(); }); }); } proxy.listen(proxyPort, setupClient); } function setupClient() { agent = tunnel.httpsOverHttp({ maxSockets: poolSize, key: clientKey, cert: clientCert, ca: [serverCA], rejectUnauthorized: true, proxy: { port: proxyPort } }); for (var i = 0; i < N; ++i) { doClientRequest(i); } function doClientRequest(i) { tunnel.debug('CLIENT: Making HTTPS request (%d)', i); var req = https.get({ port: serverPort, path: '/' + i, agent: agent }, function(res) { tunnel.debug('CLIENT: got HTTPS response (%d)', i); res.setEncoding('utf8'); res.on('data', function(data) { data.should.equal('Hello/' + i); }); res.on('end', function() { ++clientConnect; if (clientConnect === N) { proxy.close(); server.close(); } }); }); } } server.on('close', function() { serverConnect.should.equal(N); proxyConnect.should.equal(poolSize); clientConnect.should.equal(N); var name = 'localhost:' + serverPort; agent.sockets.should.be.empty; agent.requests.should.be.empty; done(); }); }); });