Skip to content

Commit b054cdb

Browse files
author
Hadrien Jouet
committed
Manual proxy routes are now persistent and proxies will fail gracefully if port is in use
1 parent d889e89 commit b054cdb

File tree

4 files changed

+109
-18
lines changed

4 files changed

+109
-18
lines changed

index.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,9 @@ var http_proxy = require('./lib/proxy').Proxy,
9393
//start default proxy
9494
proxy.start(app.config.get('public-port'));
9595

96+
//load persistent proxy routes
97+
proxy.autoload();
98+
9699
//define routes
97100
require('./lib/ishiki')(app, haibu, path, fs, drone, proxy);
98101

lib/proxy.js

Lines changed: 55 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
var http_proxy = require('http-proxy');
1+
var http_proxy = require('http-proxy'),
2+
proxyModel = require('../models/proxy');
23

34
var Proxy = exports.Proxy = function(app, haibu) {
45
var self = this;
@@ -44,7 +45,7 @@ var Proxy = exports.Proxy = function(app, haibu) {
4445

4546
var route_message = this.req.body.domain + ':' + port + ' > ' + pkg.host + ':' + pkg.port;
4647

47-
if (self.set(port, pkg, this.req.body.domain))
48+
if (self.set(port, pkg, this.req.body.domain, true))
4849
haibu.sendResponse(this.res, 200, {message: 'Proxy route added: ' + route_message});
4950
else
5051
haibu.sendResponse(this.res, 500, {message: 'Could not create route: ' + route_message});
@@ -130,7 +131,15 @@ Proxy.prototype.start = function(port) {
130131
//forward request to target
131132
proxy.proxyRequest(req, res, self.proxies[port].routes[host]);
132133
}
133-
}).listen(port);
134+
});
135+
136+
this.proxies[port].proxy.on('error', function(err) {
137+
//if proxy failed to start, remove it
138+
console.log('Could not start proxy on ' + port, err);
139+
delete self.proxies[port];
140+
});
141+
142+
this.proxies[port].proxy.listen(port);
134143

135144
return true;
136145
}
@@ -141,7 +150,7 @@ Proxy.prototype.start = function(port) {
141150
//stops proxy on given port
142151
Proxy.prototype.stop = function(port) {
143152
if (this.proxies[port]) {
144-
this.proxies[port].close();
153+
this.proxies[port].proxy.close();
145154

146155
return true;
147156
}
@@ -161,16 +170,25 @@ Proxy.prototype.clean = function(port) {
161170
};
162171

163172
//sets domain target
164-
Proxy.prototype.set = function(port, pkg, domain) {
165-
if (domain.trim() != '' && this.proxies[port] && pkg.host && pkg.port) {
166-
this.proxies[port].routes[domain] = {
167-
host: pkg.host,
168-
port: (pkg.env.PORT),
169-
user: pkg.user,
170-
appid: pkg.name
171-
};
172-
173-
return true;
173+
Proxy.prototype.set = function(port, pkg, domain, persist) {
174+
if (domain.trim() != '' && this.proxies[port] && pkg.host) {
175+
var target_port = (pkg.env ? pkg.env.PORT : null) || pkg.port;
176+
177+
if (target_port) {
178+
this.proxies[port].routes[domain] = {
179+
host: pkg.host,
180+
port: target_port,
181+
user: pkg.user,
182+
appid: pkg.name,
183+
persist: persist
184+
};
185+
186+
//save to db if persistent
187+
if (persist)
188+
proxyModel.createOrUpdate({host: domain, port: port}, this.proxies[port].routes[domain], function(){});
189+
190+
return true;
191+
}
174192
}
175193

176194
return false;
@@ -213,6 +231,10 @@ Proxy.prototype.getBy = function(port, match) {
213231
//delete domain target
214232
Proxy.prototype.delete = function(port, domain) {
215233
if (this.proxies[port] && this.proxies[port].routes[domain]) {
234+
//remove from db if persistent
235+
if (this.proxies[port].routes[domain].persist)
236+
proxyModel.deleteBy({source: {host: domain, port: port}}, console.log);
237+
216238
delete this.proxies[port].routes[domain];
217239

218240
return true;
@@ -260,3 +282,22 @@ Proxy.prototype.load = function(port, pkg) {
260282
return false;
261283
};
262284

285+
//load all persistent routes from db
286+
Proxy.prototype.autoload = function() {
287+
var self = this;
288+
289+
proxyModel.get(function(err, routes) {
290+
if (err)
291+
return console.log(err);
292+
293+
if (routes.length > 0) {
294+
routes.forEach(function(route) {
295+
//create proxy if it doesn't exist
296+
if (!self.proxies[route.source.port])
297+
self.start(route.source.port);
298+
299+
self.set(route.source.port, route.target, route.source.host, true);
300+
});
301+
}
302+
});
303+
};

models/drone.js

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,15 @@ var BaseModel = require('./_base').BaseModel,
55
var illegal_chars = ['/', '\\', '.', ' ', '"', '*', '<', '>', ':', '|', '?'],
66
escape_with = '__';
77

8+
var DroneModel = function() {
9+
DroneModel.super_.apply(this, arguments);
10+
};
11+
12+
util.inherits(DroneModel, BaseModel);
13+
814
//processes mongodb illegal characters in keys
915
//pre to true preprocesses, otherwise postprocesses
10-
BaseModel.prototype.process = function(data, pre) {
16+
DroneModel.prototype.process = function(data, pre) {
1117
var self = this;
1218

1319
Object.keys(data).forEach(function(key) {
@@ -35,7 +41,7 @@ BaseModel.prototype.process = function(data, pre) {
3541
return data;
3642
};
3743

38-
BaseModel.prototype.getProcessed = function(filter, callback) {
44+
DroneModel.prototype.getProcessed = function(filter, callback) {
3945
var self = this;
4046

4147
this.get(filter, function(err, result) {
@@ -50,7 +56,7 @@ BaseModel.prototype.getProcessed = function(filter, callback) {
5056
});
5157
};
5258

53-
BaseModel.prototype.createOrUpdate = function(pkg, callback) {
59+
DroneModel.prototype.createOrUpdate = function(pkg, callback) {
5460
var self = this;
5561

5662
if (pkg._id) delete pkg._id;
@@ -79,4 +85,4 @@ BaseModel.prototype.createOrUpdate = function(pkg, callback) {
7985
});
8086
};
8187

82-
module.exports = new BaseModel({collection: 'drone'});
88+
module.exports = new DroneModel({collection: 'drone'});

models/proxy.js

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
var BaseModel = require('./_base').BaseModel,
2+
util = require('util');
3+
4+
var ProxyModel = function() {
5+
ProxyModel.super_.apply(this, arguments);
6+
};
7+
8+
util.inherits(ProxyModel, BaseModel);
9+
10+
ProxyModel.prototype.createOrUpdate = function(source, target, callback) {
11+
var self = this;
12+
13+
this.get({source: source}, function(err, result) {
14+
if (err)
15+
return callback(err);
16+
17+
if (result.length == 1)
18+
self.edit(result[0]._id.toString(), {$set: {target: target}}, callback);
19+
else
20+
self.add({source: source, target: target}, callback);
21+
});
22+
};
23+
24+
ProxyModel.prototype.deleteBy = function(filter, callback) {
25+
var self = this;
26+
27+
this.get(filter, function(err, result) {
28+
if (err)
29+
return callback(err);
30+
31+
if (result.length > 0) {
32+
result.forEach(function(route) {
33+
self.delete(route._id.toString(), function() {});
34+
});
35+
36+
callback(null);
37+
}
38+
});
39+
};
40+
41+
module.exports = new ProxyModel({collection: 'proxy'});

0 commit comments

Comments
 (0)