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/inspectors/data.js
CHANGED
|
@@ -10,7 +10,9 @@ var MAX_REQ_BODY_SIZE = (config.strict ? 256 : 2048) * 1024;
|
|
|
10
10
|
var MAX_RES_BODY_SIZE = (config.strict ? 256 : 2048) * 1024;
|
|
11
11
|
var BIG_DATA_SIZE = 1024 * 1024 * 16;
|
|
12
12
|
var LOCALHOST = '127.0.0.1';
|
|
13
|
-
var
|
|
13
|
+
var MAX_PAYLOAD = util.MAX_FRAME_PAYLOAD;
|
|
14
|
+
var SSE_SEP = Buffer.from('\n\n');
|
|
15
|
+
var FRAME_SEP_KEY = 'x-whistle-custom-frame-separator';
|
|
14
16
|
|
|
15
17
|
function getZipType(options) {
|
|
16
18
|
return options.headers && options.headers['content-encoding'];
|
|
@@ -57,6 +59,80 @@ function emitDataEvents(req, res, proxy) {
|
|
|
57
59
|
if (!util.showPluginReq(req) || util.isHide(req)) {
|
|
58
60
|
return;
|
|
59
61
|
}
|
|
62
|
+
|
|
63
|
+
var reqSepInfo = parseFrameSep(req.headers);
|
|
64
|
+
var cseSep = reqSepInfo && reqSepInfo.sep;
|
|
65
|
+
var resSepInfo;
|
|
66
|
+
|
|
67
|
+
function emitFrame(chunk, fromServer) {
|
|
68
|
+
proxy.emit('frame', {
|
|
69
|
+
reqId: req.reqId,
|
|
70
|
+
frameId: util.getFrameId(),
|
|
71
|
+
isClient: !fromServer,
|
|
72
|
+
length: chunk.length,
|
|
73
|
+
bin: chunk
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function parseFrameSep(headers) {
|
|
78
|
+
var sep = headers[FRAME_SEP_KEY];
|
|
79
|
+
if (!util.isString(sep)) {
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
var result = {};
|
|
83
|
+
delete headers[FRAME_SEP_KEY];
|
|
84
|
+
try {
|
|
85
|
+
sep = decodeURIComponent(sep);
|
|
86
|
+
} catch (e) {}
|
|
87
|
+
if (sep[0] === '/') {
|
|
88
|
+
result.keepSep = true;
|
|
89
|
+
sep = sep.slice(1);
|
|
90
|
+
}
|
|
91
|
+
if (sep) {
|
|
92
|
+
result.sep = Buffer.from(sep);
|
|
93
|
+
result.sepLen = sep.length;
|
|
94
|
+
}
|
|
95
|
+
return result;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function parseFrame(buf, isRes, end) {
|
|
99
|
+
var len = buf && buf.length;
|
|
100
|
+
if (!len) {
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
var sep, sepLen, keepSep;
|
|
104
|
+
var info = isRes ? resSepInfo : reqSepInfo;
|
|
105
|
+
if (info) {
|
|
106
|
+
sep = info.sep;
|
|
107
|
+
sepLen = info.sepLen;
|
|
108
|
+
keepSep = info.keepSep;
|
|
109
|
+
} else {
|
|
110
|
+
sep = SSE_SEP;
|
|
111
|
+
sepLen = 2;
|
|
112
|
+
}
|
|
113
|
+
var index = buf.indexOf(sep);
|
|
114
|
+
while (index !== -1) {
|
|
115
|
+
if (keepSep) {
|
|
116
|
+
index += sepLen;
|
|
117
|
+
}
|
|
118
|
+
index && emitFrame(buf.slice(0, index), isRes);
|
|
119
|
+
buf = buf.slice(keepSep ? index : index + sepLen);
|
|
120
|
+
index = buf.indexOf(sep);
|
|
121
|
+
}
|
|
122
|
+
len = buf.length;
|
|
123
|
+
if (!len) {
|
|
124
|
+
return null;
|
|
125
|
+
}
|
|
126
|
+
if (end) {
|
|
127
|
+
emitFrame(buf, isRes);
|
|
128
|
+
return null;
|
|
129
|
+
}
|
|
130
|
+
if (len > MAX_PAYLOAD) {
|
|
131
|
+
emitFrame(buf.slice(0, -1), isRes);
|
|
132
|
+
buf = buf.slice(-1);
|
|
133
|
+
}
|
|
134
|
+
return buf;
|
|
135
|
+
}
|
|
60
136
|
var getTTFB = function () {
|
|
61
137
|
if (req._ttfb >= now) {
|
|
62
138
|
return req._ttfb - now;
|
|
@@ -167,12 +243,20 @@ function emitDataEvents(req, res, proxy) {
|
|
|
167
243
|
var captureReqStream;
|
|
168
244
|
var maxReqSize;
|
|
169
245
|
var reqInfo;
|
|
246
|
+
var setReqBody = function (body, end) {
|
|
247
|
+
if (captureReqStream && cseSep) {
|
|
248
|
+
reqBody = parseFrame(reqBody, false, end);
|
|
249
|
+
} else {
|
|
250
|
+
reqData.body = reqBody;
|
|
251
|
+
}
|
|
252
|
+
};
|
|
170
253
|
var updateReqInfo = function() {
|
|
171
254
|
if (reqInfo && !captureReqStream) {
|
|
172
255
|
captureReqStream = !disable.captureStream && (resDone || enable.captureStream) && !getZipType(reqInfo);
|
|
173
256
|
maxReqSize = useBigData ? BIG_DATA_SIZE : (captureReqStream ? MAX_REQ_BODY_SIZE : MAX_SIZE);
|
|
174
|
-
if (captureReqStream
|
|
175
|
-
|
|
257
|
+
if (captureReqStream) {
|
|
258
|
+
data.isCse = !!cseSep;
|
|
259
|
+
reqBody && !reqData.body && setReqBody(reqBody);
|
|
176
260
|
}
|
|
177
261
|
}
|
|
178
262
|
};
|
|
@@ -198,7 +282,7 @@ function emitDataEvents(req, res, proxy) {
|
|
|
198
282
|
} else {
|
|
199
283
|
reqBody = reqBody ? Buffer.concat([reqBody, chunk]) : chunk;
|
|
200
284
|
if (captureReqStream) {
|
|
201
|
-
|
|
285
|
+
setReqBody(reqBody);
|
|
202
286
|
}
|
|
203
287
|
if (reqBody.length > maxReqSize) {
|
|
204
288
|
reqBody = false;
|
|
@@ -225,8 +309,8 @@ function emitDataEvents(req, res, proxy) {
|
|
|
225
309
|
data.endTime = endTime;
|
|
226
310
|
}
|
|
227
311
|
reqBody = err ? util.getErrorStack(err) : body;
|
|
228
|
-
|
|
229
|
-
setUnzipSize(body, reqData);
|
|
312
|
+
setReqBody(reqBody, true);
|
|
313
|
+
!data.isCse && setUnzipSize(body, reqData);
|
|
230
314
|
checkBodySize(reqData, useBigData);
|
|
231
315
|
});
|
|
232
316
|
updateEvent && proxy.emit(updateEvent, req.fullUrl, false, true);
|
|
@@ -239,9 +323,22 @@ function emitDataEvents(req, res, proxy) {
|
|
|
239
323
|
}
|
|
240
324
|
resDone = true;
|
|
241
325
|
info = info || (res._needGunzip ? { statusCode: res.statusCode, headers: '' } : res);
|
|
242
|
-
var
|
|
243
|
-
|
|
326
|
+
var isSse;
|
|
327
|
+
var captureStream;
|
|
328
|
+
if (!disable.captureStream && !getZipType(info)) {
|
|
329
|
+
var headers = info.headers;
|
|
330
|
+
captureStream = requestTime == null || enable.captureStream;
|
|
331
|
+
if (headers) {
|
|
332
|
+
isSse = headers['content-type'] === 'text/event-stream';
|
|
333
|
+
captureStream = captureStream || isSse;
|
|
334
|
+
resSepInfo = parseFrameSep(headers);
|
|
335
|
+
if (resSepInfo && resSepInfo.sep) {
|
|
336
|
+
isSse = captureStream;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
}
|
|
244
340
|
var maxResSize = useBigData ? BIG_DATA_SIZE : (captureStream ? MAX_RES_BODY_SIZE : MAX_SIZE);
|
|
341
|
+
data.isSse = isSse;
|
|
245
342
|
captureStream && updateReqInfo();
|
|
246
343
|
if (!cleared && util.hasBody(info, req) && checkType(info)) {
|
|
247
344
|
if (info.headers['content-length'] > maxResSize && !captureStream) {
|
|
@@ -261,9 +358,13 @@ function emitDataEvents(req, res, proxy) {
|
|
|
261
358
|
} else {
|
|
262
359
|
resBody = resBody ? Buffer.concat([resBody, chunk]) : chunk;
|
|
263
360
|
if (captureStream) {
|
|
264
|
-
|
|
361
|
+
if (isSse) {
|
|
362
|
+
resBody = parseFrame(resBody, true);
|
|
363
|
+
} else {
|
|
364
|
+
resData.body = resBody;
|
|
365
|
+
}
|
|
265
366
|
}
|
|
266
|
-
if (resBody.length > maxResSize) {
|
|
367
|
+
if (resBody && resBody.length > maxResSize) {
|
|
267
368
|
resBody = false;
|
|
268
369
|
}
|
|
269
370
|
}
|
|
@@ -286,9 +387,13 @@ function emitDataEvents(req, res, proxy) {
|
|
|
286
387
|
resData.hasGzipError = unzipBody(info, resBody, function (err, body) {
|
|
287
388
|
if (!data.resError) {
|
|
288
389
|
resBody = err ? util.getErrorStack(err) : body;
|
|
289
|
-
|
|
390
|
+
if (isSse) {
|
|
391
|
+
resBody = parseFrame(resBody, true, true);
|
|
392
|
+
} else {
|
|
393
|
+
resData.body = resBody;
|
|
394
|
+
}
|
|
290
395
|
}
|
|
291
|
-
setUnzipSize(body, resData);
|
|
396
|
+
!isSse && setUnzipSize(body, resData);
|
|
292
397
|
checkBodySize(resData, useBigData);
|
|
293
398
|
setEndTime();
|
|
294
399
|
reqEmitter.emit('end', data);
|
|
@@ -341,7 +446,8 @@ function emitDataEvents(req, res, proxy) {
|
|
|
341
446
|
}
|
|
342
447
|
!endTime && setEndTime();
|
|
343
448
|
delete data.abort;
|
|
344
|
-
|
|
449
|
+
var msg = err && err.message;
|
|
450
|
+
if (msg !== 'Aborted') {
|
|
345
451
|
data.resError = true;
|
|
346
452
|
if (resData.body) {
|
|
347
453
|
data.errMsg = util.getErrorStack(err);
|
package/lib/inspectors/log.js
CHANGED
|
@@ -29,7 +29,11 @@ module.exports = function (req, res) {
|
|
|
29
29
|
if (log) {
|
|
30
30
|
util.disableReqCache(req.headers);
|
|
31
31
|
var host = req.headers.host;
|
|
32
|
+
delete req.rules.log;
|
|
32
33
|
res.on('src', function (_res) {
|
|
34
|
+
if (!(log = req.rules.log) || !util.hasBody(_res)) {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
33
37
|
var topScript, isHtml;
|
|
34
38
|
if (util.supportHtmlTransform(_res, req)) {
|
|
35
39
|
isHtml = true;
|
package/lib/inspectors/req.js
CHANGED
|
@@ -147,9 +147,11 @@ function handleReq(req, data, reqRules, delType) {
|
|
|
147
147
|
}
|
|
148
148
|
}
|
|
149
149
|
|
|
150
|
-
function handleAuth(data,
|
|
151
|
-
auth = util.getAuthBasic(
|
|
152
|
-
|
|
150
|
+
function handleAuth(data, authObj) {
|
|
151
|
+
var auth = util.getAuthBasic(authObj);
|
|
152
|
+
if (auth) {
|
|
153
|
+
util.setHeader(data, (authObj.proxy ? 'proxy-' : '') + 'authorization', auth);
|
|
154
|
+
}
|
|
153
155
|
}
|
|
154
156
|
|
|
155
157
|
function handleParams(req, params, urlParams, enableBigData) {
|
package/lib/inspectors/weinre.js
CHANGED
|
@@ -21,17 +21,22 @@ function getScript(host, name, isHtml, req) {
|
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
module.exports = function (req, res) {
|
|
24
|
-
|
|
24
|
+
var weinre = req.rules.weinre;
|
|
25
|
+
if (weinre) {
|
|
25
26
|
util.disableReqCache(req.headers);
|
|
27
|
+
delete req.rules.weinre;
|
|
26
28
|
var host = req.headers.host;
|
|
27
29
|
res.on('src', function (_res) {
|
|
30
|
+
if (!(weinre = req.rules.weinre) || !util.hasBody(_res)) {
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
28
33
|
var isHtml = util.supportHtmlTransform(_res, req);
|
|
29
34
|
if (!isHtml && util.getContentType(_res.headers) !== 'JS') {
|
|
30
35
|
return;
|
|
31
36
|
}
|
|
32
37
|
!util.isEnable(req, 'keepAllCSP') && util.disableCSP(_res.headers);
|
|
33
38
|
!req._customCache && util.disableResStore(_res.headers);
|
|
34
|
-
var name = util.getPath(util.rule.getMatcher(
|
|
39
|
+
var name = util.getPath(util.rule.getMatcher(weinre));
|
|
35
40
|
var transform = new Transform();
|
|
36
41
|
transform._transform = function (chunk, _, callback) {
|
|
37
42
|
if (!chunk) {
|
|
@@ -12,6 +12,7 @@ var notUninstallPluginPaths = config.notUninstallPluginPaths || [];
|
|
|
12
12
|
var projectPluginPaths = config.projectPluginPaths || [];
|
|
13
13
|
var accountPluginsPath = config.accountPluginsPath || [];
|
|
14
14
|
var paths = mp.getPaths();
|
|
15
|
+
var PLUGIN_DIR = pluginUtil.PLUGIN_DIR;
|
|
15
16
|
|
|
16
17
|
function getMTimeSync(filePath) {
|
|
17
18
|
var stats = common.getStatSync(filePath);
|
|
@@ -41,8 +42,9 @@ function readPluginModulesSync(dir, plugins) {
|
|
|
41
42
|
var mtime = getMTimeSync(path.join(root, 'package.json'));
|
|
42
43
|
if (mtime != null) {
|
|
43
44
|
var old = plugins[name];
|
|
44
|
-
if (
|
|
45
|
+
if (pluginUtil.compparePlugin(dir, mtime, old)) {
|
|
45
46
|
plugins[name] = {
|
|
47
|
+
[PLUGIN_DIR]: dir,
|
|
46
48
|
mtime: mtime,
|
|
47
49
|
root: root,
|
|
48
50
|
account: account,
|
|
@@ -65,8 +67,9 @@ function readPluginModulesSync(dir, plugins) {
|
|
|
65
67
|
var mtime = getMTimeSync(path.join(root, 'package.json'));
|
|
66
68
|
if (mtime != null) {
|
|
67
69
|
var old = plugins[name];
|
|
68
|
-
if (
|
|
70
|
+
if (pluginUtil.compparePlugin(dir, mtime, old)) {
|
|
69
71
|
plugins[name] = {
|
|
72
|
+
[PLUGIN_DIR]: dir,
|
|
70
73
|
root: root,
|
|
71
74
|
mtime: mtime,
|
|
72
75
|
account: account,
|
|
@@ -95,15 +98,15 @@ module.exports = function () {
|
|
|
95
98
|
if (pluginUtil.excludePlugin(simpleName)) {
|
|
96
99
|
return;
|
|
97
100
|
}
|
|
98
|
-
var
|
|
99
|
-
var account =
|
|
100
|
-
var isSys =
|
|
101
|
-
var isProj =
|
|
102
|
-
var notUn =
|
|
103
|
-
var isDev =
|
|
104
|
-
var dirName =
|
|
105
|
-
var mtime =
|
|
106
|
-
dir =
|
|
101
|
+
var obj = plugins[name];
|
|
102
|
+
var account = obj.account;
|
|
103
|
+
var isSys = obj.isSys;
|
|
104
|
+
var isProj = obj.isProj;
|
|
105
|
+
var notUn = obj.notUn;
|
|
106
|
+
var isDev = obj.isDev;
|
|
107
|
+
var dirName = obj.dir;
|
|
108
|
+
var mtime = obj.mtime;
|
|
109
|
+
var dir = obj.root;
|
|
107
110
|
var pkgPath = path.join(dir, 'package.json');
|
|
108
111
|
var pkg = common.readJsonSync(pkgPath);
|
|
109
112
|
if (!pkg) {
|
|
@@ -120,6 +123,7 @@ module.exports = function () {
|
|
|
120
123
|
var tabs = util.getInspectorTabs(conf);
|
|
121
124
|
var hintList = util.getHintList(conf);
|
|
122
125
|
var plugin = {
|
|
126
|
+
[PLUGIN_DIR]: obj[PLUGIN_DIR],
|
|
123
127
|
account: account,
|
|
124
128
|
dir: dirName,
|
|
125
129
|
isSys: isSys,
|
|
@@ -9,6 +9,7 @@ var customPluginPaths = config.customPluginPaths || [];
|
|
|
9
9
|
var notUninstallPluginPaths = config.notUninstallPluginPaths || [];
|
|
10
10
|
var projectPluginPaths = config.projectPluginPaths || [];
|
|
11
11
|
var accountPluginsPath = config.accountPluginsPath || [];
|
|
12
|
+
var PLUGIN_DIR = pluginUtil.PLUGIN_DIR;
|
|
12
13
|
|
|
13
14
|
function readPluginRootList(dir, callback) {
|
|
14
15
|
var roots = [];
|
|
@@ -31,7 +32,7 @@ function readPluginRootList(dir, callback) {
|
|
|
31
32
|
if (pluginUtil.isWhistleModule(name)) {
|
|
32
33
|
roots[i] = {
|
|
33
34
|
name: name,
|
|
34
|
-
|
|
35
|
+
[PLUGIN_DIR]: dir
|
|
35
36
|
};
|
|
36
37
|
} else if (pluginUtil.isOrgModule(name)) {
|
|
37
38
|
++count;
|
|
@@ -44,7 +45,7 @@ function readPluginRootList(dir, callback) {
|
|
|
44
45
|
orgList.push({
|
|
45
46
|
org: name,
|
|
46
47
|
name: pluginName,
|
|
47
|
-
|
|
48
|
+
[PLUGIN_DIR]: dir
|
|
48
49
|
});
|
|
49
50
|
}
|
|
50
51
|
});
|
|
@@ -74,7 +75,7 @@ function readPluginModules(dir, callback, plugins, isSys) {
|
|
|
74
75
|
return callback(plugins);
|
|
75
76
|
}
|
|
76
77
|
list.forEach(function (obj) {
|
|
77
|
-
var dir = obj
|
|
78
|
+
var dir = obj[PLUGIN_DIR];
|
|
78
79
|
var dirName = obj.org ? obj.org + '/' + obj.name : obj.name;
|
|
79
80
|
pluginUtil.getSysPath(dir, dirName, isSys, function(root) {
|
|
80
81
|
common.getStat(path.join(root, 'package.json'), function (_, stats) {
|
|
@@ -83,13 +84,10 @@ function readPluginModules(dir, callback, plugins, isSys) {
|
|
|
83
84
|
obj.mtime = stats.mtime.getTime();
|
|
84
85
|
}
|
|
85
86
|
if (--len === 0) {
|
|
86
|
-
list.forEach(function (
|
|
87
|
-
var name = pluginUtil.getPluginName(
|
|
88
|
-
if (
|
|
89
|
-
|
|
90
|
-
if (!old || (obj.mtime > old.mtime && obj.root === old.root)) {
|
|
91
|
-
plugins[name] = obj;
|
|
92
|
-
}
|
|
87
|
+
list.forEach(function (item) {
|
|
88
|
+
var name = pluginUtil.getPluginName(item.name);
|
|
89
|
+
if (item.root && pluginUtil.compparePlugin(dir, item.mtime, plugins[name])) {
|
|
90
|
+
plugins[name] = item;
|
|
93
91
|
}
|
|
94
92
|
});
|
|
95
93
|
callback(plugins);
|
|
@@ -121,10 +119,11 @@ module.exports = function (callback) {
|
|
|
121
119
|
if (pluginUtil.excludePlugin(name)) {
|
|
122
120
|
return;
|
|
123
121
|
}
|
|
124
|
-
var old = result[name + ':'];
|
|
125
122
|
var obj = plugins[name];
|
|
126
|
-
|
|
123
|
+
var dir = obj[PLUGIN_DIR];
|
|
124
|
+
if (pluginUtil.compparePlugin(dir, obj.mtime, result[name + ':'])) {
|
|
127
125
|
result[name + ':'] = {
|
|
126
|
+
[PLUGIN_DIR]: dir,
|
|
128
127
|
account: account,
|
|
129
128
|
dir: config.whistleName,
|
|
130
129
|
isSys: isSys,
|
|
@@ -1202,7 +1202,7 @@ module.exports = async function (options, callback) {
|
|
|
1202
1202
|
PROXY_ID_HEADER = config.PROXY_ID_HEADER;
|
|
1203
1203
|
options.getTempFilePath = function(filePath) {
|
|
1204
1204
|
if (common.TEMP_PATH_RE.test(filePath)) {
|
|
1205
|
-
return path.join(
|
|
1205
|
+
return path.join(common.TEMP_FILES_PATH, RegExp.$1);
|
|
1206
1206
|
}
|
|
1207
1207
|
};
|
|
1208
1208
|
|
|
@@ -36,6 +36,7 @@ var pluginPaths = config.pluginPaths;
|
|
|
36
36
|
if (pluginPaths) {
|
|
37
37
|
pluginPaths = pluginPaths.concat(pluginPaths.map(formatPath).concat(addon));
|
|
38
38
|
pluginPaths = prePlugins.concat(pluginPaths);
|
|
39
|
+
config.PLUGIN_INSTALL_ROOT = pluginPaths[0];
|
|
39
40
|
addDebugPaths(pluginPaths);
|
|
40
41
|
pluginPaths = uniqueArr(pluginPaths);
|
|
41
42
|
exports.getPaths = function () {
|
|
@@ -80,6 +81,9 @@ if (pluginsPath && paths.indexOf(pluginsPath) == -1) {
|
|
|
80
81
|
}
|
|
81
82
|
if (!config.customPluginPaths || !config.customPluginPaths.length) {
|
|
82
83
|
paths.unshift(config.CUSTOM_PLUGIN_PATH);
|
|
84
|
+
config.PLUGIN_INSTALL_ROOT = config.CUSTOM_PLUGIN_PATH;
|
|
85
|
+
} else {
|
|
86
|
+
config.PLUGIN_INSTALL_ROOT = config.customPluginPaths[0];
|
|
83
87
|
}
|
|
84
88
|
paths = addon.concat(paths);
|
|
85
89
|
addDebugPaths(paths);
|
package/lib/plugins/util.js
CHANGED
|
@@ -13,11 +13,14 @@ var MAX_EXPIRE = 36000;
|
|
|
13
13
|
var UTF8_OPTIONS = { encoding: 'utf8' };
|
|
14
14
|
var workerScript = util.readFileSync(path.join(__dirname, '../../assets/js/worker.js'), false);
|
|
15
15
|
var workers = {};
|
|
16
|
+
var PLUGIN_DIR = Symbol('dir');
|
|
16
17
|
|
|
17
18
|
function replaceScript(ctn, name) {
|
|
18
19
|
return workerScript.replace('$PLUGIN_NAME', name).replace('/*sourcecode*/', ctn);
|
|
19
20
|
}
|
|
20
21
|
|
|
22
|
+
exports.PLUGIN_DIR = PLUGIN_DIR;
|
|
23
|
+
|
|
21
24
|
exports.readWorkerSync = function(root, conf, name) {
|
|
22
25
|
var file = util.getWebWorker(conf);
|
|
23
26
|
file = file && util.readFileSync(path.join(root, file));
|
|
@@ -140,6 +143,7 @@ function setPlugin(plugins, pkg, root, mtime, sync) {
|
|
|
140
143
|
if (PLUGIN_NAME_RE.test(pkg.name)) {
|
|
141
144
|
var name = sync ? RegExp.$1 : getPluginName(RegExp.$1);
|
|
142
145
|
plugins[name] = {
|
|
146
|
+
[PLUGIN_DIR]: DEV_PLUGINS_PATH,
|
|
143
147
|
root: root,
|
|
144
148
|
mtime: mtime,
|
|
145
149
|
notUn: true,
|
|
@@ -256,3 +260,7 @@ exports.getSysPath = function(dir, name, isSys, cb) {
|
|
|
256
260
|
cb(exists ? sysRoot : root);
|
|
257
261
|
});
|
|
258
262
|
};
|
|
263
|
+
|
|
264
|
+
exports.compparePlugin = function (dir, mtime, old) {
|
|
265
|
+
return !old || (mtime > old.mtime && dir === old[PLUGIN_DIR]);
|
|
266
|
+
};
|
package/lib/rules/dns.js
CHANGED
package/lib/rules/index.js
CHANGED
|
@@ -63,7 +63,6 @@ exports.hasReqScript = rules.hasReqScript.bind(rules);
|
|
|
63
63
|
exports.resolveDisable = rules.resolveDisable.bind(rules);
|
|
64
64
|
exports.resolvePipe = rules.resolvePipe.bind(rules);
|
|
65
65
|
exports.resolveRule = rules.resolveRule.bind(rules);
|
|
66
|
-
exports.resolveRules = resolveReqRules;
|
|
67
66
|
exports.resolveResRules = rules.resolveResRules.bind(rules);
|
|
68
67
|
exports.resolveBodyFilter = rules.resolveBodyFilter.bind(rules);
|
|
69
68
|
exports.lookupHost = rules.lookupHost.bind(rules);
|
package/lib/rules/protocols.js
CHANGED
|
@@ -73,6 +73,7 @@ var protocols = [
|
|
|
73
73
|
'cipher',
|
|
74
74
|
'sniCallback'
|
|
75
75
|
];
|
|
76
|
+
var toolProtocols = ['log', 'weinre'];
|
|
76
77
|
|
|
77
78
|
var RULE_RE = /^(?:|x|xs)(?:file|rawfile|dust|tpl|jsonp):/;
|
|
78
79
|
var LOC_RE = /^locationHref:/;
|
|
@@ -86,7 +87,6 @@ var pureResProtocols = [
|
|
|
86
87
|
'resDelay',
|
|
87
88
|
'resSpeed',
|
|
88
89
|
'resType',
|
|
89
|
-
'resType',
|
|
90
90
|
'resCharset',
|
|
91
91
|
'resCookies',
|
|
92
92
|
'resCors',
|
|
@@ -108,7 +108,7 @@ var pureResProtocols = [
|
|
|
108
108
|
'htmlPrepend',
|
|
109
109
|
'jsPrepend',
|
|
110
110
|
'responseFor'
|
|
111
|
-
];
|
|
111
|
+
].concat(toolProtocols);
|
|
112
112
|
var resProtocols = [
|
|
113
113
|
'filter',
|
|
114
114
|
'enable',
|
|
@@ -155,7 +155,7 @@ var aliasProtocols = {
|
|
|
155
155
|
var protocolsWithoutG = protocols.slice(1);
|
|
156
156
|
var reqProtocols = protocols.filter(function (name) {
|
|
157
157
|
return pureResProtocols.indexOf(name) === -1;
|
|
158
|
-
});
|
|
158
|
+
}).concat(toolProtocols);
|
|
159
159
|
var reqProtosWithoutG = reqProtocols.filter(function (name) {
|
|
160
160
|
return name !== 'G';
|
|
161
161
|
});
|
|
@@ -266,12 +266,6 @@ function resetRules(rules) {
|
|
|
266
266
|
|
|
267
267
|
exports.resetRules = resetRules;
|
|
268
268
|
|
|
269
|
-
function isResRule(protocol) {
|
|
270
|
-
return resProtocols.indexOf(protocol) != -1;
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
exports.isResRule = isResRule;
|
|
274
|
-
|
|
275
269
|
function isWebProtocol(protocol) {
|
|
276
270
|
return protocol == 'http:' || protocol == 'https:';
|
|
277
271
|
}
|
package/lib/rules/rules.js
CHANGED
|
@@ -14,7 +14,6 @@ var env = process.env || {};
|
|
|
14
14
|
var allowDnsCache = true;
|
|
15
15
|
var SUB_MATCH_RE = /\$[&\d]/;
|
|
16
16
|
var BODY_MATCH_RE = /\$b[&\d]/;
|
|
17
|
-
var SPACE_RE = /\s+/g;
|
|
18
17
|
var EXACT_RE = /^\$/;
|
|
19
18
|
var NON_RE = /^!/;
|
|
20
19
|
var HAS_SPACE_RE = /\s/;
|
|
@@ -98,6 +97,7 @@ var FILE_PROTO_RE = /^x?((raw)?file|tpl|jsonp|dust):\/\//;
|
|
|
98
97
|
var NO_PROTO_RE = /[^\w!*|.-]/;
|
|
99
98
|
var SKIP_RE = /^skip:\/\//;
|
|
100
99
|
var SUB_VAR_RE = /\$\{RegExp\.\$([&\d])\}/g;
|
|
100
|
+
var TOOL_RE = /^(?:log|weinre):\/\//;
|
|
101
101
|
var mIndex = 0;
|
|
102
102
|
var mNow = Date.now();
|
|
103
103
|
var IS_JSON = Symbol('isJson');
|
|
@@ -370,7 +370,7 @@ function joinUrl(a, b) {
|
|
|
370
370
|
}
|
|
371
371
|
|
|
372
372
|
function toLine(_, line) {
|
|
373
|
-
return line.replace(
|
|
373
|
+
return line.replace(/\s+/g, ' ');
|
|
374
374
|
}
|
|
375
375
|
|
|
376
376
|
function mergeLines(text) {
|
|
@@ -799,18 +799,12 @@ function getValueFor(key, vals, file) {
|
|
|
799
799
|
return val;
|
|
800
800
|
}
|
|
801
801
|
|
|
802
|
-
function getRule(req, list, vals, index, isFilter, host) {
|
|
803
|
-
var rule = resolveRuleList(req, list, vals, index || 0, isFilter, null, host);
|
|
802
|
+
function getRule(req, list, vals, index, isFilter, host, isReq) {
|
|
803
|
+
var rule = resolveRuleList(req, list, vals, index || 0, isFilter, null, host, isReq);
|
|
804
804
|
resolveValue(rule, vals, req);
|
|
805
805
|
return rule;
|
|
806
806
|
}
|
|
807
807
|
|
|
808
|
-
function getRuleList(req, list, vals, isEnableProxy) {
|
|
809
|
-
return resolveRuleList(req, list, vals, isEnableProxy).map(function (rule) {
|
|
810
|
-
return resolveValue(rule, vals, req);
|
|
811
|
-
});
|
|
812
|
-
}
|
|
813
|
-
|
|
814
808
|
function resolveValue(rule, vals, req) {
|
|
815
809
|
if (!rule) {
|
|
816
810
|
return;
|
|
@@ -924,7 +918,7 @@ function checkInternal(req, rule) {
|
|
|
924
918
|
return props.internalOnly;
|
|
925
919
|
}
|
|
926
920
|
|
|
927
|
-
function resolveRuleList(req, list, vals, index, isFilter, isEnableProxy, host) {
|
|
921
|
+
function resolveRuleList(req, list, vals, index, isFilter, isEnableProxy, host, isReq) {
|
|
928
922
|
var curUrl = util.formatUrl(req.curUrl);
|
|
929
923
|
var notHttp = list.isRuleProto && curUrl[0] !== 'h';
|
|
930
924
|
//支持域名匹配
|
|
@@ -986,6 +980,9 @@ function resolveRuleList(req, list, vals, index, isFilter, isEnableProxy, host)
|
|
|
986
980
|
if (notHttp && protoMgr.isFileProxy(rule.matcher)) {
|
|
987
981
|
return false;
|
|
988
982
|
}
|
|
983
|
+
if (isReq && TOOL_RE.test(rule.matcher)) {
|
|
984
|
+
return true;
|
|
985
|
+
}
|
|
989
986
|
return (isFilter || !matchExcludeFilters(curUrl, rule, req)) && (host == null || util.checkProxyHost(rule, host));
|
|
990
987
|
};
|
|
991
988
|
|
|
@@ -1155,7 +1152,7 @@ function resolveProps(req, rules, vals, isIgnore) {
|
|
|
1155
1152
|
return result;
|
|
1156
1153
|
}
|
|
1157
1154
|
}
|
|
1158
|
-
return util.
|
|
1155
|
+
return util.parseRuleProps(list, result);
|
|
1159
1156
|
}
|
|
1160
1157
|
|
|
1161
1158
|
function parseWildcard(pattern, not) {
|
|
@@ -1868,7 +1865,7 @@ function matchFilter(url, filter, req) {
|
|
|
1868
1865
|
if (keyLen > 0 && key[keyLen] === '%') {
|
|
1869
1866
|
key = key.substring(0, keyLen) / 100;
|
|
1870
1867
|
}
|
|
1871
|
-
return getFilterResult(Math.random() <
|
|
1868
|
+
return getFilterResult(Math.random() < key, filter);
|
|
1872
1869
|
}
|
|
1873
1870
|
if (filterProp(req.method, filter.method, filter.mPattern)) {
|
|
1874
1871
|
return getFilterResult(result, filter);
|
|
@@ -1967,7 +1964,7 @@ function matchFilter(url, filter, req) {
|
|
|
1967
1964
|
return false;
|
|
1968
1965
|
}
|
|
1969
1966
|
|
|
1970
|
-
function matchExcludeFilters(url, rule,
|
|
1967
|
+
function matchExcludeFilters(url, rule, req) {
|
|
1971
1968
|
var filters = rule.filters;
|
|
1972
1969
|
if (!filters) {
|
|
1973
1970
|
return;
|
|
@@ -1980,7 +1977,7 @@ function matchExcludeFilters(url, rule, options) {
|
|
|
1980
1977
|
hasIncludeFilter = hasIncludeFilter || filter.isInclude;
|
|
1981
1978
|
if (
|
|
1982
1979
|
(filter.isInclude ? !include : !exclude) &&
|
|
1983
|
-
matchFilter(url, filter,
|
|
1980
|
+
matchFilter(url, filter, req)
|
|
1984
1981
|
) {
|
|
1985
1982
|
if (filter.isInclude) {
|
|
1986
1983
|
include = true;
|
|
@@ -2249,7 +2246,7 @@ function resolveRules(req, isReq, isRes) {
|
|
|
2249
2246
|
name === 'rule' ||
|
|
2250
2247
|
name === 'plugin' ||
|
|
2251
2248
|
!filter[name]) &&
|
|
2252
|
-
(rule = self.getRule(req, rules[name], vals))
|
|
2249
|
+
(rule = self.getRule(req, rules[name], vals, null, null, null, isReq))
|
|
2253
2250
|
) {
|
|
2254
2251
|
_rules[name] = rule;
|
|
2255
2252
|
}
|
|
@@ -2283,15 +2280,17 @@ function resolveRules(req, isReq, isRes) {
|
|
|
2283
2280
|
return _rules;
|
|
2284
2281
|
}
|
|
2285
2282
|
|
|
2286
|
-
proto.getRule = function(req, list, vals, index, isFilter, host) {
|
|
2283
|
+
proto.getRule = function(req, list, vals, index, isFilter, host, isReq) {
|
|
2287
2284
|
if (!this._isGlobal || !req._disabledProxyRules) {
|
|
2288
|
-
return getRule(req, list, vals, index, isFilter, host);
|
|
2285
|
+
return getRule(req, list, vals, index, isFilter, host, isReq);
|
|
2289
2286
|
}
|
|
2290
2287
|
};
|
|
2291
2288
|
|
|
2292
2289
|
proto.getRuleList = function(req, list, vals, isEnableProxy) {
|
|
2293
2290
|
if (!this._isGlobal || !req._disabledProxyRules) {
|
|
2294
|
-
return
|
|
2291
|
+
return resolveRuleList(req, list, vals, null, false, isEnableProxy).map(function (rule) {
|
|
2292
|
+
return resolveValue(rule, vals, req);
|
|
2293
|
+
});
|
|
2295
2294
|
}
|
|
2296
2295
|
return [];
|
|
2297
2296
|
};
|
|
@@ -2341,8 +2340,8 @@ proto.resolveProxyProps = function (req) {
|
|
|
2341
2340
|
}
|
|
2342
2341
|
mergeRule(req.rules, enable, 'enable');
|
|
2343
2342
|
mergeRule(req.rules, disable, 'disable');
|
|
2344
|
-
enable = util.
|
|
2345
|
-
disable = util.
|
|
2343
|
+
enable = util.parseRuleProps(enable);
|
|
2344
|
+
disable = util.parseRuleProps(disable);
|
|
2346
2345
|
if (disable.clientId || disable.clientID || disable.clientid) {
|
|
2347
2346
|
req.disable.clientId = true;
|
|
2348
2347
|
}
|
|
@@ -2417,7 +2416,7 @@ proto.hasReqScript = function (req) {
|
|
|
2417
2416
|
: this.getRule(req, this._rules.rulesFile, this._values);
|
|
2418
2417
|
};
|
|
2419
2418
|
|
|
2420
|
-
proto.resolveProxy = function
|
|
2419
|
+
proto.resolveProxy = function (req, host) {
|
|
2421
2420
|
var proxy = this.getRule(req, this._rules.proxy, this._values, null, null, host);
|
|
2422
2421
|
var matcher = proxy && proxy.matcher;
|
|
2423
2422
|
var name = matcher && matcher.substring(0, matcher.indexOf(':'));
|