whistle 2.10.6 → 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.
- package/assets/menu.html +2 -2
- package/assets/modal.html +2 -2
- package/assets/tab.html +2 -2
- package/bin/api.js +545 -0
- package/bin/import.js +3 -3
- package/bin/plugin.js +4 -8
- package/bin/use.js +22 -8
- package/bin/util.js +10 -5
- package/bin/whistle.js +11 -1
- package/biz/webui/cgi-bin/abort.js +14 -5
- package/biz/webui/cgi-bin/frames.js +12 -0
- package/biz/webui/cgi-bin/is-enabled-https.js +6 -0
- package/biz/webui/cgi-bin/plugins/disable-plugin.js +16 -7
- package/biz/webui/cgi-bin/plugins/list.js +17 -0
- package/biz/webui/cgi-bin/plugins/plugin.js +21 -0
- package/biz/webui/cgi-bin/plugins/status.js +21 -0
- package/biz/webui/cgi-bin/rules/is-multi-select.js +7 -0
- package/biz/webui/cgi-bin/rules/move-top.js +11 -0
- package/biz/webui/cgi-bin/rules/select.js +1 -1
- package/biz/webui/cgi-bin/rules/select2.js +16 -0
- package/biz/webui/cgi-bin/rules/status.js +6 -0
- package/biz/webui/cgi-bin/rules/unselect.js +3 -2
- package/biz/webui/cgi-bin/rules/unselect2.js +18 -0
- package/biz/webui/cgi-bin/rules/value.js +19 -0
- package/biz/webui/cgi-bin/sessions.js +6 -0
- package/biz/webui/cgi-bin/util.js +14 -0
- package/biz/webui/htdocs/index.html +1 -1
- package/biz/webui/htdocs/js/index.js +32 -32
- package/biz/webui/lib/index.js +1 -3
- package/lib/https/index.js +4 -4
- package/lib/init.js +1 -0
- package/lib/inspectors/data.js +6 -4
- package/lib/inspectors/req.js +1 -2
- package/lib/inspectors/res.js +6 -10
- package/lib/plugins/index.js +2 -2
- package/lib/plugins/load-plugin.js +17 -6
- package/lib/rules/util.js +20 -10
- package/lib/service/composer.js +7 -22
- package/lib/service/data-center.js +0 -12
- package/lib/service/generate-saz.js +2 -2
- package/lib/service/service.js +6 -5
- package/lib/service/util.js +6 -16
- package/lib/socket-mgr.js +23 -17
- package/lib/tunnel.js +7 -17
- package/lib/upgrade.js +4 -8
- package/lib/util/common.js +75 -9
- package/lib/util/data-server.js +273 -0
- package/lib/util/index.js +8 -22
- package/lib/util/patch.js +2 -6
- package/lib/util/speed-transform.js +17 -6
- package/lib/util/whistle-transform.js +18 -7
- package/package.json +10 -7
package/biz/webui/lib/index.js
CHANGED
|
@@ -36,7 +36,6 @@ var uploadJsonParser = bodyParser.json(UPLOAD_PARSE_CONF);
|
|
|
36
36
|
var GET_METHOD_RE = /^get$/i;
|
|
37
37
|
var WEINRE_RE = /^\/weinre\/.*/;
|
|
38
38
|
var ALLOW_PLUGIN_PATHS = ['/cgi-bin/rules/list2', '/cgi-bin/values/list2', '/cgi-bin/get-custom-certs-info'];
|
|
39
|
-
var SPECIAL_PATHS = ['/cgi-bin/rules/project'];
|
|
40
39
|
var DONT_CHECK_PATHS = ['/cgi-bin/server-info', '/cgi-bin/plugins/is-enable', '/cgi-bin/plugins/get-plugins',
|
|
41
40
|
'/preview.html', '/cgi-bin/rootca', '/cgi-bin/check-update', '/cgi-bin/log/set', '/cgi-bin/status'];
|
|
42
41
|
var GUEST_PATHS = ['/cgi-bin/composer', '/cgi-bin/socket/data', '/cgi-bin/abort', '/cgi-bin/socket/abort',
|
|
@@ -196,8 +195,7 @@ function checkAuth(req, res) {
|
|
|
196
195
|
if (verifyLogin(req, res, auth)) {
|
|
197
196
|
return true;
|
|
198
197
|
}
|
|
199
|
-
if (config.specialAuth &&
|
|
200
|
-
config.specialAuth === req.headers['x-whistle-special-auth']) {
|
|
198
|
+
if (config.specialAuth && config.specialAuth === req.headers['x-whistle-special-auth']) {
|
|
201
199
|
return true;
|
|
202
200
|
}
|
|
203
201
|
requireLogin(req, res);
|
package/lib/https/index.js
CHANGED
|
@@ -198,7 +198,7 @@ function resolveWebsocket(socket, wss) {
|
|
|
198
198
|
var delay = reqDelay + resDelay;
|
|
199
199
|
if (delay > 0) {
|
|
200
200
|
clearTimeout(timeout);
|
|
201
|
-
setTimeout(end, delay);
|
|
201
|
+
timeout = setTimeout(end, delay);
|
|
202
202
|
} else {
|
|
203
203
|
end();
|
|
204
204
|
}
|
|
@@ -304,7 +304,7 @@ function resolveWebsocket(socket, wss) {
|
|
|
304
304
|
var reqDelay = util.getMatcherValue(_rules.reqDelay);
|
|
305
305
|
if (reqDelay > 0) {
|
|
306
306
|
clearTimeout(timeout);
|
|
307
|
-
setTimeout(function () {
|
|
307
|
+
timeout = setTimeout(function () {
|
|
308
308
|
timeout = setTimeout(function () {
|
|
309
309
|
destroy(util.TIMEOUT_ERR);
|
|
310
310
|
}, CONN_TIMEOUT);
|
|
@@ -779,7 +779,7 @@ function resolveWebsocket(socket, wss) {
|
|
|
779
779
|
var curResHeaders = (reqSocket.headers = res.headers);
|
|
780
780
|
socket.resHeaders = curResHeaders;
|
|
781
781
|
getResRules(socket, res, function () {
|
|
782
|
-
util.delay(util.getMatcherValue(_rules.resDelay), function () {
|
|
782
|
+
util.setDelayTimer(socket, util.delay(util.getMatcherValue(_rules.resDelay), function () {
|
|
783
783
|
if (util.needAbortRes(socket)) {
|
|
784
784
|
socket.__statusCode = res.statusCode;
|
|
785
785
|
return destroy();
|
|
@@ -812,7 +812,7 @@ function resolveWebsocket(socket, wss) {
|
|
|
812
812
|
resData.statusCode = code;
|
|
813
813
|
reqEmitter.emit('response', data);
|
|
814
814
|
execCallback(null, reqSocket);
|
|
815
|
-
});
|
|
815
|
+
}));
|
|
816
816
|
});
|
|
817
817
|
},
|
|
818
818
|
true
|
package/lib/init.js
CHANGED
package/lib/inspectors/data.js
CHANGED
|
@@ -445,13 +445,14 @@ function emitDataEvents(req, res, proxy) {
|
|
|
445
445
|
|
|
446
446
|
function handleError(err) {
|
|
447
447
|
req._hasError = true;
|
|
448
|
+
util.clearDelayTimer(req);
|
|
448
449
|
if (!data || endTime || data.endTime || (data.responseTime && !err)) {
|
|
449
450
|
return;
|
|
450
451
|
}
|
|
451
452
|
!endTime && setEndTime();
|
|
452
453
|
delete data.abort;
|
|
453
|
-
var msg = err && err.message;
|
|
454
|
-
if (
|
|
454
|
+
// 不能乱优化,跟 var msg = err && err.message; if (msg !== 'Aborted' && msg !== 'aborted') 不一样
|
|
455
|
+
if (err && err.message !== 'Aborted' && err.message !== 'aborted') {
|
|
455
456
|
data.resError = true;
|
|
456
457
|
if (resData.body) {
|
|
457
458
|
data.errMsg = util.getErrorStack(err);
|
|
@@ -534,10 +535,11 @@ function emitDataEvents(req, res, proxy) {
|
|
|
534
535
|
|
|
535
536
|
module.exports = function (req, res, next) {
|
|
536
537
|
emitDataEvents(req, res, this);
|
|
537
|
-
util.
|
|
538
|
+
var reqDelay = util.getMatcherValue(req.rules.reqDelay);
|
|
539
|
+
util.setDelayTimer(req, util.delay(reqDelay, function () {
|
|
538
540
|
if (util.needAbortReq(req)) {
|
|
539
541
|
return res.destroy();
|
|
540
542
|
}
|
|
541
543
|
next();
|
|
542
|
-
});
|
|
544
|
+
}));
|
|
543
545
|
};
|
package/lib/inspectors/req.js
CHANGED
|
@@ -10,7 +10,6 @@ var handleWeinre = require('./weinre');
|
|
|
10
10
|
var handleLog = require('./log');
|
|
11
11
|
|
|
12
12
|
var Transform = require('pipestream').Transform;
|
|
13
|
-
var WhistleTransform = util.WhistleTransform;
|
|
14
13
|
var ReplacePatternTransform = util.ReplacePatternTransform;
|
|
15
14
|
var ReplaceStringTransform = util.ReplaceStringTransform;
|
|
16
15
|
var FileWriterTransform = util.FileWriterTransform;
|
|
@@ -127,7 +126,7 @@ function handleReq(req, data, reqRules, delType) {
|
|
|
127
126
|
}
|
|
128
127
|
|
|
129
128
|
util.isWhistleTransformData(data) &&
|
|
130
|
-
req.addZipTransform(new WhistleTransform(data));
|
|
129
|
+
req.addZipTransform(new util.WhistleTransform(data, req));
|
|
131
130
|
var opList = util.parseHeaderReplace(req.rules.headerReplace).req;
|
|
132
131
|
if (opList) {
|
|
133
132
|
var host = req.headers.host;
|
package/lib/inspectors/res.js
CHANGED
|
@@ -11,10 +11,6 @@ var pluginMgr = require('../plugins');
|
|
|
11
11
|
var hparser = require('hparser');
|
|
12
12
|
var config = require('../config');
|
|
13
13
|
|
|
14
|
-
var WhistleTransform = util.WhistleTransform;
|
|
15
|
-
var SpeedTransform = util.SpeedTransform;
|
|
16
|
-
var ReplacePatternTransform = util.ReplacePatternTransform;
|
|
17
|
-
var ReplaceStringTransform = util.ReplaceStringTransform;
|
|
18
14
|
var FileWriterTransform = util.FileWriterTransform;
|
|
19
15
|
var formatHeaders = hparser.formatHeaders;
|
|
20
16
|
var getRawHeaderNames = hparser.getRawHeaderNames;
|
|
@@ -137,9 +133,9 @@ function handleReplace(res, replacement) {
|
|
|
137
133
|
util.isOriginalRegExp(pattern) &&
|
|
138
134
|
(pattern = util.toOriginalRegExp(pattern))
|
|
139
135
|
) {
|
|
140
|
-
res.addTextTransform(new ReplacePatternTransform(pattern, value, util.isSSE(res)));
|
|
136
|
+
res.addTextTransform(new util.ReplacePatternTransform(pattern, value, util.isSSE(res)));
|
|
141
137
|
} else if (pattern) {
|
|
142
|
-
res.addTextTransform(new ReplaceStringTransform(pattern, value, util.isSSE(res)));
|
|
138
|
+
res.addTextTransform(new util.ReplaceStringTransform(pattern, value, util.isSSE(res)));
|
|
143
139
|
}
|
|
144
140
|
});
|
|
145
141
|
}
|
|
@@ -1008,7 +1004,7 @@ module.exports = function (req, res, next) {
|
|
|
1008
1004
|
data.top = resPrepend;
|
|
1009
1005
|
data.bottom = resAppend;
|
|
1010
1006
|
|
|
1011
|
-
var speedTransform = data.speed || data.delay ? new SpeedTransform(data) : null;
|
|
1007
|
+
var speedTransform = data.speed || data.delay ? new util.SpeedTransform(data, req) : null;
|
|
1012
1008
|
delete data.headers;
|
|
1013
1009
|
delete data.speed;
|
|
1014
1010
|
delete data.delay;
|
|
@@ -1113,7 +1109,7 @@ module.exports = function (req, res, next) {
|
|
|
1113
1109
|
}
|
|
1114
1110
|
if (util.isWhistleTransformData(data)) {
|
|
1115
1111
|
data.noDoctype = util.isDisable(req, 'doctype');
|
|
1116
|
-
res.addZipTransform(new WhistleTransform(data));
|
|
1112
|
+
res.addZipTransform(new util.WhistleTransform(data, req));
|
|
1117
1113
|
}
|
|
1118
1114
|
if (hasResBody) {
|
|
1119
1115
|
handleReplace(res, replacement);
|
|
@@ -1166,7 +1162,7 @@ module.exports = function (req, res, next) {
|
|
|
1166
1162
|
if (_resHeaders[config.ALPN_PROTOCOL_HEADER] === 'h2') {
|
|
1167
1163
|
req.useH2 = true;
|
|
1168
1164
|
}
|
|
1169
|
-
util.delay(
|
|
1165
|
+
util.setDelayTimer(req, util.delay(
|
|
1170
1166
|
util.getMatcherValue(resRules.resDelay),
|
|
1171
1167
|
function () {
|
|
1172
1168
|
if (req._hasError) {
|
|
@@ -1299,7 +1295,7 @@ module.exports = function (req, res, next) {
|
|
|
1299
1295
|
util.emitError(res, e);
|
|
1300
1296
|
}
|
|
1301
1297
|
}
|
|
1302
|
-
);
|
|
1298
|
+
));
|
|
1303
1299
|
},
|
|
1304
1300
|
util.isEnable(req, 'forceReqWrite')
|
|
1305
1301
|
);
|
package/lib/plugins/index.js
CHANGED
|
@@ -516,8 +516,8 @@ var delayTimer;
|
|
|
516
516
|
|
|
517
517
|
function refreshPlugins() {
|
|
518
518
|
updating = true;
|
|
519
|
-
|
|
520
|
-
|
|
519
|
+
clearTimeout(delayTimer);
|
|
520
|
+
clearTimeout(updateTimer);
|
|
521
521
|
delayTimer = null;
|
|
522
522
|
updateTimer = null;
|
|
523
523
|
getPlugin(function (result) {
|
|
@@ -46,7 +46,6 @@ var httpRequest = http.request;
|
|
|
46
46
|
var httpsRequest = https.request;
|
|
47
47
|
var formatHeaders = hparser.formatHeaders;
|
|
48
48
|
var getRawHeaderNames = hparser.getRawHeaderNames;
|
|
49
|
-
var getRawHeaders = hparser.getRawHeaders;
|
|
50
49
|
var STATUS_CODES = http.STATUS_CODES || {};
|
|
51
50
|
var clientIpKey = Symbol('clientIp');
|
|
52
51
|
var clientPortKey = Symbol('clientPort');
|
|
@@ -906,6 +905,9 @@ function wrapTunnelWriter(socket, toServer) {
|
|
|
906
905
|
var write = socket.write;
|
|
907
906
|
var end = socket.end;
|
|
908
907
|
var sender = wsParser.getSender(socket, toServer);
|
|
908
|
+
var notNeedDrain = function() {
|
|
909
|
+
return socket.writableNeedDrain !== true;
|
|
910
|
+
};
|
|
909
911
|
handleError(socket, sender);
|
|
910
912
|
socket.write = function (chunk, encoding, cb) {
|
|
911
913
|
if ((chunk = toBuffer(chunk))) {
|
|
@@ -917,6 +919,7 @@ function wrapTunnelWriter(socket, toServer) {
|
|
|
917
919
|
} else {
|
|
918
920
|
sender.send(chunk);
|
|
919
921
|
}
|
|
922
|
+
return notNeedDrain();
|
|
920
923
|
}
|
|
921
924
|
};
|
|
922
925
|
if (toServer) {
|
|
@@ -926,16 +929,19 @@ function wrapTunnelWriter(socket, toServer) {
|
|
|
926
929
|
return write.call(this, chunk, opts, cb);
|
|
927
930
|
}
|
|
928
931
|
sender.send(chunk, getOptions(opts, false, true));
|
|
932
|
+
return notNeedDrain();
|
|
929
933
|
}
|
|
930
934
|
};
|
|
931
935
|
socket.writeText = function (chunk) {
|
|
932
936
|
if ((chunk = toBuffer(chunk))) {
|
|
933
937
|
sender.send(chunk, getOptions(null, false, true));
|
|
938
|
+
return notNeedDrain();
|
|
934
939
|
}
|
|
935
940
|
};
|
|
936
941
|
socket.writeBin = function (chunk) {
|
|
937
942
|
if ((chunk = toBuffer(chunk))) {
|
|
938
943
|
sender.send(chunk, getOptions(null, true, true));
|
|
944
|
+
return notNeedDrain();
|
|
939
945
|
}
|
|
940
946
|
};
|
|
941
947
|
socket.closeWebSocket = function (code, data, cb) {
|
|
@@ -951,6 +957,7 @@ function wrapTunnelWriter(socket, toServer) {
|
|
|
951
957
|
return write.call(this, chunk, encoding, cb);
|
|
952
958
|
}
|
|
953
959
|
sender.send(chunk);
|
|
960
|
+
return notNeedDrain();
|
|
954
961
|
}
|
|
955
962
|
};
|
|
956
963
|
}
|
|
@@ -1021,6 +1028,9 @@ function addFrameHandler(req, socket, maxWsPayload, fromClient, toServer) {
|
|
|
1021
1028
|
var end = socket.end;
|
|
1022
1029
|
var lastOpts;
|
|
1023
1030
|
var sender = wsParser.getSender(socket, toServer);
|
|
1031
|
+
var notNeedDrain = function() {
|
|
1032
|
+
return socket.writableNeedDrain !== true;
|
|
1033
|
+
};
|
|
1024
1034
|
|
|
1025
1035
|
handleError(socket, sender, receiver);
|
|
1026
1036
|
socket.emit = function (type, chunk) {
|
|
@@ -1042,16 +1052,19 @@ function addFrameHandler(req, socket, maxWsPayload, fromClient, toServer) {
|
|
|
1042
1052
|
return write.call(this, chunk, opts, cb);
|
|
1043
1053
|
}
|
|
1044
1054
|
sender.send(chunk, getOptions(opts || lastOpts, false, toServer));
|
|
1055
|
+
return notNeedDrain();
|
|
1045
1056
|
}
|
|
1046
1057
|
};
|
|
1047
1058
|
socket.writeText = function (chunk) {
|
|
1048
1059
|
if ((chunk = toBuffer(chunk))) {
|
|
1049
1060
|
sender.send(chunk, getOptions(null, false, toServer));
|
|
1061
|
+
return notNeedDrain();
|
|
1050
1062
|
}
|
|
1051
1063
|
};
|
|
1052
1064
|
socket.writeBin = function (chunk) {
|
|
1053
1065
|
if ((chunk = toBuffer(chunk))) {
|
|
1054
1066
|
sender.send(chunk, getOptions(null, true, toServer));
|
|
1067
|
+
return notNeedDrain();
|
|
1055
1068
|
}
|
|
1056
1069
|
};
|
|
1057
1070
|
socket.end = function (chunk, opts, cb) {
|
|
@@ -2253,11 +2266,9 @@ module.exports = async function (options, callback) {
|
|
|
2253
2266
|
socket.setRules = req.setResRules = socket.setResRules = noop;
|
|
2254
2267
|
resRules = null;
|
|
2255
2268
|
}
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
}
|
|
2260
|
-
socket.write(rawData + '\r\n\r\n', 'binary');
|
|
2269
|
+
headers = headers && formatRawHeaders(headers, svrRes);
|
|
2270
|
+
msg = msg || svrRes.statusMessage || STATUS_CODES[code] || '';
|
|
2271
|
+
socket.write(common.getHttpMeta('HTTP/1.1', code, msg, headers), 'binary');
|
|
2261
2272
|
};
|
|
2262
2273
|
req.request = function (uri, cb, opts) {
|
|
2263
2274
|
var args = normalizeArgs(uri, cb, req, curUrl, true, opts);
|
package/lib/rules/util.js
CHANGED
|
@@ -166,14 +166,19 @@ function unselectRulesFile(file, force, all) {
|
|
|
166
166
|
}
|
|
167
167
|
var selectedList = getSelectedRulesList();
|
|
168
168
|
var hasChanged;
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
169
|
+
if (file === false) {
|
|
170
|
+
hasChanged = selectedList.length;
|
|
171
|
+
selectedList = [];
|
|
172
|
+
} else {
|
|
173
|
+
all = all || [file];
|
|
174
|
+
all.forEach(function(name) {
|
|
175
|
+
var index = selectedList.indexOf(name);
|
|
176
|
+
if (index != -1) {
|
|
177
|
+
selectedList.splice(index, 1);
|
|
178
|
+
hasChanged = true;
|
|
179
|
+
}
|
|
180
|
+
});
|
|
181
|
+
}
|
|
177
182
|
if (hasChanged) {
|
|
178
183
|
rulesStorage.setProperty('selectedList', selectedList);
|
|
179
184
|
parseRules();
|
|
@@ -185,7 +190,7 @@ function unselectRulesFile(file, force, all) {
|
|
|
185
190
|
function allowMultipleChoice() {
|
|
186
191
|
return (
|
|
187
192
|
!config.disabledMultipleOption &&
|
|
188
|
-
propertiesStorage.getProperty('allowMultipleChoice')
|
|
193
|
+
!!propertiesStorage.getProperty('allowMultipleChoice')
|
|
189
194
|
);
|
|
190
195
|
}
|
|
191
196
|
|
|
@@ -290,8 +295,10 @@ exports.rules = {
|
|
|
290
295
|
}
|
|
291
296
|
});
|
|
292
297
|
return {
|
|
298
|
+
laterRulesFirst: propertiesStorage.getProperty('backRulesFirst') === true,
|
|
293
299
|
pluginsDisabled: propertiesStorage.getProperty('disabledAllPlugins'),
|
|
294
300
|
disabled: !config.notAllowedDisableRules && propertiesStorage.getProperty('disabledAllRules'),
|
|
301
|
+
multiSelect: allowMultipleChoice(),
|
|
295
302
|
list: list
|
|
296
303
|
};
|
|
297
304
|
},
|
|
@@ -320,6 +327,9 @@ exports.rules = {
|
|
|
320
327
|
exists: function(name) {
|
|
321
328
|
return rulesStorage.existsFile(name);
|
|
322
329
|
},
|
|
330
|
+
isSelected: function(name) {
|
|
331
|
+
return getSelectedRulesList().indexOf(name) !== -1;
|
|
332
|
+
},
|
|
323
333
|
recycleBin: rulesStorage.recycleBin,
|
|
324
334
|
enableBackRulesFirst: function (backRulesFirst) {
|
|
325
335
|
var curFlag = propertiesStorage.getProperty('backRulesFirst') === true;
|
|
@@ -338,7 +348,7 @@ exports.rules = {
|
|
|
338
348
|
});
|
|
339
349
|
return {
|
|
340
350
|
backRulesFirst: propertiesStorage.getProperty('backRulesFirst') === true,
|
|
341
|
-
allowMultipleChoice:
|
|
351
|
+
allowMultipleChoice: allowMultipleChoice(),
|
|
342
352
|
list: list
|
|
343
353
|
};
|
|
344
354
|
},
|
package/lib/service/composer.js
CHANGED
|
@@ -11,7 +11,6 @@ var Storage = require('../rules/storage');
|
|
|
11
11
|
var dataCenter = require('./data-center');
|
|
12
12
|
|
|
13
13
|
var formatHeaders = hparser.formatHeaders;
|
|
14
|
-
var getRawHeaders = hparser.getRawHeaders;
|
|
15
14
|
var getRawHeaderNames = hparser.getRawHeaderNames;
|
|
16
15
|
var config = {};
|
|
17
16
|
var noop = common.noop;
|
|
@@ -68,10 +67,8 @@ function handleComposerHistory(data, isConn) {
|
|
|
68
67
|
body: body.length > MAX_BODY_LEN ? body.substring(0, MAX_BODY_LEN) : body,
|
|
69
68
|
isHexText: !!data.isHexText,
|
|
70
69
|
base64: base64,
|
|
71
|
-
enableProxyRules:
|
|
70
|
+
enableProxyRules: data.enableProxyRules
|
|
72
71
|
};
|
|
73
|
-
var dataHash;
|
|
74
|
-
var base64Hash;
|
|
75
72
|
for (var i = 0, len = composerHistory.length; i < len; i++) {
|
|
76
73
|
var item = composerHistory[i];
|
|
77
74
|
if (
|
|
@@ -81,16 +78,12 @@ function handleComposerHistory(data, isConn) {
|
|
|
81
78
|
item.body === result.body &&
|
|
82
79
|
item.base64 === result.base64 &&
|
|
83
80
|
!item.useH2 !== result.useH2 &&
|
|
84
|
-
|
|
81
|
+
item.enableProxyRules === result.enableProxyRules
|
|
85
82
|
) {
|
|
86
|
-
dataHash = item.dataHash;
|
|
87
|
-
base64Hash = item.base64Hash;
|
|
88
83
|
composerHistory.splice(i, 1);
|
|
89
84
|
break;
|
|
90
85
|
}
|
|
91
86
|
}
|
|
92
|
-
result.dataHash = dataHash;
|
|
93
|
-
result.base64Hash = base64Hash;
|
|
94
87
|
composerHistory.unshift(result);
|
|
95
88
|
var overflow = composerHistory.length - MAX_HISTORY_LEN;
|
|
96
89
|
if (overflow > 0) {
|
|
@@ -183,16 +176,6 @@ function handleConnect(options, cb, count, testId) {
|
|
|
183
176
|
}
|
|
184
177
|
}
|
|
185
178
|
|
|
186
|
-
function getReqRaw(options) {
|
|
187
|
-
var headers = options.headers;
|
|
188
|
-
var statusLine = options.method +' ' + (options.path || '/') +' ' + 'HTTP/1.1';
|
|
189
|
-
var raw = statusLine;
|
|
190
|
-
if (headers = getRawHeaders(headers)) {
|
|
191
|
-
raw += '\r\n' + headers;
|
|
192
|
-
}
|
|
193
|
-
return raw + '\r\n\r\n';
|
|
194
|
-
}
|
|
195
|
-
|
|
196
179
|
function handleWebSocket(options, cb, count, testId) {
|
|
197
180
|
count = getReqCount(count);
|
|
198
181
|
if (options.protocol === 'https:' || options.protocol === 'wss:') {
|
|
@@ -213,7 +196,7 @@ function handleWebSocket(options, cb, count, testId) {
|
|
|
213
196
|
if (err) {
|
|
214
197
|
handleCallback(execCb, err, null, testId);
|
|
215
198
|
} else {
|
|
216
|
-
socket.write(
|
|
199
|
+
socket.write(common.getHttpMeta(options.method, options.path || '/', 'HTTP/1.1', options.headers));
|
|
217
200
|
var data = options.body;
|
|
218
201
|
if ((!data || !data.length) && !cb) {
|
|
219
202
|
return drain(socket);
|
|
@@ -293,7 +276,7 @@ function handleHttp(options, cb, count, reqId, testId) {
|
|
|
293
276
|
if (buffer === null) {
|
|
294
277
|
return;
|
|
295
278
|
}
|
|
296
|
-
|
|
279
|
+
clearTimeout(timer);
|
|
297
280
|
var headers = svrRes.headers;
|
|
298
281
|
if (typeof headers.trailer === 'string' && headers.trailer.indexOf(',') !== -1) {
|
|
299
282
|
headers.trailer = headers.trailer.split(',');
|
|
@@ -397,7 +380,9 @@ exports.handleRequest = function(req, res) {
|
|
|
397
380
|
headers[config.FROM_COM_HEADER] = '1';
|
|
398
381
|
var isTest = reqBody.isTest;
|
|
399
382
|
var testId;
|
|
400
|
-
|
|
383
|
+
var enableProxyRules = reqBody.enableProxyRules !== false && !reqBody.disabledGlobalRules;
|
|
384
|
+
reqBody.enableProxyRules = enableProxyRules;
|
|
385
|
+
if (!enableProxyRules || isTest) {
|
|
401
386
|
headers[config.DISABLE_RULES_HEADER] = '1';
|
|
402
387
|
if (isTest) {
|
|
403
388
|
testId = ++testIndex + '';
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
var common = require('../util/common');
|
|
2
2
|
var request = require('../util/http-mgr').request;
|
|
3
3
|
var util = require('./util');
|
|
4
|
-
var extend = require('extend');
|
|
5
4
|
|
|
6
5
|
var requestData;
|
|
7
6
|
var BASE_URL = 'https://' + common.SERVICE_HOST;
|
|
@@ -71,17 +70,6 @@ var saveComposeData = function(data) {
|
|
|
71
70
|
if (!config.whistleToken || !Array.isArray(historyList)) {
|
|
72
71
|
return;
|
|
73
72
|
}
|
|
74
|
-
historyList.map(function(item) {
|
|
75
|
-
var newItem = extend({}, item);
|
|
76
|
-
var rawData = item.headers + '\r\n\r\n' + (item.base64 || item.body || '');
|
|
77
|
-
if (!item.dataHash && !item.base64Hash) {
|
|
78
|
-
item[item.base64 ? 'base64Hash' : 'dataHash'] = util.getHexHash(rawData);
|
|
79
|
-
}
|
|
80
|
-
delete newItem.headers;
|
|
81
|
-
delete newItem.body;
|
|
82
|
-
delete newItem.base64;
|
|
83
|
-
return newItem;
|
|
84
|
-
});
|
|
85
73
|
};
|
|
86
74
|
|
|
87
75
|
var descSorter = function(a, b) {
|
|
@@ -124,11 +124,11 @@ module.exports = function (body, callback) {
|
|
|
124
124
|
var zip = new AdmZip();
|
|
125
125
|
sessions.map(function (item, index) {
|
|
126
126
|
item.req.url = item.url;
|
|
127
|
-
var req = util.
|
|
127
|
+
var req = util.getRawReq(item.req);
|
|
128
128
|
var res =
|
|
129
129
|
!item.res || item.res.statusCode == null
|
|
130
130
|
? Buffer.from('')
|
|
131
|
-
: util.
|
|
131
|
+
: util.getRawRes(item.res);
|
|
132
132
|
var name = getName();
|
|
133
133
|
item.index = index;
|
|
134
134
|
zip.addFile('raw/' + name + '_c.txt', req);
|
package/lib/service/service.js
CHANGED
|
@@ -96,12 +96,13 @@ function getFilename(filename, time, count) {
|
|
|
96
96
|
}
|
|
97
97
|
|
|
98
98
|
function saveSessions(data, cb) {
|
|
99
|
-
var
|
|
99
|
+
var sessions = data.sessions;
|
|
100
|
+
var count = Array.isArray(sessions) && sessions.length;
|
|
100
101
|
if (!count) {
|
|
101
102
|
return cb();
|
|
102
103
|
}
|
|
103
104
|
limiter.push(function (done) {
|
|
104
|
-
gzip(JSON.stringify(
|
|
105
|
+
gzip(JSON.stringify(sessions), function(err, buf) {
|
|
105
106
|
done();
|
|
106
107
|
if (err) {
|
|
107
108
|
return cb(err);
|
|
@@ -109,7 +110,7 @@ function saveSessions(data, cb) {
|
|
|
109
110
|
var filename = getFilename(data.filename, 0, count);
|
|
110
111
|
common.writeFile(path.join(SAVED_SESSIONS_PATH, filename), buf, function(e) {
|
|
111
112
|
!e && saveData({ type: 'savedData', filename: filename, buffer: buf } );
|
|
112
|
-
cb(e);
|
|
113
|
+
cb(e, filename.substring(filename.indexOf('/') + 1));
|
|
113
114
|
});
|
|
114
115
|
});
|
|
115
116
|
});
|
|
@@ -415,8 +416,8 @@ function sessionsHandler() {
|
|
|
415
416
|
res.json({ec: 0});
|
|
416
417
|
});
|
|
417
418
|
app.post('/cgi-bin/saved/save', jsonParser, function(req, res) {
|
|
418
|
-
saveSessions(req.body, function(err) {
|
|
419
|
-
res.json({ec: err ? 2 : 0, em: err ? err.message || 'Error' : undefined});
|
|
419
|
+
saveSessions(req.body, function(err, filename) {
|
|
420
|
+
res.json({ec: err ? 2 : 0, em: err ? err.message || 'Error' : undefined, filename: filename});
|
|
420
421
|
});
|
|
421
422
|
});
|
|
422
423
|
app.post('/cgi-bin/composer', jsonParser, composer.handleRequest);
|
package/lib/service/util.js
CHANGED
|
@@ -77,7 +77,7 @@ function getBodyBuffer(data) {
|
|
|
77
77
|
}
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
-
function
|
|
80
|
+
function getRawReq(req) {
|
|
81
81
|
removeEncodingFields(req.headers);
|
|
82
82
|
var headers = getHeadersRaw(req.headers, req.rawHeaderNames);
|
|
83
83
|
var url = String(req.url || '').replace(/^ws/, 'http');
|
|
@@ -85,9 +85,9 @@ function getReqRaw(req) {
|
|
|
85
85
|
return decodeRaw(headers, req);
|
|
86
86
|
}
|
|
87
87
|
|
|
88
|
-
exports.
|
|
88
|
+
exports.getRawReq = getRawReq;
|
|
89
89
|
|
|
90
|
-
function
|
|
90
|
+
function getRawRes(res) {
|
|
91
91
|
removeEncodingFields(res.headers);
|
|
92
92
|
var headers = getHeadersRaw(res.headers, res.rawHeaderNames);
|
|
93
93
|
var statusCode = res.statusCode === 'aborted' ? 502 : res.statusCode;
|
|
@@ -98,7 +98,7 @@ function getResRaw(res) {
|
|
|
98
98
|
return decodeRaw(headers, res);
|
|
99
99
|
}
|
|
100
100
|
|
|
101
|
-
exports.
|
|
101
|
+
exports.getRawRes = getRawRes;
|
|
102
102
|
|
|
103
103
|
var BODY_SEP = Buffer.from('\r\n\r\n');
|
|
104
104
|
|
|
@@ -425,23 +425,13 @@ function parseFrames(res, content, callback) {
|
|
|
425
425
|
exports.parseFrames = parseFrames;
|
|
426
426
|
|
|
427
427
|
var MAX_SESSIONS_FILES = 2000;
|
|
428
|
-
var SAVED_SESSIONS_FILE_RE = /_([1-9]\d*)_(\d+)$/;
|
|
429
428
|
var DIR_RE = /^\d{6}$/;
|
|
430
429
|
|
|
431
|
-
exports.SAVED_SESSIONS_FILE_RE = SAVED_SESSIONS_FILE_RE;
|
|
432
|
-
|
|
433
430
|
function getFileList(files) {
|
|
434
431
|
var result = [];
|
|
435
432
|
files.forEach(function(file, i) {
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
var time = RegExp.$2;
|
|
439
|
-
result.push({
|
|
440
|
-
filename: file.slice(0, - time.length - count.length - 2),
|
|
441
|
-
count: +count,
|
|
442
|
-
time: +time
|
|
443
|
-
});
|
|
444
|
-
}
|
|
433
|
+
file = common.getSavedFileItem(file);
|
|
434
|
+
file && result.push(file);
|
|
445
435
|
});
|
|
446
436
|
return result;
|
|
447
437
|
}
|
package/lib/socket-mgr.js
CHANGED
|
@@ -584,7 +584,7 @@ function handleWsReceive(ctx, resTrans, receiveStatus, handleTransform, frameCtx
|
|
|
584
584
|
|
|
585
585
|
function getContext(req, res, hasEvent, sendStatus, receiveStatus, noDecompress) {
|
|
586
586
|
var reqId = req.reqId;
|
|
587
|
-
var ctx =
|
|
587
|
+
var ctx = conns[reqId] = {
|
|
588
588
|
customParser: req.customParser,
|
|
589
589
|
req: req,
|
|
590
590
|
res: res,
|
|
@@ -601,7 +601,7 @@ function getContext(req, res, hasEvent, sendStatus, receiveStatus, noDecompress)
|
|
|
601
601
|
setReceiveStatus: function (status) {
|
|
602
602
|
setConnStatus(ctx, status, receiveStatus);
|
|
603
603
|
}
|
|
604
|
-
}
|
|
604
|
+
};
|
|
605
605
|
initStatus(ctx, req.enable);
|
|
606
606
|
return ctx;
|
|
607
607
|
}
|
|
@@ -718,9 +718,21 @@ exports.handleUpgrade = function (req, res) {
|
|
|
718
718
|
hasEvent && proxy.emit('wsRequest', url);
|
|
719
719
|
cb(null, chunk);
|
|
720
720
|
};
|
|
721
|
-
|
|
721
|
+
var ctx = false;
|
|
722
|
+
if (!hide || frameCtx) {
|
|
723
|
+
ctx = getContext(
|
|
724
|
+
req,
|
|
725
|
+
res,
|
|
726
|
+
hasEvent,
|
|
727
|
+
sendStatus,
|
|
728
|
+
receiveStatus,
|
|
729
|
+
noDecompress
|
|
730
|
+
);
|
|
731
|
+
ctx.hideFrame = req.hideFrame = hideFrame;
|
|
732
|
+
}
|
|
733
|
+
options.ctx = ctx;
|
|
734
|
+
if (!ctx || customParser) {
|
|
722
735
|
reqTrans._transform = resTrans._transform = handleTransform;
|
|
723
|
-
options.ctx = false;
|
|
724
736
|
} else {
|
|
725
737
|
reqTrans.headers = resTrans.headers = res.headers;
|
|
726
738
|
if (reqWrite) {
|
|
@@ -731,15 +743,6 @@ exports.handleUpgrade = function (req, res) {
|
|
|
731
743
|
resWrite.headers = res.headers;
|
|
732
744
|
req.pipeWriter = resWrite;
|
|
733
745
|
}
|
|
734
|
-
var ctx = options.ctx = (conns[reqId] = getContext(
|
|
735
|
-
req,
|
|
736
|
-
res,
|
|
737
|
-
hasEvent,
|
|
738
|
-
sendStatus,
|
|
739
|
-
receiveStatus,
|
|
740
|
-
noDecompress
|
|
741
|
-
));
|
|
742
|
-
ctx.hideFrame = req.hideFrame = hideFrame;
|
|
743
746
|
handleWsSend(ctx, reqTrans, sendStatus, handleTransform, frameCtx);
|
|
744
747
|
handleWsReceive(ctx, resTrans, receiveStatus, handleTransform, frameCtx);
|
|
745
748
|
cleanCacheFrames(ctx, options);
|
|
@@ -798,9 +801,14 @@ exports.handleConnect = function (req, res, isUpgrade) {
|
|
|
798
801
|
if (req._hasClosed) {
|
|
799
802
|
return;
|
|
800
803
|
}
|
|
801
|
-
|
|
804
|
+
var ctx = false;
|
|
805
|
+
if (!hide || frameCtx) {
|
|
806
|
+
ctx = getContext(req, res, hasEvent, sendStatus, receiveStatus);
|
|
807
|
+
ctx.hideFrame = req.hideFrame = hideFrame;
|
|
808
|
+
}
|
|
809
|
+
options.ctx = ctx;
|
|
810
|
+
if (!ctx || customParser) {
|
|
802
811
|
reqTrans._transform = resTrans._transform = handleTransform;
|
|
803
|
-
options.ctx = false;
|
|
804
812
|
} else {
|
|
805
813
|
req.wsExts = res.wsExts = reqTrans.wsExts = resTrans.wsExts = '';
|
|
806
814
|
if (reqWrite) {
|
|
@@ -811,8 +819,6 @@ exports.handleConnect = function (req, res, isUpgrade) {
|
|
|
811
819
|
resWrite.wsExts = '';
|
|
812
820
|
req.pipeWriter = resWrite;
|
|
813
821
|
}
|
|
814
|
-
var ctx = options.ctx = getContext(req, res, hasEvent, sendStatus, receiveStatus);
|
|
815
|
-
ctx.hideFrame = req.hideFrame = hideFrame;
|
|
816
822
|
if (reqRead && reqWrite) {
|
|
817
823
|
handleWsSend(ctx, reqTrans, sendStatus, handleTransform, frameCtx, eventName);
|
|
818
824
|
} else {
|