Skip to content

Re-emit 'start', 'forward' and 'end' events in RoutingProxy #216

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
May 10, 2012
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,32 @@ proxyServerWithForwarding.listen(80);

The forwarding option can be used in conjunction with the proxy table options by simply including both the 'forward' and 'router' properties in the options passed to 'createServer'.

### Listening for proxy events
Sometimes you want to listen to an event on a proxy. For example, you may want to listen to the 'end' event, which represents when the proxy has finished proxying a request.

``` js
var httpProxy = require('http-proxy');

var server = httpProxy.createServer(function (req, res, proxy) {

var buffer = httpProxy.buffer(req);

proxy.proxyRequest(req, res, {
host: '127.0.0.1',
port: 9000,
buffer: buffer
});

});

server.proxy.on('end', function() {
console.log("The request was proxied.");
});

server.listen(8000);
```

It's important to remember not to listen for events on the proxy object in the function passed to `httpProxy.createServer`. Doing so would add a new listener on every request, which would end up being a disaster.

## Using HTTPS
You have all the full flexibility of node-http-proxy offers in HTTPS as well as HTTP. The two basic scenarios are: with a stand-alone proxy server or in conjunction with another HTTPS server.
Expand Down
76 changes: 47 additions & 29 deletions lib/node-http-proxy/routing-proxy.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,26 +23,26 @@ var RoutingProxy = exports.RoutingProxy = function (options) {

var self = this;
options = options || {};

if (options.router) {
this.proxyTable = new ProxyTable(options);
this.proxyTable.on('routes', function (routes) {
self.emit('routes', routes);
});
}

//
// Create a set of `HttpProxy` objects to be used later on calls
// Create a set of `HttpProxy` objects to be used later on calls
// to `.proxyRequest()` and `.proxyWebSocketRequest()`.
//
this.proxies = {};

//
// Setup default target options (such as `https`).
//
this.target  = {};
this.target.https = options.target && options.target.https;

//
// Setup other default options to be used for instances of
// `HttpProxy` created by this `RoutingProxy` instance.
Expand All @@ -51,6 +51,18 @@ var RoutingProxy = exports.RoutingProxy = function (options) {
this.https = this.source.https || options.https;
this.enable = options.enable;
this.forward = options.forward;

//
// Listen for 'newListener' events so that we can bind 'proxyError'
// listeners to each HttpProxy's 'proxyError' event.
//
this.on('newListener', function (evt) {
if (evt === 'proxyError' || evt === 'webSocketProxyError') {
Object.keys(self.proxies).forEach(function (key) {
self.proxies[key].on(evt, this.emit.bind(this, evt));
});
}
});
};


Expand All @@ -68,30 +80,37 @@ util.inherits(RoutingProxy, events.EventEmitter);
RoutingProxy.prototype.add = function (options) {
var self = this,
key = this._getKey(options);

//
// TODO: Consume properties in `options` related to the `ProxyTable`.
//
options.target = options.target || {};
options.target.host = options.target.host || options.host;
options.target.port = options.target.port || options.port;
options.target.https = this.target && this.target.https ||
options.target && options.target.https ||
options.target.https = this.target && this.target.https ||
options.target && options.target.https ||
options.https;

//
// Setup options to pass-thru to the new `HttpProxy` instance
// for the specified `options.host` and `options.port` pair.
// for the specified `options.host` and `options.port` pair.
//
['https', 'enable', 'forward'].forEach(function (key) {
if (options[key] !== false && self[key]) {
options[key] = self[key];
}
});

this.proxies[key] = new HttpProxy(options);
this.proxies[key].on('proxyError', this.emit.bind(this, 'proxyError'));
this.proxies[key].on('webSocketProxyError', this.emit.bind(this, 'webSocketProxyError'));
if (this.listeners('proxyError').length > 0) {
this.proxies[key].on('proxyError', this.emit.bind(this, 'proxyError'));
}
if (this.listeners('webSocketProxyError').length > 0) {
this.proxies[key].on('webSocketProxyError', this.emit.bind(this, 'webSocketProxyError'));
}
this.proxies[key].on('start', this.emit.bind(this, 'start'));
this.proxies[key].on('forward', this.emit.bind(this, 'forward'));
this.proxies[key].on('end', this.emit.bind(this, 'end'));
};

//
Expand All @@ -111,18 +130,18 @@ RoutingProxy.prototype.remove = function (options) {
//
RoutingProxy.prototype.close = function () {
var self = this;

if (this.proxyTable) {
//
// Close the `RoutingTable` associated with
// Close the `RoutingTable` associated with
// this instance (if any).
//
this.proxyTable.close();
}

//
// Close all sockets for all `HttpProxy` object(s)
// associated with this instance.
// associated with this instance.
//
Object.keys(this.proxies).forEach(function (key) {
self.proxies[key].close();
Expand Down Expand Up @@ -160,11 +179,11 @@ RoutingProxy.prototype.proxyRequest = function (req, res, options) {
try {
res.writeHead(404);
res.end();
}
}
catch (er) {
console.error("res.writeHead/res.end error: %s", er.message);
}

return;
}

Expand All @@ -179,15 +198,14 @@ RoutingProxy.prototype.proxyRequest = function (req, res, options) {
options.port = location.port;
options.host = location.host;
}

var key = this._getKey(options),
proxy;

if (!this.proxies[key]) {
this.add(options);

}

}

proxy = this.proxies[key];
proxy.proxyRequest(req, res, options.buffer);
};
Expand All @@ -206,7 +224,7 @@ RoutingProxy.prototype.proxyRequest = function (req, res, options) {
//
RoutingProxy.prototype.proxyWebSocketRequest = function (req, socket, head, options) {
options = options || {};

if (this.proxyTable && !options.host) {
location = this.proxyTable.getProxyLocation(req);

Expand All @@ -217,15 +235,15 @@ RoutingProxy.prototype.proxyWebSocketRequest = function (req, socket, head, opti
options.port = location.port;
options.host = location.host;
}

var key = this._getKey(options),
proxy;

if (!this.proxies[key]) {
this.add(options);
}

proxy = this.proxies[key];
proxy = this.proxies[key];
proxy.proxyWebSocketRequest(req, socket, head, options.buffer);
};

Expand All @@ -237,14 +255,14 @@ RoutingProxy.prototype.proxyWebSocketRequest = function (req, socket, head, opti
// combination contained within.
//
RoutingProxy.prototype._getKey = function (options) {
if (!options || ((!options.host || !options.port)
if (!options || ((!options.host || !options.port)
&& (!options.target || !options.target.host || !options.target.port))) {
throw new Error('options.host and options.port or options.target are required.');
return;
}

return [
options.host || options.target.host,
options.host || options.target.host,
options.port || options.target.port
].join(':');
}