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.
Files changed (56) hide show
  1. package/assets/menu.html +2 -2
  2. package/assets/modal.html +2 -2
  3. package/assets/tab.html +2 -2
  4. package/bin/api.js +545 -0
  5. package/bin/import.js +3 -3
  6. package/bin/plugin.js +4 -8
  7. package/bin/use.js +22 -8
  8. package/bin/util.js +12 -7
  9. package/bin/whistle.js +11 -1
  10. package/biz/webui/cgi-bin/abort.js +14 -5
  11. package/biz/webui/cgi-bin/frames.js +12 -0
  12. package/biz/webui/cgi-bin/get-session.js +7 -3
  13. package/biz/webui/cgi-bin/is-enabled-https.js +6 -0
  14. package/biz/webui/cgi-bin/plugins/disable-plugin.js +16 -7
  15. package/biz/webui/cgi-bin/plugins/list.js +17 -0
  16. package/biz/webui/cgi-bin/plugins/plugin.js +21 -0
  17. package/biz/webui/cgi-bin/plugins/status.js +21 -0
  18. package/biz/webui/cgi-bin/rules/is-multi-select.js +7 -0
  19. package/biz/webui/cgi-bin/rules/move-top.js +11 -0
  20. package/biz/webui/cgi-bin/rules/select.js +1 -1
  21. package/biz/webui/cgi-bin/rules/select2.js +16 -0
  22. package/biz/webui/cgi-bin/rules/status.js +6 -0
  23. package/biz/webui/cgi-bin/rules/unselect.js +3 -2
  24. package/biz/webui/cgi-bin/rules/unselect2.js +18 -0
  25. package/biz/webui/cgi-bin/rules/value.js +19 -0
  26. package/biz/webui/cgi-bin/sessions.js +6 -0
  27. package/biz/webui/cgi-bin/util.js +45 -20
  28. package/biz/webui/htdocs/index.html +1 -1
  29. package/biz/webui/htdocs/js/index.js +51 -51
  30. package/biz/webui/lib/index.js +1 -3
  31. package/lib/https/index.js +7 -5
  32. package/lib/init.js +1 -0
  33. package/lib/inspectors/data.js +39 -34
  34. package/lib/inspectors/req.js +9 -6
  35. package/lib/inspectors/res.js +10 -14
  36. package/lib/plugins/index.js +2 -2
  37. package/lib/plugins/load-plugin.js +19 -8
  38. package/lib/rules/util.js +20 -10
  39. package/lib/service/composer.js +7 -22
  40. package/lib/service/data-center.js +0 -12
  41. package/lib/service/generate-saz.js +2 -2
  42. package/lib/service/service.js +8 -7
  43. package/lib/service/util.js +6 -16
  44. package/lib/socket-mgr.js +23 -17
  45. package/lib/tunnel.js +7 -17
  46. package/lib/upgrade.js +4 -8
  47. package/lib/util/common.js +78 -11
  48. package/lib/util/data-server.js +273 -0
  49. package/lib/util/file-mgr.js +7 -4
  50. package/lib/util/http-mgr.js +17 -9
  51. package/lib/util/index.js +67 -54
  52. package/lib/util/parse-url.js +11 -9
  53. package/lib/util/patch.js +2 -6
  54. package/lib/util/speed-transform.js +17 -6
  55. package/lib/util/whistle-transform.js +18 -7
  56. 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 getReqOptions(options) {
78
- var reqOptions = url.parse('http://' + getHost(options) + '/cgi-bin/rules/project');
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 ' + new Buffer.from(auth).toString('base64');
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
- var resBody;
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 = resBody ? Buffer.concat([resBody, data]) : data;
194
+ resBody.push(data);
191
195
  });
192
196
  res.on('end', function() {
193
- if (res.statusCode != 200) {
194
- callback('Bad response (' + res.statusCode + ')');
195
- } else {
196
- callback(null, JSON.parse(resBody + ''));
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 === 'status') {
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
- function abort(reqId) {
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(',').forEach(abort);
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
- reqList.concat(resList).forEach(function(id) {
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 && reqList.indexOf(id) !== -1) || item.endTime) {
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
  };
@@ -0,0 +1,6 @@
1
+ var properties = require('../../../lib/rules/util').properties;
2
+
3
+ module.exports = function(req, res) {
4
+ res.json({ec: 0, enabled: properties.isEnableCapture()});
5
+ };
6
+
@@ -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
- if (req.body.disabled == 1) {
7
- disabledPlugins[req.body.name] = 1;
8
- } else {
9
- delete disabledPlugins[req.body.name];
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
- properties.set('disabledPlugins', disabledPlugins);
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,7 @@
1
+ var properties = require('../../../../lib/rules/util').properties;
2
+
3
+ module.exports = function(req, res) {
4
+ res.json({multiSelect: !!properties.get('allowMultipleChoice')});
5
+ };
6
+
7
+
@@ -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
+ };
@@ -11,6 +11,6 @@ module.exports = function(req, res) {
11
11
  changed = true;
12
12
  }
13
13
  }
14
- rules.select(req.body.name);
14
+ rules.select(body.name);
15
15
  res.json({ec: 0, defaultRulesIsDisabled: rules.defaultRulesIsDisabled(), list: rules.getSelectedList(), changed: changed});
16
16
  };
@@ -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
+ };
@@ -0,0 +1,6 @@
1
+ var getConfig = require('../../../../lib/rules/util').rules.getConfig;
2
+ var util = require('../util');
3
+
4
+ module.exports = function(req, res) {
5
+ util.sendGzip(req, res, getConfig());
6
+ };
@@ -1,7 +1,8 @@
1
1
  var rules = require('../../../../lib/rules/util').rules;
2
2
 
3
3
  module.exports = function(req, res) {
4
- rules.add(req.body.name, req.body.value);
5
- rules.unselect(req.body.name);
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
+ };
@@ -0,0 +1,6 @@
1
+ var util = require('./util');
2
+ var proxy = require('../lib/proxy');
3
+
4
+ module.exports = function(req, res) {
5
+ util.sendGzip(req, res, proxy.getSessionsForApi(req.body));
6
+ };
@@ -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 ifaces = util.networkInterfaces();
75
- Object.keys(ifaces).forEach(function(ifname) {
76
- ifaces[ifname].forEach(function (iface) {
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
- result = result ? Buffer.concat([result, chunk]) : chunk;
93
- if (result.length > MAX_OBJECT_SIZE) {
94
- req.removeAllListeners('data');
95
- callback(new Error('The file size can not exceed 6MB'));
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', callback);
106
+ req.on('error', handleCb);
99
107
  req.on('end', function() {
100
- result += '';
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 callback(new Error('The file content is not a JSON object'));
118
+ return handleCb(INVALID_CONTENT_ERR);
108
119
  }
109
120
  try {
110
121
  data = JSON.parse(data);
111
122
  } catch(err) {
112
- return callback(err);
123
+ return handleCb(err);
113
124
  }
114
- callback(null, {
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
+ };
@@ -8,6 +8,6 @@
8
8
  </head>
9
9
  <body>
10
10
  <div id="container" class="main"></div>
11
- <script src="js/index.js?v=2.10.5"></script>
11
+ <script src="js/index.js?v=2.10.7"></script>
12
12
  </body>
13
13
  </html>