whistle 2.9.12 → 2.9.15-beta

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.
@@ -251,7 +251,7 @@ function cgiHandler(req, res) {
251
251
  try {
252
252
  require(filepath)(req, res);
253
253
  } catch(err) {
254
- var msg = config.debugMode ? '<pre>' + util.getErrorStack(err) + '</pre>' : 'Internal Server Error';
254
+ var msg = config.debugMode ? '<pre>' + util.encodeHtml(util.getErrorStack(err)) + '</pre>' : 'Internal Server Error';
255
255
  res.status(500).send(msg);
256
256
  }
257
257
  };
@@ -263,7 +263,7 @@ function cgiHandler(req, res) {
263
263
  var notFound = err ? err.code === 'ENOENT' : !stat.isFile();
264
264
  var msg;
265
265
  if (config.debugMode) {
266
- msg = '<pre>' + (err ? util.getErrorStack(err) : 'Not File') + '</pre>';
266
+ msg = '<pre>' + (err ? util.encodeHtml(util.getErrorStack(err)) : 'Not File') + '</pre>';
267
267
  } else {
268
268
  msg = notFound ? 'Not Found' : 'Internal Server Error';
269
269
  }
@@ -326,7 +326,7 @@ app.all(PLUGIN_PATH_RE, function(req, res) {
326
326
  pluginMgr.loadPlugin(plugin, function(err, ports) {
327
327
  if (err || !ports.uiPort) {
328
328
  if (err) {
329
- res.status(500).send('<pre>' + err + '</pre>');
329
+ res.status(500).send('<pre>' + util.encodeHtml(err) + '</pre>');
330
330
  } else {
331
331
  res.status(404).send('Not Found');
332
332
  }
package/lib/config.js CHANGED
@@ -587,7 +587,10 @@ function getPluginList(list) {
587
587
  exports.extend = function (newConf) {
588
588
  config.pluginHostMap = {};
589
589
  config.uiport = config.port;
590
-
590
+ if (process.env.WHISTLE_MODE) {
591
+ newConf = newConf || {};
592
+ newConf.mode = process.env.WHISTLE_MODE + '|' + (newConf.mode || '');
593
+ }
591
594
  if (newConf) {
592
595
  config.uiMiddleware = newConf.uiMiddlewares || newConf.uiMiddleware;
593
596
  if (newConf.cmdName && CMD_RE.test(newConf.cmdName)) {
@@ -829,20 +832,14 @@ exports.extend = function (newConf) {
829
832
  process.env.PFORK_EXEC_PATH = process.execPath;
830
833
  } else if (m === 'safe' || m === 'rejectUnauthorized') {
831
834
  config.rejectUnauthorized = true;
832
- } else if (
833
- ['capture', 'intercept', 'enable-capture', 'enableCapture'].indexOf(
834
- m
835
- ) !== -1
836
- ) {
835
+ } else if (['capture', 'intercept', 'enable-capture', 'enableCapture'].indexOf(m) !== -1) {
837
836
  config.isEnableCapture = true;
838
837
  } else if (['disable-capture', 'disableCapture'].indexOf(m) !== -1) {
839
838
  config.isEnableCapture = false;
840
839
  } else if (['http2', 'enable-http2', 'enableHttp2', 'enable-h2', 'enableH2'].indexOf(m) !== -1) {
841
840
  config.isEnableHttp2 = true;
842
841
  } else if (
843
- ['disable-http2', 'disableHttp2', 'disable-h2', 'disableH2'].indexOf(
844
- m
845
- ) !== -1
842
+ ['disable-http2', 'disableHttp2', 'disable-h2', 'disableH2'].indexOf(m) !== -1
846
843
  ) {
847
844
  config.isEnableHttp2 = false;
848
845
  } else if (m === 'hideLeftBar' || m === 'hideLeftMenu') {
@@ -103,6 +103,7 @@ module.exports = function () {
103
103
  account: account,
104
104
  isSys: isSys,
105
105
  isProj: isProj,
106
+ noOpt: !!(conf.noOption || conf.notOption),
106
107
  notUn: notUn,
107
108
  moduleName: pkg.name,
108
109
  enableAuthUI: !!conf.enableAuthUI,
@@ -361,6 +361,7 @@ function readPackages(obj, callback) {
361
361
  var hintList = util.getHintList(conf);
362
362
  var simpleName = name.slice(0, -1);
363
363
  newPkg.enableAuthUI = !!conf.enableAuthUI;
364
+ newPkg.noOpt = !!(conf.noOption || conf.notOption);
364
365
  newPkg.updateUrl = util.getUpdateUrl(conf);
365
366
  newPkg.inheritAuth = !!conf.inheritAuth;
366
367
  newPkg.tunnelKey = util.getTunnelKey(conf);
@@ -698,6 +699,7 @@ function loadPlugin(plugin, callback) {
698
699
  conf.host = host || LOCALHOST;
699
700
  var moduleName = plugin.moduleName;
700
701
  var name = moduleName.substring(moduleName.indexOf('/') + 1);
702
+ var isInline = config.inspectMode || process.env.PFORK_MODE === 'inline';
701
703
  p.fork(
702
704
  {
703
705
  data: config.getPluginData(moduleName),
@@ -741,7 +743,7 @@ function loadPlugin(plugin, callback) {
741
743
  CERT_CACHE_INFO: CERT_CACHE_INFO,
742
744
  HOST_IP_HEADER: HOST_IP_HEADER,
743
745
  debugMode: debugMode,
744
- config: conf
746
+ config: isInline ? extend(true, {}, conf) : conf // 防止 inline 时,子进程删除 conf
745
747
  },
746
748
  function (err, ports, child, first) {
747
749
  callback(err, ports);
@@ -18,6 +18,7 @@ var transproto = require('../util/transproto');
18
18
  var common = require('../util/common');
19
19
  var getProxy = require('./proxy');
20
20
  var rootRequire = require('../../require');
21
+ var os = require('os');
21
22
 
22
23
  var getEncodeTransform = transproto.getEncodeTransform;
23
24
  var getDecodeTransform = transproto.getDecodeTransform;
@@ -92,6 +93,7 @@ process._handlePforkUncaughtException = function (msg, e) {
92
93
  msg = [
93
94
  'From: ' + pluginName + pluginVersion,
94
95
  'Node: ' + process.version,
96
+ 'Host: ' + os.hostname(),
95
97
  'Date: ' + new Date().toLocaleString(),
96
98
  msg
97
99
  ].join('\n');
package/lib/upgrade.js CHANGED
@@ -61,7 +61,7 @@ function getPluginNameByReq(req, callback) {
61
61
  err ? 500 : 404,
62
62
  err ? 'Internal Server Error' : 'Not Found'
63
63
  ].join(' ');
64
- err = err ? '<pre>' + err + '</pre>' : 'Not Found';
64
+ err = err ? '<pre>' + util.encodeHtml(err) + '</pre>' : 'Not Found';
65
65
  var length = Buffer.byteLength(err);
66
66
  err = [
67
67
  msg,
@@ -271,3 +271,24 @@ exports.writeLogSync = function(msg) {
271
271
  }
272
272
  }
273
273
  };
274
+
275
+ var SPEC_TAGS = {
276
+ '&': '&amp;',
277
+ '<': '&lt;',
278
+ '>': '&gt;',
279
+ '"': '&quot;',
280
+ '\'': '&#39;',
281
+ '`': '&#96;'
282
+ };
283
+ var SPEC_TAG_RE = /[&<>"'`]/g;
284
+
285
+ function transformTag(tag) {
286
+ return SPEC_TAGS[tag] || tag;
287
+ }
288
+
289
+ exports.encodeHtml = function(str) {
290
+ if (typeof str !== 'string') {
291
+ return str;
292
+ }
293
+ return str.replace(SPEC_TAG_RE, transformTag);
294
+ };
package/lib/util/index.js CHANGED
@@ -117,6 +117,7 @@ var CIPHER_OPTIONS = [
117
117
  ];
118
118
  var TLSV2_CIPHERS = 'ECDHE-ECDSA-AES256-GCM-SHA384';
119
119
  var EMPTY_BUFFER = toBuffer('');
120
+ var encodeHtml = common.encodeHtml;
120
121
  var lowerCaseify = common.lowerCaseify;
121
122
  var removeIPV6Prefix = common.removeIPV6Prefix;
122
123
  var hasBody = common.hasBody;
@@ -128,6 +129,7 @@ var pluginMgr;
128
129
 
129
130
  workerIndex = workerIndex >= 0 ? padReqId(config.workerIndex) : '';
130
131
 
132
+ exports.encodeHtml = encodeHtml;
131
133
  exports.hasProtocol = hasProtocol;
132
134
  exports.removeProtocol = removeProtocol;
133
135
  exports.setProtocol = common.setProtocol;
@@ -472,6 +474,7 @@ function getErrorStack(err) {
472
474
  var result = [
473
475
  'From: ' + config.name + '@' + config.version,
474
476
  'Node: ' + process.version,
477
+ 'Host: ' + hostname,
475
478
  'Date: ' + formatDate(),
476
479
  stack
477
480
  ];
@@ -970,7 +973,7 @@ function wrapGatewayError(body) {
970
973
  },
971
974
  body: body
972
975
  ? '<pre>\n' +
973
- body +
976
+ encodeHtml(body) +
974
977
  '\n\n\n<a href="javascript:;" onclick="location.reload()"' +
975
978
  '>Reload this page</a>\n</pre>'
976
979
  : ''
@@ -1005,7 +1008,7 @@ function parseInlineJSON(text, isValue) {
1005
1008
  data[RegExp.$1] = RegExp.$2;
1006
1009
  return data;
1007
1010
  }
1008
- return parseQuery(text, null, null, text[0] === '&');
1011
+ return parseQuery(text, null, null, true);
1009
1012
  }
1010
1013
 
1011
1014
  function replaceCrLf(char) {
@@ -1251,7 +1254,7 @@ exports.parseRuleJson = function(rules, callback, req) {
1251
1254
  ).spread(callback);
1252
1255
  };
1253
1256
 
1254
- function readRuleValue(rule, callback, checkUrl, needRawData, req) {
1257
+ function readRuleValue(rule, callback, checkUrl, needRawData, req, isJson) {
1255
1258
  if (!rule) {
1256
1259
  return callback();
1257
1260
  }
@@ -1267,6 +1270,7 @@ function readRuleValue(rule, callback, checkUrl, needRawData, req) {
1267
1270
  if (opts) {
1268
1271
  readFile = pluginMgr[needRawData ? 'requestBin' : 'requestText'];
1269
1272
  filePath = opts;
1273
+ isJson = false;
1270
1274
  } else {
1271
1275
  readFile = fileMgr[needRawData ? 'readFile' : 'readFileText'];
1272
1276
  filePath = decodePath(filePath);
@@ -1274,6 +1278,24 @@ function readRuleValue(rule, callback, checkUrl, needRawData, req) {
1274
1278
  filePath = join(rule.root, filePath);
1275
1279
  }
1276
1280
  }
1281
+ if (isJson && filePath.indexOf('=') !== -1) {
1282
+ try {
1283
+ var handleStat = function(err, stat) {
1284
+ if (err || !stat || !stat.isFile()) {
1285
+ callback(filePath);
1286
+ } else {
1287
+ readFile(filePath, callback);
1288
+ }
1289
+ };
1290
+ return fs.stat(filePath, function(err, stat) {
1291
+ if (err && err.code !== 'ENOENT') {
1292
+ return fs.stat(filePath, handleStat);
1293
+ } else {
1294
+ handleStat(err, stat);
1295
+ }
1296
+ });
1297
+ } catch (e) { }
1298
+ }
1277
1299
  readFile(filePath, callback);
1278
1300
  }
1279
1301
 
@@ -1323,7 +1345,8 @@ function readRuleList(rule, callback, isJson, charset, isHtml, req) {
1323
1345
  : callback,
1324
1346
  false,
1325
1347
  needRawData,
1326
- req
1348
+ req,
1349
+ isJson
1327
1350
  );
1328
1351
  }
1329
1352
  var result = [];
@@ -1383,7 +1406,8 @@ function readRuleList(rule, callback, isJson, charset, isHtml, req) {
1383
1406
  },
1384
1407
  checkUrl,
1385
1408
  needRawData,
1386
- req
1409
+ req,
1410
+ isJson
1387
1411
  );
1388
1412
  });
1389
1413
  }
@@ -8,7 +8,7 @@ function isUtf8(buf, i) {
8
8
  byte == 0x09 ||
9
9
  byte == 0x0a ||
10
10
  byte == 0x0d ||
11
- (0x20 <= byte && byte <= 0x7e)
11
+ (0x20 <= byte && byte <= 0x7f)
12
12
  ) {
13
13
  continue;
14
14
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "whistle",
3
3
  "description": "HTTP, HTTP2, HTTPS, Websocket debugging proxy",
4
- "version": "2.9.12",
4
+ "version": "2.9.15-beta",
5
5
  "dataDirname": ".whistle",
6
6
  "localUIHost": "local.whistlejs.com",
7
7
  "port": 8899,
@@ -40,7 +40,7 @@
40
40
  "colors": "1.1.2",
41
41
  "cookie": "^0.3.1",
42
42
  "express": "^4.17.1",
43
- "extend": "^3.0.1",
43
+ "extend": "^3.0.2",
44
44
  "fs-extra2": "^1.0.0",
45
45
  "hagent": "^0.9.0",
46
46
  "hparser": "^0.4.0",