Skip to content

Commit b36c51a

Browse files
committed
Make it all async
1 parent 7d34c7d commit b36c51a

File tree

6 files changed

+459
-350
lines changed

6 files changed

+459
-350
lines changed

lib/configproxy.js

+117-85
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ function ConfigurableProxy (options) {
169169
}
170170

171171
// proxy requests separately
172-
var proxy_callback = log_errors(that.handle_proxy_web);
172+
var proxy_callback = log_errors(this.handle_proxy_web);
173173
if ( this.options.ssl ) {
174174
this.proxy_server = https.createServer(this.options.ssl, proxy_callback);
175175
} else {
@@ -185,21 +185,33 @@ function ConfigurableProxy (options) {
185185

186186
util.inherits(ConfigurableProxy, EventEmitter);
187187

188-
ConfigurableProxy.prototype.add_route = function (path, data) {
188+
ConfigurableProxy.prototype.add_route = function (path, data, cb) {
189189
// add a route to the routing table
190190
path = this._routes.cleanPath(path);
191191
if (this.host_routing && path !== '/') {
192192
data.host = path.split('/')[1];
193193
}
194-
this._routes.add(path, data);
195-
this.update_last_activity(path);
194+
195+
var that = this;
196+
197+
this._routes.add(path, data, function () {
198+
that.update_last_activity(path, function () {
199+
if (typeof(cb) === "function") {
200+
cb();
201+
}
202+
});
203+
});
196204
};
197205

198-
ConfigurableProxy.prototype.remove_route = function (path) {
206+
ConfigurableProxy.prototype.remove_route = function (path, cb) {
199207
// remove a route from the routing table
200-
if (this._routes.hasRoute(path)) {
201-
this._routes.remove(path);
202-
}
208+
var routes = this._routes;
209+
210+
routes.hasRoute(path, function (result) {
211+
if (result) {
212+
routes.remove(path, cb);
213+
}
214+
});
203215
};
204216

205217
ConfigurableProxy.prototype.get_routes = function (req, res) {
@@ -220,20 +232,25 @@ ConfigurableProxy.prototype.get_routes = function (req, res) {
220232
}
221233
}
222234
res.writeHead(200, { 'Content-Type': 'application/json' });
223-
var routes = {};
224-
if (inactive_since) {
225-
Object.keys(this._routes.getAll()).map(function (path) {
226-
var route = that._routes.get(path);
227-
if (route.last_activity < inactive_since) {
228-
routes[path] = route;
229-
}
230-
});
231-
} else {
232-
routes = this._routes.getAll();
233-
}
234-
res.write(JSON.stringify(routes));
235-
res.end();
236-
this.statsd.increment('api.route.get', 1);
235+
236+
this._routes.getAll(function (routes) {
237+
var results = {};
238+
239+
if (inactive_since) {
240+
var keys = Object.keys(routes).filter(function (key) {
241+
return routes[key].last_activity < inactive_since;
242+
});
243+
244+
keys.forEach(function (key) { results[key] = routes[key]; });
245+
} else {
246+
results = routes;
247+
}
248+
249+
250+
res.write(JSON.stringify(results));
251+
res.end();
252+
that.statsd.increment('api.route.get', 1);
253+
});
237254
};
238255

239256
ConfigurableProxy.prototype.post_routes = function (req, res, path, data) {
@@ -247,47 +264,63 @@ ConfigurableProxy.prototype.post_routes = function (req, res, path, data) {
247264
return;
248265
}
249266

250-
this.add_route(path, data);
251-
res.writeHead(201);
252-
res.end();
253-
this.statsd.increment('api.route.add', 1);
267+
var that = this;
268+
this.add_route(path, data, function () {
269+
res.writeHead(201);
270+
res.end();
271+
that.statsd.increment('api.route.add', 1);
272+
});
254273
};
255274

256275
ConfigurableProxy.prototype.delete_routes = function (req, res, path) {
257276
// DELETE removes an existing route
258277
log.debug('DELETE', path);
259-
if (this._routes.hasRoute(path)) {
260-
this.remove_route(path);
261-
res.writeHead(204);
262-
} else {
263-
res.writeHead(404);
264-
}
265-
res.end();
266-
this.statsd.increment('api.route.delete', 1);
278+
279+
var that = this;
280+
this._routes.hasRoute(path, function (result) {
281+
if (result) {
282+
that.remove_route(path, function () {
283+
res.writeHead(204);
284+
res.end();
285+
that.statsd.increment('api.route.delete', 1);
286+
});
287+
} else {
288+
res.writeHead(404);
289+
res.end();
290+
that.statsd.increment('api.route.delete', 1);
291+
}
292+
});
267293
};
268294

269-
ConfigurableProxy.prototype.target_for_req = function (req) {
295+
ConfigurableProxy.prototype.target_for_req = function (req, cb) {
270296
var timer = this.statsd.createTimer('find_target_for_req');
271297
// return proxy target for a given url path
272298
var base_path = (this.host_routing) ? '/' + parse_host(req) : '';
273-
var route = this._routes.getTarget(base_path + decodeURIComponent(req.url));
274-
timer.stop();
275-
if (route) {
276-
return {
277-
prefix: route.prefix,
278-
target: route.data.target,
279-
};
280-
}
299+
300+
this._routes.getTarget(base_path + decodeURIComponent(req.url), function (route) {
301+
timer.stop();
302+
var result = route ? { prefix: route.prefix, target: route.data.target } : null;
303+
cb(result);
304+
});
281305
};
282306

283-
ConfigurableProxy.prototype.update_last_activity = function (prefix) {
307+
ConfigurableProxy.prototype.update_last_activity = function (prefix, cb) {
284308
var timer = this.statsd.createTimer('last_activity_updating');
285-
// note last activity in routing table
286-
if (this._routes.hasRoute(prefix)) {
287-
// route may have been deleted with open connections
288-
this._routes.update(prefix, { "last_activity": new Date() });
289-
}
290-
timer.stop();
309+
var routes = this._routes;
310+
311+
routes.hasRoute(prefix, function (result) {
312+
cb = cb || function() {};
313+
314+
if (result) {
315+
routes.update(prefix, { "last_activity": new Date() }, function () {
316+
timer.stop();
317+
cb();
318+
});
319+
} else {
320+
timer.stop();
321+
cb();
322+
}
323+
});
291324
};
292325

293326
ConfigurableProxy.prototype._handle_proxy_error_default = function (code, kind, req, res) {
@@ -360,48 +393,47 @@ ConfigurableProxy.prototype.handle_proxy_error = function (code, kind, req, res)
360393
ConfigurableProxy.prototype.handle_proxy = function (kind, req, res) {
361394
// proxy any request
362395
var that = this;
396+
var args = Array.prototype.slice.call(arguments, 1);
397+
363398
// get the proxy target
364-
var match = this.target_for_req(req);
365-
if (!match) {
366-
this.handle_proxy_error(404, kind, req, res);
367-
return;
368-
}
369-
this.emit("proxy_request", req, res);
370-
var prefix = match.prefix;
371-
var target = match.target;
372-
log.debug("PROXY", kind.toUpperCase(), req.url, "to", target);
373-
if (!this.includePrefix) {
374-
req.url = req.url.slice(prefix.length);
375-
}
399+
this.target_for_req(req, function (match) {
400+
if (!match) {
401+
that.handle_proxy_error(404, kind, req, res);
402+
return;
403+
}
376404

377-
// pop method off the front
378-
var args = arguments_array(arguments);
379-
args.shift();
405+
that.emit("proxy_request", req, res);
406+
var prefix = match.prefix;
407+
var target = match.target;
408+
log.debug("PROXY", kind.toUpperCase(), req.url, "to", target);
409+
if (!that.includePrefix) {
410+
req.url = req.url.slice(prefix.length);
411+
}
380412

381-
// add config argument
382-
args.push({
383-
target: target
384-
});
413+
// add config argument
414+
args.push({ target: target });
385415

386-
// add error handling
387-
args.push(function (e) {
388-
log.error("Proxy error: ", e);
389-
that.handle_proxy_error(503, kind, req, res);
390-
});
416+
// add error handling
417+
args.push(function (e) {
418+
log.error("Proxy error: ", e);
419+
that.handle_proxy_error(503, kind, req, res);
420+
});
391421

392-
// update last activity timestamp in routing table
393-
this.update_last_activity(prefix);
422+
// update timestamp on any reply data as well (this includes websocket data)
423+
req.on('data', function () {
424+
that.update_last_activity(prefix);
425+
});
394426

395-
// update timestamp on any reply data as well (this includes websocket data)
396-
req.on('data', function () {
397-
that.update_last_activity(prefix);
398-
});
399-
res.on('data', function () {
400-
that.update_last_activity(prefix);
401-
});
427+
res.on('data', function () {
428+
that.update_last_activity(prefix);
429+
});
402430

403-
// dispatch the actual method
404-
this.proxy[kind].apply(this.proxy, args);
431+
// update last activity timestamp in routing table
432+
that.update_last_activity(prefix, function () {
433+
// dispatch the actual method
434+
that.proxy[kind].apply(that.proxy, args);
435+
});
436+
});
405437
};
406438

407439
ConfigurableProxy.prototype.handle_proxy_ws = function (req, res, head) {

lib/store.js

+31-19
Original file line numberDiff line numberDiff line change
@@ -9,61 +9,73 @@ var NotImplemented = function (name) {
99

1010
var BaseStore = Object.create(Object.prototype, {
1111
// "abstract" methods
12-
get: { value: function (path) { throw NotImplemented("get"); } },
13-
getTarget: { value: function (path) { throw NotImplemented("getTarget"); } },
14-
getAll: { value: function (path) { throw NotImplemented("getAll"); } },
15-
add: { value: function (path) { throw NotImplemented("add"); } },
16-
update: { value: function (path) { throw NotImplemented("update"); } },
17-
remove: { value: function (path) { throw NotImplemented("remove"); } },
18-
hasRoute: { value: function (path) { throw NotImplemented("hasRoute"); } },
12+
get: { value: function () { throw NotImplemented("get"); } },
13+
getTarget: { value: function () { throw NotImplemented("getTarget"); } },
14+
getAll: { value: function () { throw NotImplemented("getAll"); } },
15+
add: { value: function () { throw NotImplemented("add"); } },
16+
update: { value: function () { throw NotImplemented("update"); } },
17+
remove: { value: function () { throw NotImplemented("remove"); } },
18+
hasRoute: { value: function () { throw NotImplemented("hasRoute"); } },
1919

2020
cleanPath: {
2121
value: function (path) {
2222
return trie.trim_prefix(path);
2323
}
24+
},
25+
26+
notify: {
27+
value: function (cb) {
28+
if (typeof(cb) === "function") {
29+
var args = Array.prototype.slice.call(arguments, 1);
30+
cb.apply(this, args);
31+
}
32+
}
2433
}
2534
});
2635

2736
function MemoryStore () {
2837
var routes = {};
29-
var urls = new trie.URLTrie()
38+
var urls = new trie.URLTrie();
3039

3140
return Object.create(BaseStore, {
3241
get: {
33-
value: function (path) {
34-
return routes[path];
42+
value: function (path, cb) {
43+
this.notify(cb, routes[path]);
3544
}
3645
},
3746
getTarget: {
38-
value: function (path) {
39-
return urls.get(path);
47+
value: function (path, cb) {
48+
this.notify(cb, urls.get(path));
4049
}
4150
},
4251
getAll: {
43-
value: function () {
44-
return routes;
52+
value: function (cb) {
53+
this.notify(cb, routes);
4554
}
4655
},
4756
add: {
48-
value: function (path, data) {
57+
value: function (path, data, cb) {
4958
routes[path] = data;
5059
urls.add(path, data);
60+
this.notify(cb);
5161
}
5262
},
5363
update: {
54-
value: function (path, data) {
64+
value: function (path, data, cb) {
5565
Object.assign(routes[path], data);
66+
this.notify(cb);
5667
}
5768
},
5869
remove: {
59-
value: function (path) {
70+
value: function (path, cb) {
6071
delete routes[path];
6172
urls.remove(path);
73+
this.notify(cb);
6274
}
6375
},
6476
hasRoute: {
65-
value: function (path) {
66-
return routes.hasOwnProperty(path);
77+
value: function (path, cb) {
78+
this.notify(cb, routes.hasOwnProperty(path));
6779
}
6880
}
6981
});

0 commit comments

Comments
 (0)