mirror of
https://github.com/http-party/node-http-proxy.git
synced 2025-12-08 20:59:18 +00:00
[api] Object creation is cheap for HttpProxy, so lets take advantage
This commit is contained in:
parent
66afb2a2a3
commit
9f0aeacab1
12
demo.js
12
demo.js
@ -45,15 +45,15 @@ httpProxy.createServer(9000, 'localhost').listen(8000);
|
|||||||
sys.puts('http proxy server'.blue + ' started '.green.bold + 'on port '.blue + '8000'.yellow);
|
sys.puts('http proxy server'.blue + ' started '.green.bold + 'on port '.blue + '8000'.yellow);
|
||||||
|
|
||||||
/****** http proxy server with latency******/
|
/****** http proxy server with latency******/
|
||||||
httpProxy.createServer(function (req, res, proxy){
|
/*httpProxy.createServer(function (req, res, proxy){
|
||||||
setTimeout(function(){
|
setTimeout(function(){
|
||||||
proxy.proxyRequest(9000, 'localhost', req, res);
|
proxy.proxyRequest(9000, 'localhost', req, res);
|
||||||
}, 200)
|
}, 200)
|
||||||
}).listen(8001);
|
}).listen(8001);
|
||||||
sys.puts('http proxy server '.blue + 'started '.green.bold + 'on port '.blue + '8001 '.yellow + 'with latency'.magenta.underline );
|
sys.puts('http proxy server '.blue + 'started '.green.bold + 'on port '.blue + '8001 '.yellow + 'with latency'.magenta.underline );*/
|
||||||
|
|
||||||
/****** http server with proxyRequest handler and latency******/
|
/****** http server with proxyRequest handler and latency******/
|
||||||
http.createServer(function (req, res){
|
/*http.createServer(function (req, res){
|
||||||
var proxy = new httpProxy.HttpProxy;
|
var proxy = new httpProxy.HttpProxy;
|
||||||
proxy.watch(req, res);
|
proxy.watch(req, res);
|
||||||
|
|
||||||
@ -61,12 +61,12 @@ http.createServer(function (req, res){
|
|||||||
proxy.proxyRequest(9000, 'localhost', req, res);
|
proxy.proxyRequest(9000, 'localhost', req, res);
|
||||||
}, 200);
|
}, 200);
|
||||||
}).listen(8002);
|
}).listen(8002);
|
||||||
sys.puts('http server '.blue + 'started '.green.bold + 'on port '.blue + '8002 '.yellow + 'with proxyRequest handler'.cyan.underline + ' and latency'.magenta);
|
sys.puts('http server '.blue + 'started '.green.bold + 'on port '.blue + '8002 '.yellow + 'with proxyRequest handler'.cyan.underline + ' and latency'.magenta);*/
|
||||||
|
|
||||||
/****** regular http server ******/
|
/****** regular http server ******/
|
||||||
/*http.createServer(function (req, res){
|
http.createServer(function (req, res){
|
||||||
res.writeHead(200, {'Content-Type': 'text/plain'});
|
res.writeHead(200, {'Content-Type': 'text/plain'});
|
||||||
res.write('request successfully proxied to: ' + req.url + '\n' + JSON.stringify(req.headers, true, 2));
|
res.write('request successfully proxied to: ' + req.url + '\n' + JSON.stringify(req.headers, true, 2));
|
||||||
res.end();
|
res.end();
|
||||||
}).listen(9000);
|
}).listen(9000);
|
||||||
sys.puts('http server '.blue + 'started '.green.bold + 'on port '.blue + '9000 '.yellow);*/
|
sys.puts('http server '.blue + 'started '.green.bold + 'on port '.blue + '9000 '.yellow);
|
||||||
|
|||||||
@ -27,6 +27,7 @@
|
|||||||
var sys = require('sys'),
|
var sys = require('sys'),
|
||||||
http = require('http'),
|
http = require('http'),
|
||||||
eyes = require('eyes'),
|
eyes = require('eyes'),
|
||||||
|
pool = require('pool'),
|
||||||
events = require('events'),
|
events = require('events'),
|
||||||
pool = require('pool'),
|
pool = require('pool'),
|
||||||
min = 0,
|
min = 0,
|
||||||
@ -38,9 +39,26 @@ manager.setMinClients(min);
|
|||||||
manager.setMaxClients(max);
|
manager.setMaxClients(max);
|
||||||
|
|
||||||
exports.createServer = function () {
|
exports.createServer = function () {
|
||||||
// Initialize the nodeProxy to start proxying requests
|
var args, callback, port, host;
|
||||||
var proxy = new (exports.HttpProxy);
|
args = Array.prototype.slice.call(arguments);
|
||||||
return proxy.createServer.apply(proxy, arguments);
|
callback = typeof args[args.length - 1] === 'function' && args.pop();
|
||||||
|
if (args[0]) port = args[0];
|
||||||
|
if (args[1]) host = args[1];
|
||||||
|
|
||||||
|
var server = http.createServer(function (req, res){
|
||||||
|
var proxy = new HttpProxy(req, res);
|
||||||
|
|
||||||
|
// If we were passed a callback to process the request
|
||||||
|
// or response in some way, then call it.
|
||||||
|
if(callback) {
|
||||||
|
callback(req, res, proxy);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
proxy.proxyRequest(port, server);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return server;
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.setMin = function (value) {
|
exports.setMin = function (value) {
|
||||||
@ -53,14 +71,15 @@ exports.setMax = function (value) {
|
|||||||
manager.setMaxClients(max);
|
manager.setMaxClients(max);
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.HttpProxy = function () {
|
var HttpProxy = function (req, res) {
|
||||||
this.emitter = new(events.EventEmitter);
|
this.emitter = new(events.EventEmitter);
|
||||||
this.events = {};
|
this.events = {};
|
||||||
this.listeners = {};
|
this.req = req;
|
||||||
this.collisions = {};
|
this.res = res;
|
||||||
|
this.watch(req);
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.HttpProxy.prototype = {
|
HttpProxy.prototype = {
|
||||||
toArray: function (obj){
|
toArray: function (obj){
|
||||||
var len = obj.length,
|
var len = obj.length,
|
||||||
arr = new Array(len);
|
arr = new Array(len);
|
||||||
@ -70,102 +89,42 @@ exports.HttpProxy.prototype = {
|
|||||||
return arr;
|
return arr;
|
||||||
},
|
},
|
||||||
|
|
||||||
createServer: function () {
|
watch: function (req) {
|
||||||
var self = this,
|
this.events = [];
|
||||||
server,
|
|
||||||
port,
|
|
||||||
callback;
|
|
||||||
|
|
||||||
if (typeof(arguments[0]) === "function") {
|
|
||||||
callback = arguments[0];
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
port = arguments[0];
|
|
||||||
server = arguments[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
var proxyServer = http.createServer(function (req, res){
|
|
||||||
self.watch(req, res);
|
|
||||||
|
|
||||||
// If we were passed a callback to process the request
|
|
||||||
// or response in some way, then call it.
|
|
||||||
if(callback) {
|
|
||||||
callback(req, res, self);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
self.proxyRequest(port, server, req, res);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return proxyServer;
|
|
||||||
},
|
|
||||||
|
|
||||||
watch: function (req, res) {
|
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
// Create a unique id for this request so
|
this.onData = function () {
|
||||||
// we can reference it later.
|
self.events.push(['data'].concat(self.toArray(arguments)));
|
||||||
var id = new Date().getTime().toString();
|
};
|
||||||
|
this.onEnd = function () {
|
||||||
// If we get a request in the same tick, we need to
|
self.events.push(['end'].concat(self.toArray(arguments)));
|
||||||
// append to the id so it stays unique.
|
|
||||||
if(typeof this.collisions[id] === 'undefined') {
|
|
||||||
this.collisions[id] = 0;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
this.collisions[id]++;
|
|
||||||
id += this.collisions[id];
|
|
||||||
}
|
|
||||||
|
|
||||||
req.id = id;
|
|
||||||
this.events[req.id] = [];
|
|
||||||
|
|
||||||
this.listeners[req.id] = {
|
|
||||||
onData: function () {
|
|
||||||
self.events[req.id].push(['data'].concat(self.toArray(arguments)));
|
|
||||||
},
|
|
||||||
onEnd: function () {
|
|
||||||
self.events[req.id].push(['end'].concat(self.toArray(arguments)));
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
req.addListener('data', this.listeners[req.id].onData);
|
req.addListener('data', this.onData);
|
||||||
req.addListener('end', this.listeners[req.id].onEnd);
|
req.addListener('end', this.onEnd);
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
unwatch: function (req, res) {
|
unwatch: function (req) {
|
||||||
req.removeListener('data', this.listeners[req.id].onData);
|
req.removeListener('data', this.onData);
|
||||||
req.removeListener('end', this.listeners[req.id].onEnd);
|
req.removeListener('end', this.onEnd);
|
||||||
|
|
||||||
// Rebroadcast any events that have been buffered
|
// Rebroadcast any events that have been buffered
|
||||||
while(this.events[req.id].length > 0) {
|
for (var i = 0, len = this.events.length; i < len; ++i) {
|
||||||
var args = this.events[req.id].shift();
|
req.emit.apply(req, this.events[i]);
|
||||||
req.emit.apply(req, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove the data from the event and listeners hashes
|
|
||||||
delete this.listeners[req.id];
|
|
||||||
delete this.events[req.id];
|
|
||||||
|
|
||||||
// If this request id is a base time, delete it
|
|
||||||
if (typeof this.collisions[req.id] !== 'undefined') {
|
|
||||||
delete this.collisions[req.id];
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
proxyRequest: function (port, server, req, res) {
|
proxyRequest: function (port, server) {
|
||||||
// Remark: nodeProxy.body exists solely for testability
|
// Remark: nodeProxy.body exists solely for testability
|
||||||
this.body = '';
|
var self = this, req = this.req, res = this.res;
|
||||||
var self = this;
|
self.body = '';
|
||||||
|
|
||||||
// Open new HTTP request to internal resource with will act as a reverse proxy pass
|
// Open new HTTP request to internal resource with will act as a reverse proxy pass
|
||||||
var p = manager.getPool(port, server);
|
var p = manager.getPool(port, server);
|
||||||
eyes.inspect(req.headers);
|
|
||||||
// Make request to internal server, passing along the method and headers
|
|
||||||
p.request(req.method, req.url, req.headers, function (reverse_proxy) {
|
p.request(req.method, req.url, req.headers, function (reverse_proxy) {
|
||||||
// Add a listener for the connection timeout event
|
// Create an error handler so we can use it temporarily
|
||||||
reverse_proxy.connection.addListener('error', function (err) {
|
var error = function (err) {
|
||||||
res.writeHead(200, {'Content-Type': 'text/plain'});
|
res.writeHead(200, {'Content-Type': 'text/plain'});
|
||||||
|
|
||||||
if(req.method !== 'HEAD') {
|
if(req.method !== 'HEAD') {
|
||||||
@ -173,8 +132,9 @@ exports.HttpProxy.prototype = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
res.end();
|
res.end();
|
||||||
});
|
};
|
||||||
|
// Add a listener for the connection timeout event
|
||||||
|
reverse_proxy.connection.addListener('error', error);
|
||||||
|
|
||||||
// Add a listener for the reverse_proxy response event
|
// Add a listener for the reverse_proxy response event
|
||||||
reverse_proxy.addListener('response', function (response) {
|
reverse_proxy.addListener('response', function (response) {
|
||||||
@ -211,9 +171,65 @@ exports.HttpProxy.prototype = {
|
|||||||
// At the end of the client request, we are going to stop the proxied request
|
// At the end of the client request, we are going to stop the proxied request
|
||||||
req.addListener('end', function () {
|
req.addListener('end', function () {
|
||||||
reverse_proxy.end();
|
reverse_proxy.end();
|
||||||
|
reverse_proxy.connection.removeListener('error', error);
|
||||||
});
|
});
|
||||||
|
|
||||||
self.unwatch(req, res);
|
self.unwatch(req);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
exports.HttpProxy = HttpProxy;
|
||||||
|
|
||||||
|
/*// Create an error handler so we can use it temporarily
|
||||||
|
var error = function (err) {
|
||||||
|
res.writeHead(200, {'Content-Type': 'text/plain'});
|
||||||
|
|
||||||
|
if(req.method !== 'HEAD') {
|
||||||
|
res.write('An error has occurred: ' + sys.puts(JSON.stringify(err)));
|
||||||
|
}
|
||||||
|
|
||||||
|
res.end();
|
||||||
|
};
|
||||||
|
// Add a listener for the connection timeout event
|
||||||
|
reverse_proxy.connection.addListener('error', error);
|
||||||
|
|
||||||
|
// Add a listener for the reverse_proxy response event
|
||||||
|
reverse_proxy.addListener('response', function (response) {
|
||||||
|
if (response.headers.connection) {
|
||||||
|
if (req.headers.connection) response.headers.connection = req.headers.connection;
|
||||||
|
else response.headers.connection = 'close';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the response headers of the client response
|
||||||
|
res.writeHead(response.statusCode, response.headers);
|
||||||
|
|
||||||
|
// Add event handler for the proxied response in chunks
|
||||||
|
response.addListener('data', function (chunk) {
|
||||||
|
if(req.method !== 'HEAD') {
|
||||||
|
res.write(chunk, 'binary');
|
||||||
|
self.body += chunk;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Add event listener for end of proxied response
|
||||||
|
response.addListener('end', function () {
|
||||||
|
// Remark: Emit the end event for testability
|
||||||
|
self.emitter.emit('end', null, self.body);
|
||||||
|
|
||||||
|
res.end();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Chunk the client request body as chunks from the proxied request come in
|
||||||
|
req.addListener('data', function (chunk) {
|
||||||
|
reverse_proxy.write(chunk, 'binary');
|
||||||
|
})
|
||||||
|
|
||||||
|
// At the end of the client request, we are going to stop the proxied request
|
||||||
|
req.addListener('end', function () {
|
||||||
|
reverse_proxy.end();
|
||||||
|
//reverse_proxy.connection.removeListener('error', error);
|
||||||
|
});
|
||||||
|
|
||||||
|
self.unwatch(req);*/
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user