From 4110448046dd945afe3e092968d9382d573a369a Mon Sep 17 00:00:00 2001
From: indexzero
var http = require('http'),
httpProxy = require('http-proxy');
-
+ //
// Create your proxy server
+ //
httpProxy.createServer(9000, 'localhost').listen(8000);
+ //
// Create your target server
+ //
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.write('request successfully proxied!' + '\n' + JSON.stringify(req.headers, true, 2));
@@ -63,11 +66,15 @@ See the [demo](http://github.com/nodejitsu/node-http-proxy/blob/master/demo.js)
var http = require('http'),
httpProxy = require('http-proxy');
-
- // create a proxy server with custom application logic
+
+ //
+ // Create a proxy server with custom application logic
+ //
httpProxy.createServer(function (req, res, proxy) {
+ //
// Put your custom server logic here
- proxy.proxyRequest(9000, 'localhost');
+ //
+ proxy.proxyRequest(req, res, 9000, 'localhost');
}).listen(8000);
http.createServer(function (req, res) {
@@ -81,13 +88,23 @@ See the [demo](http://github.com/nodejitsu/node-http-proxy/blob/master/demo.js)
var http = require('http'),
httpProxy = require('http-proxy');
-
- // create a proxy server with custom application logic
+
+ //
+ // Create a proxy server with custom application logic
+ //
httpProxy.createServer(function (req, res, proxy) {
+ //
+ // Buffer the request so that `data` and `end` events
+ // are not lost during async operation(s).
+ //
+ var buffer = proxy.buffer(req);
+
+ //
// Wait for two seconds then respond: this simulates
// performing async actions before proxying a request
+ //
setTimeout(function () {
- proxy.proxyRequest(9000, 'localhost');
+ proxy.proxyRequest(req, res, 9000, 'localhost', buffer);
}, 2000);
}).listen(8000);
@@ -102,15 +119,20 @@ See the [demo](http://github.com/nodejitsu/node-http-proxy/blob/master/demo.js)
var http = require('http'),
httpProxy = require('http-proxy');
+
+ //
+ // Create a new instance of HttProxy to use in your server
+ //
+ var proxy = new httpProxy.HttpProxy();
- // create a regular http server and proxy its handler
+ //
+ // Create a regular http server and proxy its handler
+ //
http.createServer(function (req, res) {
- // Create a new instance of HttProxy for this request
- // each instance is only valid for serving one request
- var proxy = new httpProxy.HttpProxy(req, res);
-
+ //
// Put your custom server logic here, then proxy
- proxy.proxyRequest(9000, 'localhost', req, res);
+ //
+ proxy.proxyRequest(req, res, 9000, 'localhost');
}).listen(8001);
http.createServer(function (req, res) {
diff --git a/bin/node-http-proxy b/bin/node-http-proxy
index 29e5c34..ad2b24c 100755
--- a/bin/node-http-proxy
+++ b/bin/node-http-proxy
@@ -9,7 +9,7 @@ var path = require('path'),
var help = [
"usage: node-http-proxy [options] ",
"",
- "All options should be set with the syntax --option=value",
+ "Starts a node-http-proxy server using the specified command-line options",
"",
"options:",
" --port PORT Port that the proxy server should run on",
@@ -20,8 +20,7 @@ var help = [
].join('\n');
if (argv.h || argv.help || Object.keys(argv).length === 2) {
- util.puts(help);
- process.exit(0);
+ return util.puts(help);
}
var location, config = {},
diff --git a/demo.js b/demo.js
index 4e5fbb2..d3c17db 100644
--- a/demo.js
+++ b/demo.js
@@ -59,9 +59,9 @@ util.puts('http proxy server '.blue + 'started '.green.bold + 'on port '.blue +
// Http Proxy Server with Latency
//
httpProxy.createServer(function (req, res, proxy) {
- var paused = proxy.pause(req);
+ var buffer = proxy.buffer(req);
setTimeout(function() {
- proxy.proxyRequest(req, res, 9000, 'localhost', paused);
+ proxy.proxyRequest(req, res, 9000, 'localhost', buffer);
}, 200)
}).listen(8002);
util.puts('http proxy server '.blue + 'started '.green.bold + 'on port '.blue + '8002 '.yellow + 'with latency'.magenta.underline);
@@ -82,9 +82,9 @@ util.puts('http proxy server '.blue + 'started '.green.bold + 'on port '.blue +
//
var standAloneProxy = new httpProxy.HttpProxy();
http.createServer(function (req, res) {
- var paused = standAloneProxy.pause(req);
+ var buffer = standAloneProxy.buffer(req);
setTimeout(function() {
- proxy.proxyRequest(req, res, 9000, 'localhost', paused);
+ proxy.proxyRequest(req, res, 9000, 'localhost', buffer);
}, 200);
}).listen(8004);
util.puts('http server '.blue + 'started '.green.bold + 'on port '.blue + '8004 '.yellow + 'with proxyRequest handler'.cyan.underline + ' and latency'.magenta);
diff --git a/docs/node-http-proxy.html b/docs/node-http-proxy.html
index dd9dd97..31f1af1 100644
--- a/docs/node-http-proxy.html
+++ b/docs/node-http-proxy.html
@@ -52,7 +52,23 @@ made by all instances of HttpProxy
HttpProxy exports.setMaxSockets = function (value) {
maxSockets = value;
-};exports.createServer = function () {
+};Returns a server that manages an instance of HttpProxy. Flexible arguments allow for:
+ +httpProxy.createServer(9000, 'localhost')httpPRoxy.createServer(function (req, res, proxy) { ... })exports.createServer = function () {
var args, callback, port, host, forward,
silent, options, proxy, server;
@@ -137,7 +153,7 @@ for managing the life-cycle of streaming reverse proxyied HTTP requests.
self.emit('routes', routes);
});
}
-};Inherit from events.EventEmitter
util.inherits(HttpProxy, events.EventEmitter);Inherit from events.EventEmitter
util.inherits(HttpProxy, events.EventEmitter); var pause = httpProxy.pause(req);
+ var buffer = httpProxy.buffer(req);
fs.readFile(path, function(){
- httpProxy.proxyRequest(req, res, host, port, paused);
+ httpProxy.proxyRequest(req, res, host, port, buffer);
});
@@ -157,7 +173,7 @@ the async operation has completed, otherwise these
Connect.
However, this is not a big leap from the implementation in node-http-proxy < 0.4.0.
This simply chooses to manage the scope of the events on a new Object literal as opposed to
-on the HttpProxy instance. HttpProxy.prototype.pause = function (obj) {
+on the HttpProxy instance. HttpProxy.prototype.buffer = function (obj) {
var onData, onEnd, events = [];
obj.on('data', onData = function (data, encoding) {
@@ -195,7 +211,7 @@ if they exist. httpProxy.pause(req)HttpProxy.prototype.proxyRequest = function (req, res, port, host, paused) {
+@buffer {Object} Optional Result from httpProxy.buffer(req)
HttpProxy.prototype.proxyRequest = function (req, res, port, host, buffer) {
var self = this, reverseProxy, location, errState = false;
Check the proxy table for this instance to see if we need
to get the proxy location for the request supplied. We will
@@ -211,10 +227,10 @@ then respond with 404 since we do not have a valid proxy target.
proxy.proxyRequest(req, res, port, host, paused): This will be skippedproxy.proxyRequest(req, res, paused): Paused will get updated appropriatelyproxy.proxyRequest(req, res, port, host, buffer): This will be skippedproxy.proxyRequest(req, res, buffer): Buffer will get updated appropriatelyproxy.proxyRequest(req, res): No effect undefined = undefined paused = port;
+ buffer = port;
port = location.port;
host = location.host;
}
@@ -242,7 +258,7 @@ specified request to the address provided in this.options.forward
path: req.url,
headers: req.headers
}, function (response) {
- Process the reverse_proxy response when it's received.
if (response.headers.connection) {
+ Process the reverseProxy response when it's received.
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);Status code = 304 @@ -268,48 +284,50 @@ No 'data' event and no 'end'
If we have been passed buffered data, resume it.
if (buffer && !errState) {
+ buffer.resume();
}
};
-
-HttpProxy.prototype._forwardRequest = function (req) {
+ Forwards the specified req to the location specified
+by this.options.forward ignoring errors and the subsequent response.
HttpProxy.prototype._forwardRequest = function (req) {
var self = this, port, host, forwardProxy;
port = this.options.forward.port;
host = this.options.forward.host;
- Open new HTTP request to internal resource with will act as a reverse proxy pass
forwardProxy = http.request({
+ Open new HTTP request to internal resource with will act as a reverse proxy pass
forwardProxy = http.request({
host: host,
port: port,
agent: _getAgent(host, port),
method: req.method,
path: req.url,
headers: req.headers
- }, function (response) {Ignore the response from the forward proxy since this is a 'fire-and-forget' proxy. + }, function (response) {
Ignore the response from the forward proxy since this is a 'fire-and-forget' proxy. Remark (indexzero): We will eventually emit a 'forward' event here for performance tuning.
});
- Add a listener for the connection timeout event.
+Add a listener for the connection timeout event.
Remark: Ignoring this error in the event - forward target doesn't exist.
forwardProxy.on('error', function (err) { });Chunk the client request body as chunks from the proxied request come in
req.on('data', function (chunk) {
+ forward target doesn't exist. forwardProxy.on('error', function (err) { });Chunk the client request body as chunks from the proxied request come in
req.on('data', function (chunk) {
forwardProxy.write(chunk);
- })At the end of the client request, we are going to stop the proxied request
req.on('end', function () {
+ })At the end of the client request, we are going to stop the proxied request
req.on('end', function () {
forwardProxy.end();
});
};
HttpProxy.prototype.proxyWebSocketRequest = function (port, server, host, data) {
var self = this, req = self.req, socket = self.sock, head = self.head,
- headers = new _headers(req.headers), CRLF = '\r\n';Will generate clone of headers + headers = new _headers(req.headers), CRLF = '\r\n';
Will generate clone of headers To not change original
function _headers(headers) {
var h = {};
for (var i in headers) {
h[i] = headers[i];
}
return h;
- }WebSocket requests has method = GET
if (req.method !== 'GET' || headers.upgrade.toLowerCase() !== 'websocket') {This request is not WebSocket request
return;
- }Turn of all bufferings + }
WebSocket requests has method = GET
if (req.method !== 'GET' || headers.upgrade.toLowerCase() !== 'websocket') {This request is not WebSocket request
return;
+ }Turn of all bufferings For server set KeepAlive For client set encoding
function _socket(socket, server) {
socket.setTimeout(0);
@@ -320,20 +338,20 @@ For client set encoding Client socket
_socket(socket);If host is undefined + }
Client socket
_socket(socket);If host is undefined Get it from headers
if (!host) {
host = headers.Host;
}
- Remote host address
var remote_host = server + (port - 80 === 0 ? '' : ':' + port);Change headers
headers.Host = remote_host;
- headers.Origin = 'http://' + remote_host;Open request
var p = manager.getPool(port, server);
+ Remote host address
var remote_host = server + (port - 80 === 0 ? '' : ':' + port);Change headers
headers.Host = remote_host;
+ headers.Origin = 'http://' + remote_host;Open request
var p = manager.getPool(port, server);
- p.getClient(function(client) {Based on 'pool/main.js'
var request = client.request('GET', req.url, headers);
+ p.getClient(function(client) {Based on 'pool/main.js'
var request = client.request('GET', req.url, headers);
var errorListener = function (error) {
client.removeListener('error', errorListener);
- Remove the client from the pool's available clients since it has errored
p.clients.splice(p.clients.indexOf(client), 1);
+ Remove the client from the pool's available clients since it has errored
p.clients.splice(p.clients.indexOf(client), 1);
socket.end();
- }Not disconnect on update
client.on('upgrade', function(request, remote_socket, head) {Prepare socket
_socket(remote_socket, true);Emit event
onUpgrade(remote_socket);
+ }Not disconnect on update
client.on('upgrade', function(request, remote_socket, head) {Prepare socket
_socket(remote_socket, true);Emit event
onUpgrade(remote_socket);
});
client.on('error', errorListener);
@@ -347,23 +365,23 @@ Get it from headers Handshaking
Ok, kind of harmfull part of code + request.socket.on('data', handshake = function(data) {
Handshaking
Ok, kind of harmfull part of code Socket.IO is sending hash at the end of handshake If protocol = 76 But we need to replace 'host' and 'origin' in response So we split data to printable data and to non-printable -(Non-printable will come after double-CRLF)
var sdata = data.toString();Get Printable
sdata = sdata.substr(0, sdata.search(CRLF + CRLF));Get Non-Printable
data = data.slice(Buffer.byteLength(sdata), data.length);Replace host and origin
sdata = sdata.replace(remote_host, host)
+(Non-printable will come after double-CRLF) var sdata = data.toString();Get Printable
sdata = sdata.substr(0, sdata.search(CRLF + CRLF));Get Non-Printable
data = data.slice(Buffer.byteLength(sdata), data.length);Replace host and origin
sdata = sdata.replace(remote_host, host)
.replace(remote_host, host);
- try {Write printable
socket.write(sdata);Write non-printable
socket.write(data);
+ try {Write printable
socket.write(sdata);Write non-printable
socket.write(data);
}
catch (e) {
request.end();
socket.end();
- }Catch socket errors
socket.on('error', function() {
+ }Catch socket errors
socket.on('error', function() {
request.end();
- });Remove data listener now that the 'handshake' is complete
request.socket.removeListener('data', handshake);
- });Write upgrade-head
try {
+ });Remove data listener now that the 'handshake' is complete
request.socket.removeListener('data', handshake);
+ });Write upgrade-head
try {
request.write(head);
}
catch(e) {
@@ -371,9 +389,9 @@ So we split data to printable data and to non-printable
socket.end();
}
self.unwatch(socket);
- });Request
function onUpgrade(reverse_proxy) {
+ });Request
function onUpgrade(reverse_proxy) {
var listeners = {};
- We're now connected to the server, so lets change server socket
reverse_proxy.on('data', listeners._r_data = function(data) {Pass data to client
if (socket.writable) {
+ We're now connected to the server, so lets change server socket
reverse_proxy.on('data', listeners._r_data = function(data) {Pass data to client
if (socket.writable) {
try {
socket.write(data);
}
@@ -384,19 +402,19 @@ So we split data to printable data and to non-printable
}
});
- socket.on('data', listeners._data = function(data) {Pass data from client to server
try {
+ socket.on('data', listeners._data = function(data) {Pass data from client to server
try {
reverse_proxy.write(data);
}
catch (e) {
reverse_proxy.end();
socket.end();
}
- });Detach event listeners from reverse_proxy
function detach() {
+ });Detach event listeners from reverse_proxy
function detach() {
reverse_proxy.removeListener('close', listeners._r_close);
reverse_proxy.removeListener('data', listeners._r_data);
socket.removeListener('data', listeners._data);
socket.removeListener('close', listeners._close);
- }Hook disconnections
reverse_proxy.on('end', listeners._r_close = function() {
+ }Hook disconnections
reverse_proxy.on('end', listeners._r_close = function() {
socket.end();
detach();
});
diff --git a/lib/node-http-proxy.js b/lib/node-http-proxy.js
index 5362ab5..1594d48 100644
--- a/lib/node-http-proxy.js
+++ b/lib/node-http-proxy.js
@@ -69,8 +69,16 @@ exports.setMaxSockets = function (value) {
};
//
-// ### function createServer ([port, host, options], handler)
-//
+// ### function createServer ([port, host, options, handler])
+// #### @port {number} **Optional** Port to use on the proxy target host.
+// #### @host {string} **Optional** Host of the proxy target.
+// #### @options {Object} **Optional** Options for the HttpProxy instance used
+// #### @handler {function} **Optional** Request handler for the server
+// Returns a server that manages an instance of HttpProxy. Flexible arguments allow for:
+//
+// * `httpProxy.createServer(9000, 'localhost')`
+// * `httpProxy.createServer(9000, 'localhost', options)
+// * `httpPRoxy.createServer(function (req, res, proxy) { ... })`
//
exports.createServer = function () {
var args, callback, port, host, forward,
@@ -172,7 +180,7 @@ var HttpProxy = exports.HttpProxy = function (options) {
util.inherits(HttpProxy, events.EventEmitter);
//
-// ### function pause (obj)
+// ### function buffer (obj)
// #### @obj {Object} Object to pause events from
// Pause `data` and `end` events on the given `obj`.
// Consumers of HttpProxy performing async tasks
@@ -180,9 +188,9 @@ util.inherits(HttpProxy, events.EventEmitter);
// the async operation has completed, otherwise these
// __events will be lost.__
//
-// var pause = httpProxy.pause(req);
+// var buffer = httpProxy.buffer(req);
// fs.readFile(path, function(){
-// httpProxy.proxyRequest(req, res, host, port, paused);
+// httpProxy.proxyRequest(req, res, host, port, buffer);
// });
//
// __Attribution:__ This approach is based heavily on
@@ -191,7 +199,7 @@ util.inherits(HttpProxy, events.EventEmitter);
// This simply chooses to manage the scope of the events on a new Object literal as opposed to
// [on the HttpProxy instance](https://github.com/nodejitsu/node-http-proxy/blob/v0.3.1/lib/node-http-proxy.js#L154).
//
-HttpProxy.prototype.pause = function (obj) {
+HttpProxy.prototype.buffer = function (obj) {
var onData, onEnd, events = [];
obj.on('data', onData = function (data, encoding) {
@@ -231,9 +239,9 @@ HttpProxy.prototype.close = function () {
// #### @res {ServerResponse} Outgoing HTTP Request to write proxied data to.
// #### @port {number} **Optional** Port to use on the proxy target host.
// #### @host {string} **Optional** Host of the proxy target.
-// #### @paused {Object} **Optional** Result from `httpProxy.pause(req)`
+// #### @buffer {Object} **Optional** Result from `httpProxy.buffer(req)`
//
-HttpProxy.prototype.proxyRequest = function (req, res, port, host, paused) {
+HttpProxy.prototype.proxyRequest = function (req, res, port, host, buffer) {
var self = this, reverseProxy, location, errState = false;
//
@@ -258,11 +266,11 @@ HttpProxy.prototype.proxyRequest = function (req, res, port, host, paused) {
// When using the ProxyTable in conjunction with an HttpProxy instance
// only the following arguments are valid:
//
- // * `proxy.proxyRequest(req, res, port, host, paused)`: This will be skipped
- // * `proxy.proxyRequest(req, res, paused)`: Paused will get updated appropriately
+ // * `proxy.proxyRequest(req, res, port, host, buffer)`: This will be skipped
+ // * `proxy.proxyRequest(req, res, buffer)`: Buffer will get updated appropriately
// * `proxy.proxyRequest(req, res)`: No effect `undefined = undefined`
//
- paused = port;
+ buffer = port;
port = location.port;
host = location.host;
}
@@ -297,7 +305,7 @@ HttpProxy.prototype.proxyRequest = function (req, res, port, host, paused) {
headers: req.headers
}, function (response) {
- // Process the reverse_proxy response when it's received.
+ // Process the reverseProxy response when it's received.
if (response.headers.connection) {
if (req.headers.connection) response.headers.connection = req.headers.connection;
else response.headers.connection = 'close';
@@ -345,11 +353,18 @@ HttpProxy.prototype.proxyRequest = function (req, res, port, host, paused) {
}
});
- if (paused && !errState) {
- paused.resume();
+ // If we have been passed buffered data, resume it.
+ if (buffer && !errState) {
+ buffer.resume();
}
};
+//
+// ### @private function _forwardRequest (req)
+// #### @req {ServerRequest} Incoming HTTP Request to proxy.
+// Forwards the specified `req` to the location specified
+// by `this.options.forward` ignoring errors and the subsequent response.
+//
HttpProxy.prototype._forwardRequest = function (req) {
var self = this, port, host, forwardProxy;
diff --git a/test/helpers.js b/test/helpers.js
index 87a1e95..85782e7 100644
--- a/test/helpers.js
+++ b/test/helpers.js
@@ -100,7 +100,7 @@ TestRunner.prototype.startProxyServer = function (port, targetPort, host, callba
TestRunner.prototype.startLatentProxyServer = function (port, targetPort, host, latency, callback) {
// Initialize the nodeProxy and start proxying the request
var that = this, proxyServer = httpProxy.createServer(function (req, res, proxy) {
- var data = proxy.pause(req);
+ var data = proxy.buffer(req);
setTimeout(function () {
proxy.proxyRequest(req, res, targetPort, host, data);
@@ -133,9 +133,9 @@ TestRunner.prototype.startProxyServerWithTableAndLatency = function (port, laten
// Initialize the nodeProxy and start proxying the request
var proxyServer, that = this, proxy = new httpProxy.HttpProxy(options);
proxyServer = http.createServer(function (req, res) {
- var paused = proxy.pause(req);
+ var buffer = proxy.buffer(req);
setTimeout(function () {
- proxy.proxyRequest(req, res, paused);
+ proxy.proxyRequest(req, res, buffer);
}, latency);
});