/** * Module dependencies. */ const fs = require('fs'); const net = require('net'); const path = require('path'); const http = require('http'); const https = require('https'); const assert = require('assert'); const setup = require('../'); describe('proxy', function() { var proxy; var proxyPort; var server; var serverPort; before(function(done) { // setup proxy server proxy = setup(http.createServer()); proxy.listen(function() { proxyPort = proxy.address().port; done(); }); }); before(function(done) { // setup target server server = http.createServer(); server.listen(function() { serverPort = server.address().port; done(); }); }); after(function(done) { proxy.once('close', function() { done(); }); proxy.close(); }); after(function(done) { server.once('close', function() { done(); }); server.close(); }); it('should proxy HTTP GET requests', function(done) { var gotData = false; var gotRequest = false; var host = '127.0.0.1:' + serverPort; server.once('request', function(req, res) { gotRequest = true; // ensure headers are being proxied assert(req.headers['user-agent'] == 'curl/7.30.0'); assert(req.headers.host == host); assert(req.headers.accept == '*/*'); res.end(); }); var socket = net.connect({ port: proxyPort }); socket.once('close', function() { assert(gotData); assert(gotRequest); done(); }); socket.once('connect', function() { socket.write( 'GET http://' + host + '/ HTTP/1.1\r\n' + 'User-Agent: curl/7.30.0\r\n' + 'Host: ' + host + '\r\n' + 'Accept: */*\r\n' + 'Proxy-Connection: Keep-Alive\r\n' + '\r\n' ); }); socket.setEncoding('utf8'); socket.once('data', function(data) { assert(0 == data.indexOf('HTTP/1.1 200 OK\r\n')); gotData = true; socket.destroy(); }); }); it('should establish connection for CONNECT requests', function(done) { var gotData = false; var socket = net.connect({ port: proxyPort }); socket.once('close', function() { assert(gotData); done(); }); socket.once('connect', function() { var host = '127.0.0.1:' + serverPort; socket.write( 'CONNECT ' + host + ' HTTP/1.1\r\n' + 'Host: ' + host + '\r\n' + 'User-Agent: curl/7.30.0\r\n' + 'Proxy-Connection: Keep-Alive\r\n' + '\r\n' ); }); socket.setEncoding('utf8'); socket.once('data', function(data) { assert( 0 == data.indexOf('HTTP/1.1 200 Connection established\r\n') ); gotData = true; socket.destroy(); }); }); describe('authentication', function() { function clearAuth() { delete proxy.authenticate; } before(clearAuth); after(clearAuth); it('should invoke the `server.authenticate()` function when set', function(done) { var auth = 'Basic Zm9vOmJhcg=='; var called = false; proxy.authenticate = function(req, fn) { assert(auth == req.headers['proxy-authorization']); socket.destroy(); called = true; }; var socket = net.connect({ port: proxyPort }); socket.once('close', function() { assert(called); done(); }); socket.once('connect', function() { socket.write( 'GET / HTTP/1.1\r\n' + 'Proxy-Authorization: ' + auth + '\r\n' + '\r\n' ); }); }); it('should provide the HTTP client with a 407 response status code', function(done) { proxy.authenticate = function(req, fn) { // reject everything fn(null, false); }; var gotData = false; var socket = net.connect({ port: proxyPort }); socket.once('close', function() { assert(gotData); done(); }); socket.once('connect', function() { socket.write('GET / HTTP/1.1\r\n\r\n'); }); socket.setEncoding('utf8'); socket.once('data', function(data) { assert(0 == data.indexOf('HTTP/1.1 407')); gotData = true; socket.destroy(); }); }); it("should close the socket after a CONNECT request's 407 response status code", function(done) { proxy.authenticate = function(req, fn) { // reject everything fn(null, false); }; var gotData = false; var socket = net.connect({ port: proxyPort }); socket.once('close', function() { assert(gotData); done(); }); socket.once('connect', function() { socket.write('CONNECT 127.0.0.1:80 HTTP/1.1\r\n\r\n'); }); socket.setEncoding('utf8'); socket.once('data', function(data) { assert(0 == data.indexOf('HTTP/1.1 407')); gotData = true; }); }); }); });