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.
- package/README.md +2 -0
- package/bin/ca/cli.js +95 -0
- package/bin/ca/index.d.ts +1 -0
- package/bin/ca/index.js +43 -0
- package/bin/proxy/cli.js +76 -0
- package/bin/proxy/index.d.ts +9 -0
- package/bin/proxy/index.js +49 -0
- package/bin/proxy/mac/Whistle +0 -0
- package/bin/proxy/mac/index.js +61 -0
- package/bin/proxy/win/index.js +32 -0
- package/bin/proxy/win/refresh.exe +0 -0
- package/bin/status.js +6 -6
- package/bin/use.js +2 -2
- package/bin/util.js +19 -2
- package/bin/whistle.js +32 -8
- package/biz/index.js +1 -1
- package/biz/webui/cgi-bin/util.js +1 -1
- package/biz/webui/htdocs/index.html +1 -1
- package/biz/webui/htdocs/js/index.js +43 -43
- package/biz/webui/lib/index.js +3 -3
- package/lib/config.js +6 -9
- package/lib/plugins/get-plugins-sync.js +1 -0
- package/lib/plugins/index.js +3 -1
- package/lib/plugins/load-plugin.js +2 -0
- package/lib/upgrade.js +1 -1
- package/lib/util/common.js +21 -0
- package/lib/util/index.js +29 -5
- package/lib/util/is-utf8.js +1 -1
- package/package.json +2 -2
package/biz/webui/lib/index.js
CHANGED
|
@@ -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') {
|
package/lib/plugins/index.js
CHANGED
|
@@ -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,
|
package/lib/util/common.js
CHANGED
|
@@ -271,3 +271,24 @@ exports.writeLogSync = function(msg) {
|
|
|
271
271
|
}
|
|
272
272
|
}
|
|
273
273
|
};
|
|
274
|
+
|
|
275
|
+
var SPEC_TAGS = {
|
|
276
|
+
'&': '&',
|
|
277
|
+
'<': '<',
|
|
278
|
+
'>': '>',
|
|
279
|
+
'"': '"',
|
|
280
|
+
'\'': ''',
|
|
281
|
+
'`': '`'
|
|
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,
|
|
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
|
}
|
package/lib/util/is-utf8.js
CHANGED
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.
|
|
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.
|
|
43
|
+
"extend": "^3.0.2",
|
|
44
44
|
"fs-extra2": "^1.0.0",
|
|
45
45
|
"hagent": "^0.9.0",
|
|
46
46
|
"hparser": "^0.4.0",
|