whistle 2.10.5 → 2.10.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/menu.html +2 -2
- package/assets/modal.html +2 -2
- package/assets/tab.html +2 -2
- package/bin/api.js +545 -0
- package/bin/import.js +3 -3
- package/bin/plugin.js +4 -8
- package/bin/use.js +22 -8
- package/bin/util.js +12 -7
- package/bin/whistle.js +11 -1
- package/biz/webui/cgi-bin/abort.js +14 -5
- package/biz/webui/cgi-bin/frames.js +12 -0
- package/biz/webui/cgi-bin/get-session.js +7 -3
- package/biz/webui/cgi-bin/is-enabled-https.js +6 -0
- package/biz/webui/cgi-bin/plugins/disable-plugin.js +16 -7
- package/biz/webui/cgi-bin/plugins/list.js +17 -0
- package/biz/webui/cgi-bin/plugins/plugin.js +21 -0
- package/biz/webui/cgi-bin/plugins/status.js +21 -0
- package/biz/webui/cgi-bin/rules/is-multi-select.js +7 -0
- package/biz/webui/cgi-bin/rules/move-top.js +11 -0
- package/biz/webui/cgi-bin/rules/select.js +1 -1
- package/biz/webui/cgi-bin/rules/select2.js +16 -0
- package/biz/webui/cgi-bin/rules/status.js +6 -0
- package/biz/webui/cgi-bin/rules/unselect.js +3 -2
- package/biz/webui/cgi-bin/rules/unselect2.js +18 -0
- package/biz/webui/cgi-bin/rules/value.js +19 -0
- package/biz/webui/cgi-bin/sessions.js +6 -0
- package/biz/webui/cgi-bin/util.js +45 -20
- package/biz/webui/htdocs/index.html +1 -1
- package/biz/webui/htdocs/js/index.js +51 -51
- package/biz/webui/lib/index.js +1 -3
- package/lib/https/index.js +7 -5
- package/lib/init.js +1 -0
- package/lib/inspectors/data.js +39 -34
- package/lib/inspectors/req.js +9 -6
- package/lib/inspectors/res.js +10 -14
- package/lib/plugins/index.js +2 -2
- package/lib/plugins/load-plugin.js +19 -8
- package/lib/rules/util.js +20 -10
- package/lib/service/composer.js +7 -22
- package/lib/service/data-center.js +0 -12
- package/lib/service/generate-saz.js +2 -2
- package/lib/service/service.js +8 -7
- package/lib/service/util.js +6 -16
- package/lib/socket-mgr.js +23 -17
- package/lib/tunnel.js +7 -17
- package/lib/upgrade.js +4 -8
- package/lib/util/common.js +78 -11
- package/lib/util/data-server.js +273 -0
- package/lib/util/file-mgr.js +7 -4
- package/lib/util/http-mgr.js +17 -9
- package/lib/util/index.js +67 -54
- package/lib/util/parse-url.js +11 -9
- package/lib/util/patch.js +2 -6
- package/lib/util/speed-transform.js +17 -6
- package/lib/util/whistle-transform.js +18 -7
- package/package.json +10 -7
package/bin/use.js
CHANGED
|
@@ -27,9 +27,6 @@ function handleRules(options, filepath, callback) {
|
|
|
27
27
|
port: options.port,
|
|
28
28
|
existsPlugin: existsPlugin
|
|
29
29
|
};
|
|
30
|
-
if (options && options.host) {
|
|
31
|
-
opts.host = options.host;
|
|
32
|
-
}
|
|
33
30
|
getRules(callback, opts);
|
|
34
31
|
});
|
|
35
32
|
}
|
|
@@ -74,22 +71,27 @@ function getHost(options) {
|
|
|
74
71
|
return util.joinIpPort(options.host || DEFAULT_OPTIONS.host, options.port);
|
|
75
72
|
}
|
|
76
73
|
|
|
77
|
-
function
|
|
78
|
-
var reqOptions = url.parse('http://' + getHost(options) + '/cgi-bin/
|
|
74
|
+
function getReqOpts(options, path, jsJson) {
|
|
75
|
+
var reqOptions = url.parse('http://' + getHost(options) + '/cgi-bin/' + path);
|
|
79
76
|
reqOptions.headers = {
|
|
80
|
-
'content-type': 'application/x-www-form-urlencoded'
|
|
77
|
+
'content-type': 'application/' + (jsJson ? 'json' : 'x-www-form-urlencoded')
|
|
81
78
|
};
|
|
82
79
|
if (options.specialAuth) {
|
|
83
80
|
reqOptions.headers['x-whistle-special-auth'] = options.specialAuth;
|
|
84
81
|
}
|
|
85
|
-
reqOptions.method = 'POST';
|
|
86
82
|
if (options.username || options.password) {
|
|
87
83
|
var auth = [options.username || '', options.password || ''].join(':');
|
|
88
|
-
reqOptions.headers.authorization = 'Basic ' +
|
|
84
|
+
reqOptions.headers.authorization = 'Basic ' + Buffer.from(auth).toString('base64');
|
|
89
85
|
}
|
|
90
86
|
return reqOptions;
|
|
91
87
|
}
|
|
92
88
|
|
|
89
|
+
function getReqOptions(options) {
|
|
90
|
+
var reqOptions = getReqOpts(options, 'rules/project');
|
|
91
|
+
reqOptions.method = 'POST';
|
|
92
|
+
return reqOptions;
|
|
93
|
+
}
|
|
94
|
+
|
|
93
95
|
function request(reqOptions, body, cb) {
|
|
94
96
|
var done;
|
|
95
97
|
var handleCb = function(err, data) {
|
|
@@ -198,6 +200,7 @@ function getConfig(filepath, storage, force, isClient, cb) {
|
|
|
198
200
|
force = storage;
|
|
199
201
|
storage = temp;
|
|
200
202
|
}
|
|
203
|
+
// getConfig(options, callback)
|
|
201
204
|
if (typeof storage === 'function') {
|
|
202
205
|
callback = storage;
|
|
203
206
|
storage = '';
|
|
@@ -315,6 +318,17 @@ module.exports = function(filepath, storage, force, isClient) {
|
|
|
315
318
|
});
|
|
316
319
|
};
|
|
317
320
|
|
|
321
|
+
module.exports.getConfig = function(options, cb) {
|
|
322
|
+
if (typeof options === 'function') {
|
|
323
|
+
cb = options;
|
|
324
|
+
options = {};
|
|
325
|
+
} else if (options === true) {
|
|
326
|
+
options = { client: true };
|
|
327
|
+
}
|
|
328
|
+
return getConfig(options, null, null, null, cb);
|
|
329
|
+
};
|
|
330
|
+
|
|
331
|
+
module.exports.getReqOpts = getReqOpts;
|
|
318
332
|
module.exports.existsPlugin = existsPlugin;
|
|
319
333
|
module.exports.getOptions = function(cb, storage, isClient) {
|
|
320
334
|
if (typeof cb !== 'function') {
|
package/bin/util.js
CHANGED
|
@@ -184,16 +184,21 @@ exports.getDefaultPort = function () {
|
|
|
184
184
|
return port > 0 ? port : 8899;
|
|
185
185
|
};
|
|
186
186
|
|
|
187
|
-
exports.getBody = function (res, callback) {
|
|
188
|
-
|
|
187
|
+
exports.getBody = function (res, callback, isRaw) {
|
|
188
|
+
if (res.statusCode != 200) {
|
|
189
|
+
res.destroy();
|
|
190
|
+
return callback('Bad response (' + res.statusCode + ')');
|
|
191
|
+
}
|
|
192
|
+
var resBody = [];
|
|
189
193
|
res.on('data', function(data) {
|
|
190
|
-
resBody
|
|
194
|
+
resBody.push(data);
|
|
191
195
|
});
|
|
192
196
|
res.on('end', function() {
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
+
resBody = Buffer.concat(resBody);
|
|
198
|
+
try {
|
|
199
|
+
callback(null, isRaw ? resBody : JSON.parse(resBody.toString()));
|
|
200
|
+
} catch(e) {
|
|
201
|
+
callback(e);
|
|
197
202
|
}
|
|
198
203
|
});
|
|
199
204
|
};
|
package/bin/whistle.js
CHANGED
|
@@ -124,6 +124,9 @@ program.setConfig({
|
|
|
124
124
|
}
|
|
125
125
|
});
|
|
126
126
|
|
|
127
|
+
program
|
|
128
|
+
.command('root')
|
|
129
|
+
.description('Output the install root (code directory) of Whistle');
|
|
127
130
|
program
|
|
128
131
|
.command('status')
|
|
129
132
|
.description('Display running status');
|
|
@@ -190,7 +193,14 @@ var removeItem = function(list, name) {
|
|
|
190
193
|
if (argv.indexOf('--init') !== -1) {
|
|
191
194
|
process.env.WHISTLE_MODE = (process.env.WHISTLE_MODE || '') + '|persistentCapture';
|
|
192
195
|
}
|
|
193
|
-
if (cmd === '
|
|
196
|
+
if (cmd === 'root') {
|
|
197
|
+
var root = path.join(__dirname, '../');
|
|
198
|
+
var file = typeof argv[3] === 'string' ? argv[3].trim() : '';
|
|
199
|
+
if (file) {
|
|
200
|
+
root = path.join(root, file);
|
|
201
|
+
}
|
|
202
|
+
process.stdout.write(root);
|
|
203
|
+
} else if (cmd === 'status') {
|
|
194
204
|
var all = argv[3] === '--all' || argv[3] === '-l';
|
|
195
205
|
if (argv[3] === '-S') {
|
|
196
206
|
storage = argv[4];
|
|
@@ -1,15 +1,24 @@
|
|
|
1
1
|
var proxy = require('../lib/proxy');
|
|
2
2
|
var socketMgr = proxy.socketMgr;
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
proxy.abortRequest(reqId);
|
|
6
|
-
socketMgr.abort(reqId);
|
|
7
|
-
}
|
|
4
|
+
var MAX_COUNT = 1200;
|
|
8
5
|
|
|
9
6
|
module.exports = function(req, res) {
|
|
10
7
|
var list = req.body.list;
|
|
11
8
|
if (list && typeof list === 'string') {
|
|
12
|
-
list.split(',')
|
|
9
|
+
list = list.split(',');
|
|
10
|
+
var len = list.length;
|
|
11
|
+
if (len > MAX_COUNT) {
|
|
12
|
+
len = MAX_COUNT;
|
|
13
|
+
list = list.slice(0, MAX_COUNT);
|
|
14
|
+
}
|
|
15
|
+
for (var i = 0; i < len; i++) {
|
|
16
|
+
var reqId = list[i];
|
|
17
|
+
if (reqId) {
|
|
18
|
+
proxy.abortRequest(reqId);
|
|
19
|
+
socketMgr.abort(reqId);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
13
22
|
}
|
|
14
23
|
res.json({ ec: 0 });
|
|
15
24
|
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
var util = require('./util');
|
|
2
|
+
var common = require('../../../lib/util/common');
|
|
3
|
+
var proxy = require('../lib/proxy');
|
|
4
|
+
|
|
5
|
+
module.exports = function(req, res) {
|
|
6
|
+
var body = req.body;
|
|
7
|
+
if (!common.isString(body.reqId)) {
|
|
8
|
+
res.statusCode = 400;
|
|
9
|
+
return res.end('reqId is required');
|
|
10
|
+
}
|
|
11
|
+
util.sendGzip(req, res, proxy.getFramesForApi(body));
|
|
12
|
+
};
|
|
@@ -13,7 +13,8 @@ module.exports = function(req, res) {
|
|
|
13
13
|
var reqList = parseArray(req.query.reqList);
|
|
14
14
|
var resList = parseArray(req.query.resList);
|
|
15
15
|
var result = {};
|
|
16
|
-
|
|
16
|
+
var isReq;
|
|
17
|
+
var appendResult = function(id) {
|
|
17
18
|
if (result[id] != null) {
|
|
18
19
|
return;
|
|
19
20
|
}
|
|
@@ -22,9 +23,12 @@ module.exports = function(req, res) {
|
|
|
22
23
|
result[id] = 0;
|
|
23
24
|
return;
|
|
24
25
|
}
|
|
25
|
-
if ((item.requestTime &&
|
|
26
|
+
if ((item.requestTime && isReq) || item.endTime) {
|
|
26
27
|
result[id] = item;
|
|
27
28
|
}
|
|
28
|
-
}
|
|
29
|
+
};
|
|
30
|
+
resList.forEach(appendResult);
|
|
31
|
+
isReq = true;
|
|
32
|
+
reqList.forEach(appendResult);
|
|
29
33
|
res.json(result);
|
|
30
34
|
};
|
|
@@ -2,13 +2,22 @@ var properties = require('../../../../lib/rules/util').properties;
|
|
|
2
2
|
var pluginMgr = require('../../lib/proxy').pluginMgr;
|
|
3
3
|
|
|
4
4
|
module.exports = function(req, res) {
|
|
5
|
+
var name = req.body.name;
|
|
5
6
|
var disabledPlugins = properties.get('disabledPlugins') || {};
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
var exists = false;
|
|
8
|
+
if (typeof name === 'string') {
|
|
9
|
+
name = name.trim();
|
|
10
|
+
name = name.substring(name.lastIndexOf('.') + 1);
|
|
11
|
+
exists = !!pluginMgr.getPluginByName(name);
|
|
12
|
+
if (exists) {
|
|
13
|
+
if (req.body.disabled == 1) {
|
|
14
|
+
disabledPlugins[name] = 1;
|
|
15
|
+
} else {
|
|
16
|
+
delete disabledPlugins[name];
|
|
17
|
+
}
|
|
18
|
+
properties.set('disabledPlugins', disabledPlugins);
|
|
19
|
+
pluginMgr.updateRules();
|
|
20
|
+
}
|
|
10
21
|
}
|
|
11
|
-
|
|
12
|
-
pluginMgr.updateRules();
|
|
13
|
-
res.json({ec: 0, data: disabledPlugins});
|
|
22
|
+
res.json({ec: 0, data: disabledPlugins, exists: exists});
|
|
14
23
|
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
var pluginMgr = require('../../lib/proxy').pluginMgr;
|
|
2
|
+
var sortPlugins = require('../util').sortPlugins;
|
|
3
|
+
var properties = require('../../../../lib/rules/util').properties;
|
|
4
|
+
var extend = require('extend');
|
|
5
|
+
|
|
6
|
+
module.exports = function(req, res) {
|
|
7
|
+
var disabledPlugins = properties.get('disabledPlugins');
|
|
8
|
+
var list = sortPlugins(pluginMgr.getPlugins()).map(function(plugin) {
|
|
9
|
+
var name = plugin.moduleName;
|
|
10
|
+
name = name.substring(name.lastIndexOf('.') + 1);
|
|
11
|
+
plugin = extend({}, plugin);
|
|
12
|
+
plugin.name = name;
|
|
13
|
+
plugin.selected = !disabledPlugins[name];
|
|
14
|
+
return plugin;
|
|
15
|
+
});
|
|
16
|
+
res.json(list);
|
|
17
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
var pluginMgr = require('../../lib/proxy').pluginMgr;
|
|
2
|
+
var properties = require('../../../../lib/rules/util').properties;
|
|
3
|
+
var extend = require('extend');
|
|
4
|
+
|
|
5
|
+
module.exports = function(req, res) {
|
|
6
|
+
var name = req.query.name;
|
|
7
|
+
var plugin;
|
|
8
|
+
if (typeof name === 'string') {
|
|
9
|
+
name = name.trim();
|
|
10
|
+
name = name.substring(name.lastIndexOf('.') + 1);
|
|
11
|
+
plugin = pluginMgr.getPluginByName(name);
|
|
12
|
+
if (plugin) {
|
|
13
|
+
var disabledPlugins = properties.get('disabledPlugins');
|
|
14
|
+
if (disabledPlugins) {
|
|
15
|
+
plugin = extend({}, plugin);
|
|
16
|
+
plugin.selected = !disabledPlugins[name];
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
res.json({ ec: 0, plugin: plugin || undefined });
|
|
21
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
var properties = require('../../../../lib/rules/util').properties;
|
|
2
|
+
var pluginMgr = require('../../lib/proxy').pluginMgr;
|
|
3
|
+
var sortPlugins = require('../util').sortPlugins;
|
|
4
|
+
|
|
5
|
+
module.exports = function(req, res) {
|
|
6
|
+
var plugins = pluginMgr.getPlugins();
|
|
7
|
+
var disabledPlugins = properties.get('disabledPlugins') || {};
|
|
8
|
+
res.json({
|
|
9
|
+
disabled: !!properties.get('disabledAllPlugins'),
|
|
10
|
+
list: sortPlugins(plugins).map(function(plugin) {
|
|
11
|
+
name = plugin.moduleName;
|
|
12
|
+
name = name.substring(name.lastIndexOf('.') + 1);
|
|
13
|
+
return {
|
|
14
|
+
name: name,
|
|
15
|
+
moduleName: plugin.moduleName,
|
|
16
|
+
version: plugin.version,
|
|
17
|
+
selected: !disabledPlugins[name]
|
|
18
|
+
};
|
|
19
|
+
})
|
|
20
|
+
});
|
|
21
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
var rules = require('../../../../lib/rules/util').rules;
|
|
2
|
+
|
|
3
|
+
module.exports = function(req, res) {
|
|
4
|
+
var name = req.body.name;
|
|
5
|
+
var ec = 2;
|
|
6
|
+
if (name !== 'Default' && rules.exists(name)) {
|
|
7
|
+
ec = 0;
|
|
8
|
+
rules.moveToTop(name);
|
|
9
|
+
}
|
|
10
|
+
res.json({ ec: ec });
|
|
11
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
var rules = require('../../../../lib/rules/util').rules;
|
|
2
|
+
|
|
3
|
+
module.exports = function(req, res) {
|
|
4
|
+
var name = req.body.name;
|
|
5
|
+
var isDefault = name === 'Default';
|
|
6
|
+
var ec = 2;
|
|
7
|
+
if (isDefault || rules.exists(name)) {
|
|
8
|
+
ec = 0;
|
|
9
|
+
if (isDefault) {
|
|
10
|
+
rules.enableDefault();
|
|
11
|
+
} else {
|
|
12
|
+
rules.select(name);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
res.json({ec: ec});
|
|
16
|
+
};
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
var rules = require('../../../../lib/rules/util').rules;
|
|
2
2
|
|
|
3
3
|
module.exports = function(req, res) {
|
|
4
|
-
|
|
5
|
-
rules.
|
|
4
|
+
var body = req.body;
|
|
5
|
+
rules.add(body.name, body.value);
|
|
6
|
+
rules.unselect(body.name);
|
|
6
7
|
res.json({ec: 0, defaultRulesIsDisabled: rules.defaultRulesIsDisabled(), list: rules.getSelectedList()});
|
|
7
8
|
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
var rules = require('../../../../lib/rules/util').rules;
|
|
2
|
+
|
|
3
|
+
module.exports = function(req, res) {
|
|
4
|
+
var name = req.body.name;
|
|
5
|
+
var ec = 2;
|
|
6
|
+
var isDefault = name === 'Default';
|
|
7
|
+
var unselectAll = name === false;
|
|
8
|
+
if (isDefault || unselectAll || rules.exists(name)) {
|
|
9
|
+
ec = 0;
|
|
10
|
+
if (isDefault || unselectAll) {
|
|
11
|
+
rules.disableDefault();
|
|
12
|
+
}
|
|
13
|
+
if (!isDefault) {
|
|
14
|
+
rules.unselect(name);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
res.json({ec: ec});
|
|
18
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
var rules = require('../../../../lib/rules/util').rules;
|
|
2
|
+
|
|
3
|
+
module.exports = function(req, res) {
|
|
4
|
+
var name = req.query.name;
|
|
5
|
+
if (name === 'Default') {
|
|
6
|
+
return res.json({ value: {
|
|
7
|
+
value: rules.getDefault(),
|
|
8
|
+
selected: !rules.defaultRulesIsDisabled()
|
|
9
|
+
}});
|
|
10
|
+
}
|
|
11
|
+
var value = rules.get(name);
|
|
12
|
+
if (value == null) {
|
|
13
|
+
return res.json({ value: null });
|
|
14
|
+
}
|
|
15
|
+
res.json({ value: {
|
|
16
|
+
value: value,
|
|
17
|
+
selected: rules.isSelected(name)
|
|
18
|
+
}});
|
|
19
|
+
};
|
|
@@ -71,47 +71,58 @@ exports.getServerInfo = function(req) {
|
|
|
71
71
|
ipv6: [],
|
|
72
72
|
mac: req.ip + (config.storage ? '\n' + config.storage : '')
|
|
73
73
|
};
|
|
74
|
-
var
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
if (iface.internal) {
|
|
78
|
-
return;
|
|
79
|
-
}
|
|
80
|
-
info[iface.family == 'IPv4' || iface.family === 4 ? 'ipv4' : 'ipv6'].push(iface.address);
|
|
81
|
-
});
|
|
82
|
-
});
|
|
83
|
-
|
|
74
|
+
var serverInfo = util.getServerInfo();
|
|
75
|
+
info.ipv4 = serverInfo.ipv4;
|
|
76
|
+
info.ipv6 = serverInfo.ipv6;
|
|
84
77
|
return info;
|
|
85
78
|
};
|
|
86
79
|
|
|
87
80
|
var DATA_RE = /[\r\n]\s*(\{[\s\S]*\})[\r\n]/;
|
|
88
81
|
var REPLACE_RE = /[\r\n]1[\r\n]/;
|
|
82
|
+
var EXCEED_SIZE_ERR = new Error('The file size can not exceed 6MB');
|
|
83
|
+
var INVALID_CONTENT_ERR = new Error('The file content is not a JSON object');
|
|
84
|
+
|
|
89
85
|
exports.getReqData = function(req, callback) {
|
|
90
|
-
var result =
|
|
86
|
+
var result = [];
|
|
87
|
+
var len = 0;
|
|
88
|
+
var done;
|
|
89
|
+
var handleCb = function(err, data) {
|
|
90
|
+
if (!done) {
|
|
91
|
+
done = true;
|
|
92
|
+
callback(err, data);
|
|
93
|
+
result = null;
|
|
94
|
+
}
|
|
95
|
+
};
|
|
91
96
|
req.on('data', function(chunk) {
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
97
|
+
if (done) {
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
len += chunk.length;
|
|
101
|
+
result.push(chunk);
|
|
102
|
+
if (len > MAX_OBJECT_SIZE) {
|
|
103
|
+
handleCb(EXCEED_SIZE_ERR);
|
|
96
104
|
}
|
|
97
105
|
});
|
|
98
|
-
req.on('error',
|
|
106
|
+
req.on('error', handleCb);
|
|
99
107
|
req.on('end', function() {
|
|
100
|
-
|
|
108
|
+
if (done) {
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
101
111
|
var data;
|
|
112
|
+
result = Buffer.concat(result).toString();
|
|
102
113
|
result = result.replace(DATA_RE, function(all, match) {
|
|
103
114
|
data = match;
|
|
104
115
|
return '';
|
|
105
116
|
});
|
|
106
117
|
if (!data) {
|
|
107
|
-
return
|
|
118
|
+
return handleCb(INVALID_CONTENT_ERR);
|
|
108
119
|
}
|
|
109
120
|
try {
|
|
110
121
|
data = JSON.parse(data);
|
|
111
122
|
} catch(err) {
|
|
112
|
-
return
|
|
123
|
+
return handleCb(err);
|
|
113
124
|
}
|
|
114
|
-
|
|
125
|
+
handleCb(null, {
|
|
115
126
|
data: data,
|
|
116
127
|
replace: REPLACE_RE.test(result)
|
|
117
128
|
});
|
|
@@ -145,3 +156,17 @@ exports.sendError = sendError;
|
|
|
145
156
|
exports.sendGzip = util.sendGzip;
|
|
146
157
|
|
|
147
158
|
exports.sendGzipText = util.sendGzipText;
|
|
159
|
+
|
|
160
|
+
function compare(v1, v2) {
|
|
161
|
+
return v1 == v2 ? 0 : v1 > v2 ? -1 : 1;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
exports.sortPlugins = function(plugins) {
|
|
165
|
+
return Object.keys(plugins).sort(function(k1, k2) {
|
|
166
|
+
var p1 = plugins[k1];
|
|
167
|
+
var p2 = plugins[k2];
|
|
168
|
+
return compare(p1.priority, p2.priority) || compare(p2.mtime, p1.mtime) || (k1 > k2 ? 1 : (k1 == k2 ? 0 : -1));
|
|
169
|
+
}).map(function(name) {
|
|
170
|
+
return plugins[name];
|
|
171
|
+
});
|
|
172
|
+
};
|