-
Notifications
You must be signed in to change notification settings - Fork 0
/
devmon.js
executable file
·158 lines (132 loc) · 5.05 KB
/
devmon.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
#!/usr/bin/env node
var fs = require('fs');
//var path = require('path');
var child_process = require('child_process');
var forever = require('forever-monitor');
var connect = require('connect');
var httpProxy = require('http-proxy');
var _ = require('underscore');
var DEBUG = true;
var PORT = process.env.PORT || 5000;
var devmon_log = function(s) {
console.log('[Appcubator] ' + s);
};
String.prototype.endsWith = function(suffix) {
return this.indexOf(suffix, this.length - suffix.length) !== -1;
};
String.prototype.startsWith = function (str){
return this.slice(0, str.length) == str;
};
/* name is used for printing logs.
* command should be an array of args.
* watchDirectory is optional, for when you want to watch files. */
var spawn = function (name, command, watchDirectory, options, exitHandler) {
options = options || {};
if (watchDirectory) {
options.watch = true;
options.watchDirectory = watchDirectory;
}
options.minUptime = 2*1000; // If app can't stand on it's feet for 2 seconds,
options.spinSleepTime = 5*1000; // wait 5 seconds before restarting.
options.outFile = '/tmp/' + name + '-out.log'; // Path to log output from child stdout
options.errFile = '/tmp/' + name + '-err.log'; // Path to log output from child stderr
var child = forever.start(command, options);
child.on('start', function () { devmon_log(name + ' has started');});
child.on('exit', function () { devmon_log(name + ' has quit'); exitHandler(); });
child.on('restart', function () { devmon_log(name + ' has restarted'); });
child.on('error', function (err) { devmon_log(name + ' had an error: ' + err.toString()); });
return child;
};
// will set it up to remove from the list when process exits.
var spawnFromConfig = function(config, parentArr) {
var options = config.options || {};
options.env = options.env || config.env;
options.cwd = options.cwd || config.cwd;
var removeHandler = function() {
// Find and remove item from an array
var i = parentArr.indexOf(config);
if(i != -1) {
parentArr.splice(i, 1);
} else {
// this could be interesting.
}
};
var child;
if (config.name === 'App')
child = spawn(config.name, config.cmd, '.', options, removeHandler);
else
child = spawn(config.name, config.cmd, null, options, removeHandler);
config.child = child;
};
/* If host matches a config host, return the config.
* Otherwise return the app config. */
var hostToConfig = function(host, configs) {
var config, i, matched = false;
for (i = 0; i < configs.length; i ++) {
config = configs[i];
// config.domain is null. don't match this, it's prolly appPConfig, which is the fallback in case nothing else is found
if (!config.domain)
continue;
if (host.toLowerCase().startsWith(config.domain.toLowerCase() + '.')) {
matched = true;
break;
}
}
if (!matched)
config = appPConfig;
return config;
};
var configureProxy = function(config) {
var proxy = httpProxy.createProxyServer({
target: 'http://localhost:' + config.port
});
config.proxy = proxy;
};
/* Each config is an obj with keys [name, domain, port, webSockFlag] */
var setupDynamicProxyServer = function (configs) {
var proxyServer = connect.createServer(
// Host based routing
function (req, res, next) {
var host = req.headers.host;
var config = hostToConfig(host, configs);
devmon_log('Incoming http request host \'' + host + '\' matched \'' + config.name +'\', routing to :' + config.port);
config.proxy.web(req, res, function (err, req, res) {
res.writeHead(500, {
'Content-Type': 'text/plain'
});
res.end('The backend \'' + config.name + '\' is down. Please see the logs.');
});
}
).listen(PORT);
proxyServer.on('upgrade', function (req, socket, head) {
// Listen to the `upgrade` event and proxy the
// WebSocket requests as well.
//
var host = req.headers.host;
var config = hostToConfig(host, configs);
if (config.webSockFlag) {
devmon_log('Incoming ws request host \'' + host + '\' matched \'' + config.name +'\', routing to :' + config.port);
config.proxy.ws(req, socket, head);
}
});
proxyServer.on('error', function (i) {
console.log('NOOOOOO');
});
return proxyServer;
};
/* Yes this is bad code, resulting from a forced refactor. */
var appSConfig, appPConfig, CONFIG;
exports.setGlobal = function (name, val) {
if (name === 'appSConfig')
appSConfig = val;
else if (name === 'appPConfig')
appPConfig = val;
else if (name === 'CONFIG')
CONFIG = val;
else
throw 'wat';
};
exports.log = devmon_log;
exports.spawnFromConfig = spawnFromConfig;
exports.configureProxy = configureProxy;
exports.setupDynamicProxyServer = setupDynamicProxyServer;