Commit e39a9f93 authored by indexzero's avatar indexzero

[api] Further work on refactor for node 0.4.0

parent 9faa924a
This diff is collapsed.
......@@ -28,27 +28,39 @@ var util = require('util'),
events = require('events'),
fs = require('fs');
var ProxyTable = function (router, silent) {
//
// ### function ProxyTable (router, silent)
// #### @router {Object} Object containing the host based routes
// #### @silent {Boolean} Value indicating whether we should suppress logs
// Constructor function for the ProxyTable responsible for getting
// locations of proxy targets based on ServerRequest headers; specifically
// the HTTP host header.
//
var ProxyTable = exports.ProxyTable = function (router, silent) {
events.EventEmitter.call(this);
this.silent = typeof silent !== 'undefined' ? silent : true;
if (typeof router === 'object') {
//
// If we are passed an object literal setup
// the routes with RegExps from the router
this.updateRoutes(router);
//
this.setRoutes(router);
}
else if (typeof router === 'string') {
//
// If we are passed a string then assume it is a
// file path, parse that file and watch it for changes
//
var self = this;
this.routeFile = router;
this.updateRoutes(JSON.parse(fs.readFileSync(router)).router);
this.setRoutes(JSON.parse(fs.readFileSync(router)).router);
fs.watchFile(this.routeFile, function (c,p) {
fs.readFile(self.routeFile, function (err, data) {
if (err) throw err;
self.updateRoutes(JSON.parse(data).router);
self.emit('updateRoutes', self.routes);
self.setRoutes(JSON.parse(data).router);
self.emit('routes', self.routes);
});
});
}
......@@ -57,9 +69,15 @@ var ProxyTable = function (router, silent) {
}
};
// Inherit from events.EventEmitter
util.inherits(ProxyTable, events.EventEmitter);
ProxyTable.prototype.updateRoutes = function (router) {
//
// ### function setRoutes (router)
// #### @router {Object} Object containing the host based routes
// Sets the host-based routes to be used by this instance.
//
ProxyTable.prototype.setRoutes = function (router) {
if (!router) throw new Error('Cannot update ProxyTable routes without router.');
var self = this;
......@@ -76,8 +94,14 @@ ProxyTable.prototype.updateRoutes = function (router) {
});
};
ProxyTable.prototype.proxyRequest = function (proxy) {
var target = proxy.req.headers.host.split(':')[0] + proxy.req.url;
//
// ### function getProxyLocation (req)
// #### @req {ServerRequest} The incoming server request to get proxy information about.
// Returns the proxy location based on the HTTP Headers in the ServerRequest `req`
// available to this instance.
//
ProxyTable.prototype.getProxyLocation = function (req) {
var target = req.headers.host.split(':')[0] + req.url;
for (var i in this.routes) {
var match, route = this.routes[i];
if (match = target.match(route.route)) {
......@@ -89,25 +113,23 @@ ProxyTable.prototype.proxyRequest = function (proxy) {
util.log('Proxy Table proxying request to: ' + host + ':' + port);
}
proxy.proxyRequest(port, host);
return;
return {
port: port,
host: host
};
}
}
if (proxy.res) {
proxy.res.writeHead(404, {'Content-Type': 'text/plain'});
proxy.res.end();
}
else if (proxy.sock) {
// Remark: How do we perform '404' over a socket?
proxy.sock.destroy();
}
return null;
};
//
// ### close function ()
// Cleans up the event listeneners maintained
// by this instance.
//
ProxyTable.prototype.close = function () {
if (typeof this.routeFile === 'string') {
fs.unwatchFile(this.routeFile);
}
};
\ No newline at end of file
exports.ProxyTable = ProxyTable;
\ No newline at end of file
/*
* forward-proxy-test.js: Tests for node-http-proxy forwarding functionality.
*
* (C) 2010, Charlie Robbins
*
*/
var fs = require('fs'),
vows = require('vows'),
util = require('util'),
path = require('path'),
request = require('request'),
assert = require('assert'),
helpers = require('./helpers');
var runner = new helpers.TestRunner(),
assertProxiedWithTarget = helpers.assertProxiedWithTarget,
assertProxiedWithNoTarget = helpers.assertProxiedWithNoTarget;
var forwardOptions = {
forward: {
port: 8300,
host: 'localhost'
}
};
var badForwardOptions = {
forward: {
port: 9000,
host: 'localhost'
}
};
vows.describe('node-http-proxy/forward-proxy').addBatch({
"When using server created by httpProxy.createServer()": {
"with forwarding enabled": {
topic: function () {
runner.startTargetServer(8300, 'forward proxy');
return null;
},
"with no latency" : {
"and a valid target server": assertProxiedWithTarget(runner, 'localhost', 8120, 8121, function () {
runner.startProxyServerWithForwarding(8120, 8121, 'localhost', forwardOptions);
}),
"and without a valid forward server": assertProxiedWithTarget(runner, 'localhost', 8122, 8123, function () {
runner.startProxyServerWithForwarding(8122, 8123, 'localhost', badForwardOptions);
})
}
}
}
}).addBatch({
"When the tests are over": {
topic: function () {
return runner.closeServers();
},
"the servers should clean up": function () {
assert.isTrue(true);
}
}
}).export(module);
\ No newline at end of file
......@@ -17,7 +17,7 @@ exports.assertProxiedWithTarget = function (runner, host, proxyPort, port, creat
var test = {
topic: function () {
var options = {
var that = this, options = {
method: 'GET',
uri: 'http://localhost:' + proxyPort,
headers: {
......@@ -25,13 +25,22 @@ exports.assertProxiedWithTarget = function (runner, host, proxyPort, port, creat
}
};
if (createProxy) createProxy();
if (port) runner.startTargetServer(port, output);
function startTest () {
if (port) {
return runner.startTargetServer(port, output, function () {
request(options, that.callback);
});
}
request(options, this.callback);
}
return createProxy ? createProxy(startTest) : startTest();
}
};
test[assertion] = function (err, res, body) {
test[assertion] = function (err, res, body) {;
assert.isNull(err);
assert.equal(body, output);
};
......@@ -43,7 +52,7 @@ exports.assertProxiedWithNoTarget = function (runner, proxyPort, statusCode, cre
var test = {
topic: function () {
var options = {
var that = this, options = {
method: 'GET',
uri: 'http://localhost:' + proxyPort,
headers: {
......@@ -51,12 +60,18 @@ exports.assertProxiedWithNoTarget = function (runner, proxyPort, statusCode, cre
}
};
if (createProxy) createProxy();
if (createProxy) {
return createProxy(function () {
request(options, that.callback);
});
}
request(options, this.callback);
}
};
test[assertion] = function (err, res, body) {
assert.isNull(err);
assert.equal(res.statusCode, statusCode);
};
......@@ -65,89 +80,98 @@ exports.assertProxiedWithNoTarget = function (runner, proxyPort, statusCode, cre
var TestRunner = exports.TestRunner = function () {
this.testServers = [];
}
};
//
// Creates the reverse proxy server
//
TestRunner.prototype.startProxyServer = function (port, targetPort, host) {
var proxyServer = httpProxy.createServer(targetPort, host);
proxyServer.listen(port);
this.testServers.push(proxyServer);
return proxyServer;
TestRunner.prototype.startProxyServer = function (port, targetPort, host, callback) {
var that = this, proxyServer = httpProxy.createServer(targetPort, host);
proxyServer.listen(port, function () {
that.testServers.push(proxyServer);
callback();
});
};
//
// Creates the reverse proxy server with a specified latency
//
TestRunner.prototype.startLatentProxyServer = function (port, targetPort, host, latency) {
TestRunner.prototype.startLatentProxyServer = function (port, targetPort, host, latency, callback) {
// Initialize the nodeProxy and start proxying the request
var proxyServer = httpProxy.createServer(function (req, res, proxy) {
var that = this, proxyServer = httpProxy.createServer(function (req, res, proxy) {
var data = proxy.pause(req);
setTimeout(function () {
proxy.proxyRequest(targetPort, host);
proxy.proxyRequest(req, res, targetPort, host, data);
}, latency);
});
proxyServer.listen(port);
this.testServers.push(proxyServer);
return proxyServer;
proxyServer.listen(port, function () {
that.testServers.push(proxyServer);
callback();
});
};
//
// Creates the reverse proxy server with a ProxyTable
//
TestRunner.prototype.startProxyServerWithTable = function (port, options) {
var proxyServer = httpProxy.createServer(options);
proxyServer.listen(port);
this.testServers.push(proxyServer);
TestRunner.prototype.startProxyServerWithTable = function (port, options, callback) {
var that = this, proxyServer = httpProxy.createServer(options);
proxyServer.listen(port, function () {
that.testServers.push(proxyServer);
callback();
});
return proxyServer;
};
//
// Creates a latent reverse proxy server using a ProxyTable
//
TestRunner.prototype.startProxyServerWithTableAndLatency = function (port, latency, router) {
TestRunner.prototype.startProxyServerWithTableAndLatency = function (port, latency, options, callback) {
// Initialize the nodeProxy and start proxying the request
var proxyTable = new httpProxy.ProxyTable(router);
var proxyServer = http.createServer(function (req, res) {
var proxy = new httpProxy.HttpProxy(req, res);
var proxyServer, that = this, proxy = new httpProxy.HttpProxy(options);
proxyServer = http.createServer(function (req, res) {
var paused = proxy.pause(req);
setTimeout(function () {
proxyTable.proxyRequest(proxy);
proxy.proxyRequest(req, res, paused);
}, latency);
});
proxyServer.on('close', function () {
proxyTable.close();
proxyServer.listen(port, function () {
that.testServers.push(proxyServer);
callback();
});
proxyServer.listen(port);
this.testServers.push(proxyServer);
return proxyServer;
};
//
// Creates proxy server forwarding to the specified options
//
TestRunner.prototype.startProxyServerWithForwarding = function (port, targetPort, host, options) {
var proxyServer = httpProxy.createServer(targetPort, host, options);
proxyServer.listen(port);
this.testServers.push(proxyServer);
return proxyServer;
TestRunner.prototype.startProxyServerWithForwarding = function (port, targetPort, host, options, callback) {
var that = this, proxyServer = httpProxy.createServer(targetPort, host, options);
proxyServer.listen(port, function () {
that.testServers.push(proxyServer);
callback();
});
};
//
// Creates the 'hellonode' server
//
TestRunner.prototype.startTargetServer = function (port, output) {
var targetServer = http.createServer(function (req, res) {
TestRunner.prototype.startTargetServer = function (port, output, callback) {
var that = this, targetServer = http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.write(output)
res.write(output);
res.end();
});
targetServer.listen(port);
this.testServers.push(targetServer);
return targetServer;
targetServer.listen(port, function () {
that.testServers.push(targetServer);
callback();
});
};
//
......
......@@ -30,6 +30,20 @@ var vows = require('vows'),
assert = require('assert'),
helpers = require('./helpers');
var forwardOptions = {
forward: {
port: 8300,
host: 'localhost'
}
};
var badForwardOptions = {
forward: {
port: 9000,
host: 'localhost'
}
};
var runner = new helpers.TestRunner(),
assertProxiedWithTarget = helpers.assertProxiedWithTarget,
assertProxiedWithNoTarget = helpers.assertProxiedWithNoTarget;
......@@ -37,20 +51,33 @@ var runner = new helpers.TestRunner(),
vows.describe('node-http-proxy').addBatch({
"When using server created by httpProxy.createServer()": {
"with no latency" : {
"and a valid target server": assertProxiedWithTarget(runner, 'localhost', 8080, 8081, function () {
runner.startProxyServer(8080, 8081, 'localhost');
"and a valid target server": assertProxiedWithTarget(runner, 'localhost', 8080, 8081, function (callback) {
runner.startProxyServer(8080, 8081, 'localhost', callback);
}),
"and without a valid target server": assertProxiedWithNoTarget(runner, 8082, 500, function () {
runner.startProxyServer(8082, 9000, 'localhost');
"and without a valid target server": assertProxiedWithNoTarget(runner, 8082, 500, function (callback) {
runner.startProxyServer(8082, 9000, 'localhost', callback);
})
},
"with latency": {
"and a valid target server": assertProxiedWithTarget(runner, 'localhost', 8083, 8084, function () {
runner.startLatentProxyServer(8083, 8084, 'localhost', 1000);
"and a valid target server": assertProxiedWithTarget(runner, 'localhost', 8083, 8084, function (callback) {
runner.startLatentProxyServer(8083, 8084, 'localhost', 1000, callback);
}),
"and without a valid target server": assertProxiedWithNoTarget(runner, 8085, 500, function () {
runner.startLatentProxyServer(8085, 9000, 'localhost', 1000);
"and without a valid target server": assertProxiedWithNoTarget(runner, 8085, 500, function (callback) {
runner.startLatentProxyServer(8085, 9000, 'localhost', 1000, callback);
})
},
"with forwarding enabled": {
topic: function () {
runner.startTargetServer(8300, 'forward proxy', this.callback);
},
"with no latency" : {
"and a valid target server": assertProxiedWithTarget(runner, 'localhost', 8120, 8121, function (callback) {
runner.startProxyServerWithForwarding(8120, 8121, 'localhost', forwardOptions, callback);
}),
"and without a valid forward server": assertProxiedWithTarget(runner, 'localhost', 8122, 8123, function (callback) {
runner.startProxyServerWithForwarding(8122, 8123, 'localhost', badForwardOptions, callback);
})
}
}
}
}).addBatch({
......
......@@ -37,8 +37,7 @@ vows.describe('node-http-proxy/proxy-table').addBatch({
"When using server created by httpProxy.createServer()": {
"when passed a routing table": {
topic: function () {
this.server = runner.startProxyServerWithTable(8090, defaultOptions);
return null;
this.server = runner.startProxyServerWithTable(8090, defaultOptions, this.callback);
},
"an incoming request to foo.com": assertProxiedWithTarget(runner, 'foo.com', 8090, 8091),
"an incoming request to bar.com": assertProxiedWithTarget(runner, 'bar.com', 8090, 8092),
......@@ -49,9 +48,7 @@ vows.describe('node-http-proxy/proxy-table').addBatch({
fs.writeFileSync(routeFile, JSON.stringify(fileOptions));
this.server = runner.startProxyServerWithTable(8100, {
router: routeFile
});
return null;
}, this.callback);
},
"an incoming request to foo.com": assertProxiedWithTarget(runner, 'foo.com', 8100, 8101),
"an incoming request to bar.com": assertProxiedWithTarget(runner, 'bar.com', 8100, 8102),
......@@ -67,7 +64,7 @@ vows.describe('node-http-proxy/proxy-table').addBatch({
config.router['dynamic.com'] = "127.0.0.1:8103"
fs.writeFileSync(routeFile, JSON.stringify(config));
this.server.on('updateRoutes', function () {
this.server.on('routes', function () {
var options = {
method: 'GET',
uri: 'http://localhost:8100',
......@@ -93,8 +90,7 @@ vows.describe('node-http-proxy/proxy-table').addBatch({
this.server = runner.startProxyServerWithTableAndLatency(8110, 100, {
'foo.com': 'localhost:8111',
'bar.com': 'localhost:8112'
});
return null;
}, this.callback);
},
"an incoming request to foo.com": assertProxiedWithTarget(runner, 'foo.com', 8110, 8111),
"an incoming request to bar.com": assertProxiedWithTarget(runner, 'bar.com', 8110, 8112),
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment