Skip to content

Commit f765f90

Browse files
committed
[api] Finalized the RoutingProxy API
1 parent 598fe2e commit f765f90

File tree

3 files changed

+122
-37
lines changed

3 files changed

+122
-37
lines changed

lib/node-http-proxy/http-proxy.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ var HttpProxy = exports.HttpProxy = function (options) {
8080
self[key].base = httpProxy._getBase(self[key]);
8181
}
8282

83-
setupProxy('target')
83+
setupProxy('target');
8484
if (this.forward) {
8585
setupProxy('forward');
8686
}
@@ -102,7 +102,7 @@ var HttpProxy = exports.HttpProxy = function (options) {
102102
//
103103
this.source = options.source || { host: 'localhost', port: 8000 };
104104
this.source.https = this.source.https || options.https;
105-
this.changeOrigin = options.changeOrigin || false;
105+
this.changeOrigin = options.changeOrigin || false;
106106
};
107107

108108
// Inherit from events.EventEmitter

lib/node-http-proxy/proxy-table.js

+31-26
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
node-http-proxy.js: Lookup table for proxy targets in node.js
33
4-
Copyright (c) 2010 Charlie Robbins
4+
Copyright (c) 2010 Charlie Robbins
55
66
Permission is hereby granted, free of charge, to any person obtaining
77
a copy of this software and associated documentation files (the
@@ -29,39 +29,42 @@ var util = require('util'),
2929
fs = require('fs');
3030

3131
//
32-
// ### function ProxyTable (router, silent)
32+
// ### function ProxyTable (router, silent)
3333
// #### @router {Object} Object containing the host based routes
3434
// #### @silent {Boolean} Value indicating whether we should suppress logs
3535
// #### @hostnameOnly {Boolean} Value indicating if we should route based on __hostname string only__
3636
// Constructor function for the ProxyTable responsible for getting
3737
// locations of proxy targets based on ServerRequest headers; specifically
3838
// the HTTP host header.
3939
//
40-
var ProxyTable = exports.ProxyTable = function (router, silent, hostnameOnly) {
40+
var ProxyTable = exports.ProxyTable = function (options) {
4141
events.EventEmitter.call(this);
42-
43-
this.silent = typeof silent !== 'undefined' ? silent : true;
44-
this.hostnameOnly = typeof hostnameOnly !== 'undefined' ? hostnameOnly : false;
45-
46-
if (typeof router === 'object') {
42+
43+
this.silent = options.silent || options.silent !== true;
44+
this.hostnameOnly = options.hostnameOnly === true;
45+
46+
if (typeof options.router === 'object') {
4747
//
48-
// If we are passed an object literal setup
49-
// the routes with RegExps from the router
48+
// If we are passed an object literal setup
49+
// the routes with RegExps from the router
5050
//
51-
this.setRoutes(router);
51+
this.setRoutes(options.router);
5252
}
53-
else if (typeof router === 'string') {
53+
else if (typeof options.router === 'string') {
5454
//
55-
// If we are passed a string then assume it is a
55+
// If we are passed a string then assume it is a
5656
// file path, parse that file and watch it for changes
5757
//
5858
var self = this;
59-
this.routeFile = router;
60-
this.setRoutes(JSON.parse(fs.readFileSync(router)).router);
61-
59+
this.routeFile = options.router;
60+
this.setRoutes(JSON.parse(fs.readFileSync(options.router)).router);
61+
6262
fs.watchFile(this.routeFile, function () {
6363
fs.readFile(self.routeFile, function (err, data) {
64-
if (err) throw err;
64+
if (err) {
65+
self.emit('error', err);
66+
}
67+
6568
self.setRoutes(JSON.parse(data).router);
6669
self.emit('routes', self.hostnameOnly === false ? self.routes : self.router);
6770
});
@@ -78,17 +81,17 @@ var ProxyTable = exports.ProxyTable = function (router, silent, hostnameOnly) {
7881
util.inherits(ProxyTable, events.EventEmitter);
7982

8083
//
81-
// ### function setRoutes (router)
84+
// ### function setRoutes (router)
8285
// #### @router {Object} Object containing the host based routes
83-
// Sets the host-based routes to be used by this instance.
86+
// Sets the host-based routes to be used by this instance.
8487
//
8588
ProxyTable.prototype.setRoutes = function (router) {
8689
if (!router) {
8790
throw new Error('Cannot update ProxyTable routes without router.');
8891
}
89-
92+
9093
this.router = router;
91-
94+
9295
if (this.hostnameOnly === false) {
9396
var self = this;
9497
this.routes = [];
@@ -105,7 +108,7 @@ ProxyTable.prototype.setRoutes = function (router) {
105108
};
106109

107110
//
108-
// ### function getProxyLocation (req)
111+
// ### function getProxyLocation (req)
109112
// #### @req {ServerRequest} The incoming server request to get proxy information about.
110113
// Returns the proxy location based on the HTTP Headers in the ServerRequest `req`
111114
// available to this instance.
@@ -114,14 +117,14 @@ ProxyTable.prototype.getProxyLocation = function (req) {
114117
if (!req || !req.headers || !req.headers.host) {
115118
return null;
116119
}
117-
120+
118121
var target = req.headers.host.split(':')[0];
119122
if (this.hostnameOnly == true) {
120123
if (this.router.hasOwnProperty(target)) {
121124
var location = this.router[target].split(':'),
122125
host = location[0],
123126
port = location.length === 1 ? 80 : location[1];
124-
127+
125128
return {
126129
port: port,
127130
host: host
@@ -131,7 +134,9 @@ ProxyTable.prototype.getProxyLocation = function (req) {
131134
else {
132135
target += req.url;
133136
for (var i in this.routes) {
134-
var match, route = this.routes[i];
137+
var route = this.routes[i],
138+
match;
139+
135140
if (match = target.match(route.route)) {
136141
var location = route.target.split(':'),
137142
host = location[0],
@@ -144,7 +149,7 @@ ProxyTable.prototype.getProxyLocation = function (req) {
144149
}
145150
}
146151
}
147-
152+
148153
return null;
149154
};
150155

lib/node-http-proxy/routing-proxy.js

+89-9
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
/*
2+
* routing-proxy.js: A routing proxy consuming a RoutingTable and multiple HttpProxy instances
3+
*
4+
* (C) 2011 Nodejitsu Inc.
5+
* MIT LICENCE
6+
*
7+
*/
8+
19
var events = require('events'),
210
util = require('util'),
311
HttpProxy = require('./http-proxy').HttpProxy,
@@ -12,18 +20,37 @@ var events = require('events'),
1220
//
1321
var RoutingProxy = exports.RoutingProxy = function (options) {
1422
events.EventEmitter.call(this);
23+
24+
var self = this;
25+
options = options || {};
1526

1627
if (options.router) {
17-
//
18-
// TODO: Consume the RoutingTable for various things: `this.proxyTable`
19-
//
28+
this.proxyTable = new ProxyTable(options);
29+
this.proxyTable.on('routes', function (routes) {
30+
self.emit('routes', routes);
31+
});
2032
}
2133

2234
//
2335
// Create a set of `HttpProxy` objects to be used later on calls
2436
// to `.proxyRequest()` and `.proxyWebSocketRequest()`.
2537
//
2638
this.proxies = {};
39+
40+
//
41+
// Setup default target options (such as `https`).
42+
//
43+
this.target  = {};
44+
this.target.https = options.target && options.target.https;
45+
46+
//
47+
// Setup other default options to be used for instances of
48+
// `HttpProxy` created by this `RoutingProxy` instance.
49+
//
50+
this.source = options.source || { host: 'localhost', port: 8000 };
51+
this.https = this.source.https || options.https;
52+
this.enable = options.enable;
53+
this.forward = options.forward;
2754
};
2855

2956

@@ -39,7 +66,30 @@ util.inherits(RoutingProxy, events.EventEmitter);
3966
// for the specified `options.host` and `options.port`.
4067
//
4168
RoutingProxy.prototype.add = function (options) {
69+
var self = this,
70+
key = this._getKey(options);
71+
72+
//
73+
// TODO: Consume properties in `options` related to the `ProxyTable`.
74+
//
75+
options.target = options.target || {};
76+
options.target.host = options.target.host || options.host;
77+
options.target.port = options.target.port || options.port;
78+
options.target.https = this.target && this.target.https ||
79+
options.target && options.target.https ||
80+
options.https;
81+
82+
//
83+
// Setup options to pass-thru to the new `HttpProxy` instance
84+
// for the specified `options.host` and `options.port` pair.
85+
//
86+
['https', 'enable', 'forward'].forEach(function (key) {
87+
if (options[key] !== false && self[key]) {
88+
options[key] = self[key];
89+
}
90+
});
4291

92+
this.proxies[key] = new HttpProxy(options);
4393
};
4494

4595
//
@@ -49,7 +99,7 @@ RoutingProxy.prototype.add = function (options) {
4999
// for the specified `options.host` and `options.port` (if they exist).
50100
//
51101
RoutingProxy.prototype.remove = function (options) {
52-
102+
var key = this._getKey(options);
53103
};
54104

55105
//
@@ -129,8 +179,13 @@ RoutingProxy.prototype.proxyRequest = function (req, res, options) {
129179
}
130180

131181
var key = options.host + ':' + options.port,
132-
proxy = this.proxies[key] || this._addTarget(options);
133-
182+
proxy;
183+
184+
if (!this.proxies[key]) {
185+
this.add(options);
186+
}
187+
188+
proxy = this.proxies[key];
134189
proxy.proxyRequest(req, res, options.buffer);
135190
};
136191

@@ -161,7 +216,32 @@ RoutingProxy.prototype.proxyWebSocketRequest = function (req, socket, head, opti
161216
}
162217

163218
var key = options.host + ':' + options.port,
164-
proxy = this.proxies[key] || this._addTarget(options);
165-
219+
proxy;
220+
221+
if (!this.proxies[key]) {
222+
this.add(options);
223+
}
224+
225+
proxy = this.proxies[key];
166226
proxy.proxyWebSocketRequest(req, socket, head, options.buffer);
167-
};
227+
};
228+
229+
//
230+
// ### @private function _getKey (options)
231+
// #### @options {Object} Options to extract the key from
232+
// Ensures that the appropriate options are present in the `options`
233+
// provided and responds with a string key representing the `host`, `port`
234+
// combination contained within.
235+
//
236+
RoutingProxy.prototype._getKey = function (options) {
237+
if (!options || ((!options.host || !options.port)
238+
&& (!options.target || !options.target.host || !options.target.port))) {
239+
throw new Error('options.host and options.port or options.target are required.');
240+
return;
241+
}
242+
243+
return [
244+
options.host || options.target.host,
245+
options.port || options.target.port
246+
].join(':');
247+
}

0 commit comments

Comments
 (0)