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.
Files changed (52) hide show
  1. package/assets/menu.html +2 -2
  2. package/assets/modal.html +2 -2
  3. package/assets/tab.html +2 -2
  4. package/bin/api.js +545 -0
  5. package/bin/import.js +3 -3
  6. package/bin/plugin.js +4 -8
  7. package/bin/use.js +22 -8
  8. package/bin/util.js +10 -5
  9. package/bin/whistle.js +11 -1
  10. package/biz/webui/cgi-bin/abort.js +14 -5
  11. package/biz/webui/cgi-bin/frames.js +12 -0
  12. package/biz/webui/cgi-bin/is-enabled-https.js +6 -0
  13. package/biz/webui/cgi-bin/plugins/disable-plugin.js +16 -7
  14. package/biz/webui/cgi-bin/plugins/list.js +17 -0
  15. package/biz/webui/cgi-bin/plugins/plugin.js +21 -0
  16. package/biz/webui/cgi-bin/plugins/status.js +21 -0
  17. package/biz/webui/cgi-bin/rules/is-multi-select.js +7 -0
  18. package/biz/webui/cgi-bin/rules/move-top.js +11 -0
  19. package/biz/webui/cgi-bin/rules/select.js +1 -1
  20. package/biz/webui/cgi-bin/rules/select2.js +16 -0
  21. package/biz/webui/cgi-bin/rules/status.js +6 -0
  22. package/biz/webui/cgi-bin/rules/unselect.js +3 -2
  23. package/biz/webui/cgi-bin/rules/unselect2.js +18 -0
  24. package/biz/webui/cgi-bin/rules/value.js +19 -0
  25. package/biz/webui/cgi-bin/sessions.js +6 -0
  26. package/biz/webui/cgi-bin/util.js +14 -0
  27. package/biz/webui/htdocs/index.html +1 -1
  28. package/biz/webui/htdocs/js/index.js +32 -32
  29. package/biz/webui/lib/index.js +1 -3
  30. package/lib/https/index.js +4 -4
  31. package/lib/init.js +1 -0
  32. package/lib/inspectors/data.js +6 -4
  33. package/lib/inspectors/req.js +1 -2
  34. package/lib/inspectors/res.js +6 -10
  35. package/lib/plugins/index.js +2 -2
  36. package/lib/plugins/load-plugin.js +17 -6
  37. package/lib/rules/util.js +20 -10
  38. package/lib/service/composer.js +7 -22
  39. package/lib/service/data-center.js +0 -12
  40. package/lib/service/generate-saz.js +2 -2
  41. package/lib/service/service.js +6 -5
  42. package/lib/service/util.js +6 -16
  43. package/lib/socket-mgr.js +23 -17
  44. package/lib/tunnel.js +7 -17
  45. package/lib/upgrade.js +4 -8
  46. package/lib/util/common.js +75 -9
  47. package/lib/util/data-server.js +273 -0
  48. package/lib/util/index.js +8 -22
  49. package/lib/util/patch.js +2 -6
  50. package/lib/util/speed-transform.js +17 -6
  51. package/lib/util/whistle-transform.js +18 -7
  52. package/package.json +10 -7
@@ -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 && SPECIAL_PATHS.indexOf(req.path) !== -1 &&
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);
@@ -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
@@ -49,6 +49,7 @@ function addErrorEvents(req, res) {
49
49
  }
50
50
  countdown();
51
51
  req._hasError = true;
52
+ util.clearDelayTimer(req);
52
53
  clientReq = req._clientReq || clientReq;
53
54
  if (clientReq) {
54
55
  if (clientReq.destroy) {
@@ -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 (msg !== 'Aborted') {
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.delay(util.getMatcherValue(req.rules.reqDelay), function () {
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
  };
@@ -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;
@@ -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
  );
@@ -516,8 +516,8 @@ var delayTimer;
516
516
 
517
517
  function refreshPlugins() {
518
518
  updating = true;
519
- delayTimer && clearTimeout(delayTimer);
520
- updateTimer && clearTimeout(updateTimer);
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
- var rawData = 'HTTP/1.1 ' + code + ' ' + (msg || svrRes.statusMessage || STATUS_CODES[code] || '');
2257
- if (headers = headers && getRawHeaders(formatRawHeaders(headers, svrRes))) {
2258
- rawData += '\r\n' + headers;
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
- all = all || [file];
170
- all.forEach(function(name) {
171
- var index = selectedList.indexOf(name);
172
- if (index != -1) {
173
- selectedList.splice(index, 1);
174
- hasChanged = true;
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: !!propertiesStorage.getProperty('allowMultipleChoice'),
351
+ allowMultipleChoice: allowMultipleChoice(),
342
352
  list: list
343
353
  };
344
354
  },
@@ -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: !!data.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
- !item.enableProxyRules !== result.enableProxyRules
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(getReqRaw(options));
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
- timer && clearTimeout(timer);
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
- if (reqBody.enableProxyRules === false || isTest) {
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.getReqRaw(item.req);
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.getResRaw(item.res);
131
+ : util.getRawRes(item.res);
132
132
  var name = getName();
133
133
  item.index = index;
134
134
  zip.addFile('raw/' + name + '_c.txt', req);
@@ -96,12 +96,13 @@ function getFilename(filename, time, count) {
96
96
  }
97
97
 
98
98
  function saveSessions(data, cb) {
99
- var count = Array.isArray(data.sessions) && data.sessions.length;
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(data.sessions), function(err, buf) {
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);
@@ -77,7 +77,7 @@ function getBodyBuffer(data) {
77
77
  }
78
78
  }
79
79
 
80
- function getReqRaw(req) {
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.getReqRaw = getReqRaw;
88
+ exports.getRawReq = getRawReq;
89
89
 
90
- function getResRaw(res) {
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.getResRaw = getResRaw;
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
- if (SAVED_SESSIONS_FILE_RE.test(file)) {
437
- var count = RegExp.$1;
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 = (conns[reqId] = {
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
- if (hideFrame && !frameCtx) {
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
- if (hideFrame && !frameCtx) {
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 {