whistle 2.10.1 → 2.10.3
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/js/log.js +44 -27
- package/assets/menu.html +2 -0
- package/assets/modal.html +2 -0
- package/assets/tab.html +3 -3
- package/bin/use.js +236 -101
- package/bin/util.js +10 -7
- package/bin/whistle.js +5 -5
- package/biz/webui/cgi-bin/download.js +1 -1
- package/biz/webui/cgi-bin/get-data.js +0 -5
- package/biz/webui/cgi-bin/init.js +0 -2
- package/biz/webui/cgi-bin/rules/clear-dns-cache.js +7 -0
- package/biz/webui/htdocs/index.html +2 -2
- package/biz/webui/htdocs/js/index.js +53 -50
- package/biz/webui/lib/index.js +49 -4
- package/lib/config.js +6 -4
- package/lib/handlers/file-proxy.js +1 -1
- package/lib/https/ca.js +39 -9
- package/lib/https/index.js +109 -114
- package/lib/index.js +1 -5
- package/lib/inspectors/data.js +119 -13
- package/lib/inspectors/log.js +4 -0
- package/lib/inspectors/req.js +5 -3
- package/lib/inspectors/weinre.js +7 -2
- package/lib/plugins/get-plugins-sync.js +15 -11
- package/lib/plugins/get-plugins.js +11 -12
- package/lib/plugins/load-plugin.js +1 -1
- package/lib/plugins/module-paths.js +4 -0
- package/lib/plugins/util.js +8 -0
- package/lib/rules/dns.js +4 -0
- package/lib/rules/index.js +0 -1
- package/lib/rules/protocols.js +3 -9
- package/lib/rules/rules.js +21 -22
- package/lib/service/composer.js +10 -5
- package/lib/{util/log-server.js → service/console-log.js} +37 -34
- package/lib/service/index.js +2 -4
- package/lib/service/service.js +64 -15
- package/lib/service/util.js +3 -42
- package/lib/socket-mgr.js +2 -16
- package/lib/tunnel.js +2 -4
- package/lib/upgrade.js +1 -1
- package/lib/util/common.js +115 -17
- package/lib/util/index.js +48 -40
- package/package.json +2 -2
- package/biz/webui/cgi-bin/import-remote.js +0 -37
- package/biz/webui/cgi-bin/log/set.js +0 -7
- package/lib/util/parse-query.js +0 -35
package/lib/util/index.js
CHANGED
|
@@ -15,20 +15,21 @@ var dns = require('dns');
|
|
|
15
15
|
var mime = require('mime');
|
|
16
16
|
var PipeStream = require('pipestream');
|
|
17
17
|
var protoMgr = require('../rules/protocols');
|
|
18
|
-
var protocols = protoMgr.protocols;
|
|
19
18
|
var logger = require('./logger');
|
|
20
19
|
var config = require('../config');
|
|
21
20
|
var isUtf8 = require('./is-utf8');
|
|
22
21
|
var fileMgr = require('./file-mgr');
|
|
23
22
|
var httpMgr = require('./http-mgr');
|
|
24
23
|
var ReplacePatternTransform = require('./replace-pattern-transform');
|
|
25
|
-
var parseQuery = require('./parse-query');
|
|
26
24
|
var common = require('./common');
|
|
27
25
|
var proc = require('./process');
|
|
28
26
|
var parseUrl = require('./parse-url');
|
|
29
27
|
var h2Consts = config.enableH2 ? require('http2').constants : {};
|
|
30
28
|
|
|
29
|
+
var protocols = protoMgr.protocols;
|
|
30
|
+
var resProtocols = protoMgr.resProtocols;
|
|
31
31
|
var uid = config.uid;
|
|
32
|
+
var parseQuery = common.parseQuery;
|
|
32
33
|
var supportsBr = common.supportsBr;
|
|
33
34
|
var isLocalIp = common.isLocalIp;
|
|
34
35
|
var getStat = common.getStat;
|
|
@@ -1163,7 +1164,7 @@ function getTempFilePath(filePath, rule) {
|
|
|
1163
1164
|
var root = rule.root;
|
|
1164
1165
|
if (!root && common.TEMP_PATH_RE.test(filePath)) {
|
|
1165
1166
|
rule._suffix = RegExp.$2;
|
|
1166
|
-
return path.join(
|
|
1167
|
+
return path.join(common.TEMP_FILES_PATH, RegExp.$1);
|
|
1167
1168
|
}
|
|
1168
1169
|
return joinPath(root, decodePath(filePath));
|
|
1169
1170
|
}
|
|
@@ -1855,23 +1856,21 @@ function joinPath(root, dir) {
|
|
|
1855
1856
|
|
|
1856
1857
|
exports.joinPath = joinPath;
|
|
1857
1858
|
|
|
1858
|
-
function
|
|
1859
|
+
function parseRuleProps(list, result) {
|
|
1859
1860
|
result = result || {};
|
|
1860
1861
|
if (list) {
|
|
1861
|
-
list
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
.split(SEP_RE)
|
|
1865
|
-
.forEach(function (action) {
|
|
1866
|
-
if (action) {
|
|
1862
|
+
list.forEach(function(rule) {
|
|
1863
|
+
if (rule = getMatcherValue(rule)) {
|
|
1864
|
+
common.parseProps(rule).forEach(function (action) {
|
|
1867
1865
|
result[action] = true;
|
|
1868
|
-
}
|
|
1869
|
-
}
|
|
1866
|
+
});
|
|
1867
|
+
}
|
|
1868
|
+
});
|
|
1870
1869
|
}
|
|
1871
1870
|
return result;
|
|
1872
1871
|
}
|
|
1873
1872
|
|
|
1874
|
-
exports.
|
|
1873
|
+
exports.parseRuleProps = parseRuleProps;
|
|
1875
1874
|
|
|
1876
1875
|
exports.parseLineProps = function (str) {
|
|
1877
1876
|
str = str && removeProtocol(str, true);
|
|
@@ -1998,17 +1997,7 @@ exports.checkSkip = function(skip, rule, curUrl) {
|
|
|
1998
1997
|
};
|
|
1999
1998
|
|
|
2000
1999
|
function resolveRuleProps(rule, result) {
|
|
2001
|
-
|
|
2002
|
-
if (rule) {
|
|
2003
|
-
rule.list.forEach(function (rule) {
|
|
2004
|
-
getMatcherValue(rule)
|
|
2005
|
-
.split(SEP_RE)
|
|
2006
|
-
.forEach(function (action) {
|
|
2007
|
-
result[action] = true;
|
|
2008
|
-
});
|
|
2009
|
-
});
|
|
2010
|
-
}
|
|
2011
|
-
return result;
|
|
2000
|
+
return parseRuleProps(rule && rule.list, result);
|
|
2012
2001
|
}
|
|
2013
2002
|
|
|
2014
2003
|
var PLUGIN_RE = /^(?:plugin|whistle)\.[a-z\d_\-]+$/;
|
|
@@ -2089,7 +2078,7 @@ function ignoreRules(rules, ignore, isResRules) {
|
|
|
2089
2078
|
if (name === 'filter' || name === 'ignore' || exclude[name]) {
|
|
2090
2079
|
return;
|
|
2091
2080
|
}
|
|
2092
|
-
if (!isResRules ||
|
|
2081
|
+
if (!isResRules || resProtocols.indexOf(name) !== -1) {
|
|
2093
2082
|
if (
|
|
2094
2083
|
ignorePlugins(rules, name, exclude) ||
|
|
2095
2084
|
ignoreProxy(rules, name, exclude) ||
|
|
@@ -2191,7 +2180,7 @@ function mergeRules(req, add, isResRules) {
|
|
|
2191
2180
|
};
|
|
2192
2181
|
if (origAdd) {
|
|
2193
2182
|
if (isResRules) {
|
|
2194
|
-
|
|
2183
|
+
resProtocols.forEach(merge);
|
|
2195
2184
|
} else {
|
|
2196
2185
|
Object.keys(origAdd).forEach(merge);
|
|
2197
2186
|
}
|
|
@@ -2680,12 +2669,12 @@ var REQ_HEADER_RE = /^req\.?H(?:eaders?)?\.(.+)$/i;
|
|
|
2680
2669
|
var RES_HEADER_RE = /^res\.?H(?:eaders?)?\.(.+)$/i;
|
|
2681
2670
|
var TRAILER_RE = /trailer\.(.+)$/;
|
|
2682
2671
|
var HEADER_RE = /^headers\.(.+)$/;
|
|
2683
|
-
var REQ_COOKIE_RE = /^req\.?C(?:ookies?)?\.(
|
|
2684
|
-
var RES_COOKIE_RE = /^res\.?C(?:ookies?)?\.(
|
|
2685
|
-
var REQ_BODY_RE = /^req\.?B(?:ody?)?\.(
|
|
2686
|
-
var RES_BODY_RE = /^res\.?B(?:ody?)?\.(
|
|
2687
|
-
var COOKIE_RE = /^cookies?\.(
|
|
2688
|
-
var QUERY_RE = /^(?:query|params|url\.?Params?)\.(
|
|
2672
|
+
var REQ_COOKIE_RE = /^req\.?C(?:ookies?)?\.([\s\S]+)$/i;
|
|
2673
|
+
var RES_COOKIE_RE = /^res\.?C(?:ookies?)?\.([\s\S]+)$/i;
|
|
2674
|
+
var REQ_BODY_RE = /^req\.?B(?:ody?)?\.([\s\S]+)$/i;
|
|
2675
|
+
var RES_BODY_RE = /^res\.?B(?:ody?)?\.([\s\S]+)$/i;
|
|
2676
|
+
var COOKIE_RE = /^cookies?\.([\s\S]+)$/i;
|
|
2677
|
+
var QUERY_RE = /^(?:query|params|url\.?Params?)\.([\s\S]+)$/i;
|
|
2689
2678
|
var QUERY_STRING_RE = /^(?:query|params|url\.?Params?)$/i;
|
|
2690
2679
|
var PATH_INDEX_RE = /^pathname(?:\.?(-?\d+|first|last))?$/i;
|
|
2691
2680
|
|
|
@@ -2766,12 +2755,11 @@ exports.parseDelResBody = function(req) {
|
|
|
2766
2755
|
|
|
2767
2756
|
exports.deleteProps = function(obj, keys) {
|
|
2768
2757
|
keys = obj && keys && Object.keys(keys);
|
|
2769
|
-
if (
|
|
2770
|
-
|
|
2758
|
+
if (keys && keys.length) {
|
|
2759
|
+
keys.forEach(function(key) {
|
|
2760
|
+
common.deleteProps(obj, key);
|
|
2761
|
+
});
|
|
2771
2762
|
}
|
|
2772
|
-
keys.forEach(function(key) {
|
|
2773
|
-
common.deleteProps(obj, key);
|
|
2774
|
-
});
|
|
2775
2763
|
};
|
|
2776
2764
|
|
|
2777
2765
|
function getDomain(req) {
|
|
@@ -3114,10 +3102,10 @@ function getCookieItem(name, cookie) {
|
|
|
3114
3102
|
if (!cookie || typeof cookie != 'object') {
|
|
3115
3103
|
return name + '=' + (cookie == null ? '' : cookie);
|
|
3116
3104
|
}
|
|
3117
|
-
var attrs = [name + '=' + escapeValue(cookie.value)];
|
|
3105
|
+
var attrs = [name + '=' + escapeValue(cookie.value || cookie.Value)];
|
|
3118
3106
|
var maxAge = cookie.maxAge || cookie.maxage ||
|
|
3119
3107
|
cookie.MaxAge || cookie['Max-Age'] || cookie['max-age'];
|
|
3120
|
-
maxAge = parseInt(
|
|
3108
|
+
maxAge = parseInt(maxAge, 10);
|
|
3121
3109
|
if (!Number.isNaN(maxAge)) {
|
|
3122
3110
|
attrs.push('Expires=' + new Date(Date.now() + maxAge * 1000).toGMTString());
|
|
3123
3111
|
attrs.push('Max-Age=' + (maxAge === EXPIRED_SEC ? 0 : maxAge));
|
|
@@ -3650,7 +3638,8 @@ function formatAuth(obj) {
|
|
|
3650
3638
|
var password = obj.password;
|
|
3651
3639
|
return {
|
|
3652
3640
|
username: username == null ? null : String(username),
|
|
3653
|
-
password: password == null ? null : String(password)
|
|
3641
|
+
password: password == null ? null : String(password),
|
|
3642
|
+
proxy: !!obj.proxy
|
|
3654
3643
|
};
|
|
3655
3644
|
}
|
|
3656
3645
|
|
|
@@ -4009,3 +3998,22 @@ exports.isHide = function(req) {
|
|
|
4009
3998
|
var d = req.disable || '';
|
|
4010
3999
|
return req.fromComposer ? checkHideProp(e, d, 'Composer') : checkHideProp(e, d, '', req._filters && req._filters.hide);
|
|
4011
4000
|
};
|
|
4001
|
+
|
|
4002
|
+
|
|
4003
|
+
var frameIndex = 0;
|
|
4004
|
+
|
|
4005
|
+
exports.MAX_FRAME_PAYLOAD = 1024 * 1024;
|
|
4006
|
+
|
|
4007
|
+
exports.getFrameId = function() {
|
|
4008
|
+
++frameIndex;
|
|
4009
|
+
if (frameIndex > 999) {
|
|
4010
|
+
frameIndex = 0;
|
|
4011
|
+
}
|
|
4012
|
+
if (frameIndex > 99) {
|
|
4013
|
+
return Date.now() + '-' + frameIndex;
|
|
4014
|
+
}
|
|
4015
|
+
if (frameIndex > 9) {
|
|
4016
|
+
return Date.now() + '-0' + frameIndex;
|
|
4017
|
+
}
|
|
4018
|
+
return Date.now() + '-00' + frameIndex;
|
|
4019
|
+
};
|
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.10.
|
|
4
|
+
"version": "2.10.3",
|
|
5
5
|
"dataDirname": ".whistle",
|
|
6
6
|
"localUIHost": "local.whistlejs.com",
|
|
7
7
|
"port": 8899,
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
"parseurl": "^1.3.1",
|
|
54
54
|
"pfork": "^0.6.3",
|
|
55
55
|
"pipestream": "^0.7.5",
|
|
56
|
-
"set-global-proxy": "^0.
|
|
56
|
+
"set-global-proxy": "^0.4.0",
|
|
57
57
|
"sni": "1.0.0",
|
|
58
58
|
"sockx": "^0.2.3",
|
|
59
59
|
"starting": "^8.0.3",
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
var util = require('../../../lib/util');
|
|
2
|
-
var loadService = require('../lib/proxy').loadService;
|
|
3
|
-
|
|
4
|
-
var MAX_LEN = 1024 * 1024 * 6;
|
|
5
|
-
var HTTP_RE = /https?:\/\/\S/i;
|
|
6
|
-
|
|
7
|
-
module.exports = function(req, res) {
|
|
8
|
-
var url = req.query.url;
|
|
9
|
-
if (HTTP_RE.test(url)) {
|
|
10
|
-
util.request({
|
|
11
|
-
url: url,
|
|
12
|
-
maxLength: MAX_LEN
|
|
13
|
-
}, function(err, body, r) {
|
|
14
|
-
if (err) {
|
|
15
|
-
var msg = err.code === 'EEXCEED' ? 'The size of response body exceeds 6MB' : err.message;
|
|
16
|
-
return res.json({ec: 2, em: msg});
|
|
17
|
-
}
|
|
18
|
-
var status = r.statusCode;
|
|
19
|
-
if (status !== 200) {
|
|
20
|
-
var em = status > 200 && status < 400 ? 'No data' : 'Request failed';
|
|
21
|
-
return res.json({ec: 2, em: em + ' (statusCode: ' + status + ')'});
|
|
22
|
-
}
|
|
23
|
-
return res.json({ec: 0, body: body});
|
|
24
|
-
});
|
|
25
|
-
} else if (util.isString(url)) {
|
|
26
|
-
loadService(function(err, options) {
|
|
27
|
-
if (err) {
|
|
28
|
-
util.sendRes(res, 500, err.stack || err);
|
|
29
|
-
} else {
|
|
30
|
-
req.url = '/cgi-bin/temp/get?filename=' + encodeURIComponent(url);
|
|
31
|
-
util.transformReq(req, res, options.port);
|
|
32
|
-
}
|
|
33
|
-
});
|
|
34
|
-
} else {
|
|
35
|
-
res.json({ec: 400, em: 'Bad url'});
|
|
36
|
-
}
|
|
37
|
-
};
|
package/lib/util/parse-query.js
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
var qs = require('querystring');
|
|
2
|
-
|
|
3
|
-
var TOKEN_RE = /\r\u0000\n\u0003\r/g;
|
|
4
|
-
var PLUS_RE = /\+/g;
|
|
5
|
-
var TOKEN = '\r\u0000\n\u0003\r';
|
|
6
|
-
|
|
7
|
-
var decoder = {
|
|
8
|
-
decodeURIComponent: function (s) {
|
|
9
|
-
s = s.replace(TOKEN_RE, '+');
|
|
10
|
-
return qs.unescape(s);
|
|
11
|
-
}
|
|
12
|
-
};
|
|
13
|
-
var rawDecoder = {
|
|
14
|
-
decodeURIComponent: function (s) {
|
|
15
|
-
return s.replace(TOKEN_RE, '+');
|
|
16
|
-
}
|
|
17
|
-
};
|
|
18
|
-
var rawDecoder2 = {
|
|
19
|
-
decodeURIComponent: function (s) {
|
|
20
|
-
return s;
|
|
21
|
-
}
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
function parse(str, sep, eq, escape) {
|
|
25
|
-
try {
|
|
26
|
-
if (str.indexOf('+') === -1 || str.indexOf(TOKEN) !== -1) {
|
|
27
|
-
return qs.parse(str, sep, eq, escape ? rawDecoder2 : undefined);
|
|
28
|
-
}
|
|
29
|
-
str = str.replace(PLUS_RE, TOKEN);
|
|
30
|
-
return qs.parse(str, sep, eq, escape ? rawDecoder : decoder);
|
|
31
|
-
} catch (e) {}
|
|
32
|
-
return '';
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
module.exports = parse;
|