UNPKG

monkey-proxy

Version:

fork of tootallnate's proxy, adding hooks for modifying requests

247 lines (221 loc) 6.63 kB
/** * Module dependencies. */ var fs = require('fs'); var net = require('net'); var path = require('path'); var http = require('http'); var https = require('https'); var assert = require('assert'); var setup = require('../'); var stream = require('stream'); describe('proxy', function () { var proxy; var proxyPort; var transformProxy; var transformProxyPort; var responseStream = new stream.PassThrough(); var requestStream = new stream.PassThrough(); var server; var serverPort; before(function (done) { // plain old proxy. function createProxy(cb) { proxy = setup(http.createServer()); proxy.listen(function () { proxyPort = proxy.address().port; return cb(); }); } // proxy that transforms HTTP stream. function createTransformProxy(cb) { transformProxy = setup(http.createServer(), { transformResponse: function() { return responseStream; }, transformRequest: function() { return requestStream; } }); transformProxy.listen(function () { transformProxyPort = transformProxy.address().port; return cb(); }); } createProxy(function() { createTransformProxy(function() { return 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) { transformProxy.once('close', function () { done(); }); transformProxy.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 allow the request and response streams to be transformed', function (done) { var host = '127.0.0.1:' + serverPort; server.once('request', function (req, res) { res.end(); }); var socket = net.connect({ port: transformProxyPort }); socket.once('close', function () { assert(requestStream._writableState.ended); assert(responseStream._writableState.ended); 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) { 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; }); }); }); });