whistle 2.10.1 → 2.10.2

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.
@@ -98,6 +98,7 @@ var FILE_PROTO_RE = /^x?((raw)?file|tpl|jsonp|dust):\/\//;
98
98
  var NO_PROTO_RE = /[^\w!*|.-]/;
99
99
  var SKIP_RE = /^skip:\/\//;
100
100
  var SUB_VAR_RE = /\$\{RegExp\.\$([&\d])\}/g;
101
+ var TOOL_RE = /^(?:log|weinre):\/\//;
101
102
  var mIndex = 0;
102
103
  var mNow = Date.now();
103
104
  var IS_JSON = Symbol('isJson');
@@ -799,18 +800,12 @@ function getValueFor(key, vals, file) {
799
800
  return val;
800
801
  }
801
802
 
802
- function getRule(req, list, vals, index, isFilter, host) {
803
- var rule = resolveRuleList(req, list, vals, index || 0, isFilter, null, host);
803
+ function getRule(req, list, vals, index, isFilter, host, isReq) {
804
+ var rule = resolveRuleList(req, list, vals, index || 0, isFilter, null, host, isReq);
804
805
  resolveValue(rule, vals, req);
805
806
  return rule;
806
807
  }
807
808
 
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
809
  function resolveValue(rule, vals, req) {
815
810
  if (!rule) {
816
811
  return;
@@ -924,7 +919,7 @@ function checkInternal(req, rule) {
924
919
  return props.internalOnly;
925
920
  }
926
921
 
927
- function resolveRuleList(req, list, vals, index, isFilter, isEnableProxy, host) {
922
+ function resolveRuleList(req, list, vals, index, isFilter, isEnableProxy, host, isReq) {
928
923
  var curUrl = util.formatUrl(req.curUrl);
929
924
  var notHttp = list.isRuleProto && curUrl[0] !== 'h';
930
925
  //支持域名匹配
@@ -986,6 +981,9 @@ function resolveRuleList(req, list, vals, index, isFilter, isEnableProxy, host)
986
981
  if (notHttp && protoMgr.isFileProxy(rule.matcher)) {
987
982
  return false;
988
983
  }
984
+ if (isReq && TOOL_RE.test(rule.matcher)) {
985
+ return true;
986
+ }
989
987
  return (isFilter || !matchExcludeFilters(curUrl, rule, req)) && (host == null || util.checkProxyHost(rule, host));
990
988
  };
991
989
 
@@ -1155,7 +1153,7 @@ function resolveProps(req, rules, vals, isIgnore) {
1155
1153
  return result;
1156
1154
  }
1157
1155
  }
1158
- return util.resolveProperties(list, result);
1156
+ return util.parseRuleProps(list, result);
1159
1157
  }
1160
1158
 
1161
1159
  function parseWildcard(pattern, not) {
@@ -1967,7 +1965,7 @@ function matchFilter(url, filter, req) {
1967
1965
  return false;
1968
1966
  }
1969
1967
 
1970
- function matchExcludeFilters(url, rule, options) {
1968
+ function matchExcludeFilters(url, rule, req) {
1971
1969
  var filters = rule.filters;
1972
1970
  if (!filters) {
1973
1971
  return;
@@ -1980,7 +1978,7 @@ function matchExcludeFilters(url, rule, options) {
1980
1978
  hasIncludeFilter = hasIncludeFilter || filter.isInclude;
1981
1979
  if (
1982
1980
  (filter.isInclude ? !include : !exclude) &&
1983
- matchFilter(url, filter, options)
1981
+ matchFilter(url, filter, req)
1984
1982
  ) {
1985
1983
  if (filter.isInclude) {
1986
1984
  include = true;
@@ -2249,7 +2247,7 @@ function resolveRules(req, isReq, isRes) {
2249
2247
  name === 'rule' ||
2250
2248
  name === 'plugin' ||
2251
2249
  !filter[name]) &&
2252
- (rule = self.getRule(req, rules[name], vals))
2250
+ (rule = self.getRule(req, rules[name], vals, null, null, null, isReq))
2253
2251
  ) {
2254
2252
  _rules[name] = rule;
2255
2253
  }
@@ -2283,15 +2281,17 @@ function resolveRules(req, isReq, isRes) {
2283
2281
  return _rules;
2284
2282
  }
2285
2283
 
2286
- proto.getRule = function(req, list, vals, index, isFilter, host) {
2284
+ proto.getRule = function(req, list, vals, index, isFilter, host, isReq) {
2287
2285
  if (!this._isGlobal || !req._disabledProxyRules) {
2288
- return getRule(req, list, vals, index, isFilter, host);
2286
+ return getRule(req, list, vals, index, isFilter, host, isReq);
2289
2287
  }
2290
2288
  };
2291
2289
 
2292
2290
  proto.getRuleList = function(req, list, vals, isEnableProxy) {
2293
2291
  if (!this._isGlobal || !req._disabledProxyRules) {
2294
- return getRuleList(req, list, vals, isEnableProxy);
2292
+ return resolveRuleList(req, list, vals, null, false, isEnableProxy).map(function (rule) {
2293
+ return resolveValue(rule, vals, req);
2294
+ });
2295
2295
  }
2296
2296
  return [];
2297
2297
  };
@@ -2341,8 +2341,8 @@ proto.resolveProxyProps = function (req) {
2341
2341
  }
2342
2342
  mergeRule(req.rules, enable, 'enable');
2343
2343
  mergeRule(req.rules, disable, 'disable');
2344
- enable = util.resolveProperties(enable);
2345
- disable = util.resolveProperties(disable);
2344
+ enable = util.parseRuleProps(enable);
2345
+ disable = util.parseRuleProps(disable);
2346
2346
  if (disable.clientId || disable.clientID || disable.clientid) {
2347
2347
  req.disable.clientId = true;
2348
2348
  }
@@ -2417,7 +2417,7 @@ proto.hasReqScript = function (req) {
2417
2417
  : this.getRule(req, this._rules.rulesFile, this._values);
2418
2418
  };
2419
2419
 
2420
- proto.resolveProxy = function resolveProxy(req, host) {
2420
+ proto.resolveProxy = function (req, host) {
2421
2421
  var proxy = this.getRule(req, this._rules.proxy, this._values, null, null, host);
2422
2422
  var matcher = proxy && proxy.matcher;
2423
2423
  var name = matcher && matcher.substring(0, matcher.indexOf(':'));
@@ -1,6 +1,6 @@
1
1
  var MAX_LENGTH = 800;
2
2
  var MIN_LENGTH = 720;
3
- var SIZE = 1024 * 64;
3
+ var SIZE = 1024 * 512;
4
4
  var COUNT = 100;
5
5
  var logIndex = 0;
6
6
  var logs = [];
@@ -45,40 +45,43 @@ function getLogs(startTime, count, logId) {
45
45
  return sliceLogs(0, count, logId);
46
46
  }
47
47
 
48
- module.exports = function init(proxy) {
49
- proxy.addLog = function set(log) {
50
- if (!log) {
51
- return;
52
- }
48
+ function getLogIndex() {
49
+ ++logIndex;
50
+ if (logIndex > 999999) {
51
+ logIndex = 0;
52
+ }
53
+ return logIndex;
54
+ }
53
55
 
54
- var now = Date.now();
55
- var text = log.text;
56
- if (text == null) {
57
- text = '';
58
- } else if (typeof text != 'string') {
59
- text += '';
60
- }
61
- var overflow = text.length - SIZE;
62
- logs.push({
63
- id: now + '-' + ++logIndex,
64
- logId: log.id,
65
- date: (log.t && parseInt(log.t, 10)) || now,
66
- level: LEVEL_RE.test(log.level)
56
+ exports.addLog = function set(log) {
57
+ if (!log) {
58
+ return;
59
+ }
60
+
61
+ var now = Date.now();
62
+ var text = log.text;
63
+ if (text == null) {
64
+ text = '';
65
+ } else if (typeof text != 'string') {
66
+ text += '';
67
+ }
68
+ var overflow = text.length - SIZE;
69
+ logs.push({
70
+ id: now + '-' + getLogIndex(),
71
+ logId: log.id,
72
+ date: (log.t && parseInt(log.t, 10)) || now,
73
+ level: LEVEL_RE.test(log.level)
67
74
  ? log.level
68
75
  : 'info',
69
- text: overflow > 9 ? text.substring(0, SIZE) + '...(' + overflow + ')' : text
70
- });
71
- var len = logs.length;
72
- if (len > MAX_LENGTH) {
73
- logs = logs.slice(len - MIN_LENGTH, len);
74
- if (logIndex > 100000) {
75
- logIndex = 0;
76
- }
77
- }
78
- };
79
- proxy.getLogs = getLogs;
80
- proxy.getLatestId = function () {
81
- var last = logs[logs.length - 1];
82
- return last && last.id;
83
- };
76
+ text: overflow > 9 ? text.substring(0, SIZE) + '...(' + overflow + ')' : text
77
+ });
78
+ var len = logs.length;
79
+ if (len > MAX_LENGTH) {
80
+ logs = logs.slice(len - MIN_LENGTH, len);
81
+ }
82
+ };
83
+ exports.getLogs = getLogs;
84
+ exports.getLatestId = function () {
85
+ var last = logs[logs.length - 1];
86
+ return last && last.id;
84
87
  };
@@ -170,9 +170,7 @@ var saveData = function(type, data) {
170
170
  method: 'POST',
171
171
  url: 'http://127.0.0.1:' + curOptions.port + '/cgi-bin/service/save',
172
172
  strictMode: true,
173
- headers: {
174
- 'content-type': 'application/json'
175
- },
173
+ headers: { 'content-type': 'application/json' },
176
174
  body: body
177
175
  }, function (err) {
178
176
  if (err) {
@@ -213,7 +211,7 @@ function sendData() {
213
211
  });
214
212
  }
215
213
 
216
- process.nextTick(sendData);
214
+ process.on('whistleStarted', sendData);
217
215
 
218
216
  module.exports = loadService;
219
217
 
@@ -16,6 +16,7 @@ var composer = require('./composer');
16
16
  var handleComposeData = require('./compose-data');
17
17
  var Limiter = require('async-limiter');
18
18
  var common = require('../util/common');
19
+ var logger = require('./console-log');
19
20
 
20
21
  process.env.NODE_TLS_REJECT_UNAUTHORIZED = '1';
21
22
 
@@ -26,7 +27,7 @@ var forwardRequest = dataCenter.forwardRequest;
26
27
 
27
28
  var INSTALL_SCRIPT = path.join(__dirname, 'install.js');
28
29
  var installChild;
29
-
30
+ var LOG_RE = /^(\d+)\r(fatal|error|warn|info|debug|log)\r([^\s]*)\r/;
30
31
  var TEMP_PLUGINS_PATH = path.join(common.getWhistlePath(), '.temp_plugins');
31
32
  var SESSIONS_FILE_RE = /\.(txt|json|saz)$/i;
32
33
  var limiter = new Limiter({ concurrency: 10 });
@@ -37,10 +38,8 @@ var LIMIT_SIZE = 1024 * 1024 * 128;
37
38
  var MAX_TEMP_SIZE = 1024 * 1024 * 12;
38
39
  var MAX_PLUGIN_SIZE = MAX_TEMP_SIZE;
39
40
  var MAX_TEMP_PLUGINS_AGE = 1000 * 60 * 10; // 10 minutes
40
- var TEMP_FILE_RE = /^[\da-f]{64}$/;
41
41
  var CR = '\r';
42
42
  var jsonParser = bodyParser.json({ limit: LIMIT_SIZE });
43
- var urlencodedParser = bodyParser.urlencoded({ extended: true, limit: '1mb'});
44
43
  var PLUGIN_SEP = /\s*,\s*/;
45
44
  var config;
46
45
  var curWhistleId;
@@ -67,6 +66,19 @@ var ensureTempPluginsDir = function() {
67
66
 
68
67
  ensureTempPluginsDir();
69
68
 
69
+ function parseLog(log) {
70
+ if (!log || typeof log !== 'string') {
71
+ return;
72
+ }
73
+ var match = LOG_RE.exec(log);
74
+ return match && {
75
+ t: match[1],
76
+ level: match[2],
77
+ id: match[3],
78
+ text: log.substring(match[0].length)
79
+ };
80
+ }
81
+
70
82
  process.on('data', function(data) {
71
83
  if (data) {
72
84
  if (data.type === 'whistleId') {
@@ -155,7 +167,7 @@ function getTempFiles(list, cb) {
155
167
  }
156
168
  };
157
169
  list = list.forEach(function(filename) {
158
- if (!TEMP_FILE_RE.test(filename)) {
170
+ if (!common.isTempFile(filename)) {
159
171
  return execCb();
160
172
  }
161
173
  filename = path.join(TEMP_FILES_PATH, filename);
@@ -336,7 +348,7 @@ function sessionsHandler() {
336
348
  } catch (e) {}
337
349
  });
338
350
  });
339
- app.post('/cgi-bin/plugins/install', urlencodedParser, function(req, res) {
351
+ app.post('/cgi-bin/plugins/install', bodyParser.urlencoded({ extended: true, limit: '1mb'}), function(req, res) {
340
352
  var plugins = req.body.plugins;
341
353
  var clientId = req.body.clientId;
342
354
  plugins = common.isString(plugins) ? plugins.trim().split(PLUGIN_SEP) : null;
@@ -444,7 +456,7 @@ function sessionsHandler() {
444
456
  });
445
457
  }
446
458
  var filename = req.query.filename;
447
- if (TEMP_FILE_RE.test(filename)) {
459
+ if (common.isTempFile(filename)) {
448
460
  filename = path.join(TEMP_FILES_PATH, filename);
449
461
  }
450
462
  getFile(filename, function(em, data) {
@@ -491,8 +503,12 @@ function sessionsHandler() {
491
503
  }
492
504
  }
493
505
  );
506
+ app.use('/cgi-bin/log/set', function(req, _, next) {
507
+ req.headers['content-type'] = 'application/json';
508
+ next();
509
+ });
494
510
  app.use(bodyParser.urlencoded({ extended: true, limit: LIMIT_SIZE }));
495
- app.use(bodyParser.json());
511
+ app.use(jsonParser);
496
512
  app.use('/cgi-bin/sessions/export', function (req, res) {
497
513
  var body = req.body;
498
514
  var type = body.exportFileType;
@@ -509,6 +525,35 @@ function sessionsHandler() {
509
525
  download(body);
510
526
  });
511
527
  });
528
+
529
+ app.use('/cgi-bin/log/set', function(req, res) {
530
+ res.setHeader('content-type', 'image/png');
531
+ if (req.method === 'POST') {
532
+ var list = req.body.list;
533
+ if (Array.isArray(list)) {
534
+ var len = Math.min(list.length, 20);
535
+ for (var i = 0; i < len; i++) {
536
+ logger.addLog(parseLog(list[i]));
537
+ }
538
+ }
539
+ } else {
540
+ logger.addLog(req.query);
541
+ }
542
+ res.end();
543
+ });
544
+ app.use('/cgi-bin/log/get', function(req, res) {
545
+ var query = req.query;
546
+ var startLogTime = query.startLogTime;
547
+ var init = startLogTime == -4;
548
+ var stopRecordConsole = startLogTime == -3;
549
+ var curLogId = logger.getLatestId();
550
+ common.sendGzip(req, res, {
551
+ ec: 0,
552
+ log: init || stopRecordConsole ? [] : logger.getLogs(startLogTime, query.count, query.logId),
553
+ curLogId: stopRecordConsole ? undefined : curLogId,
554
+ lastLogId: init ? (curLogId || -2) : (stopRecordConsole ? curLogId : undefined)
555
+ });
556
+ });
512
557
  return app;
513
558
  }
514
559
 
package/lib/tunnel.js CHANGED
@@ -47,8 +47,7 @@ function tunnelProxy(server, proxy, type) {
47
47
  var headers = req.headers;
48
48
  if (headers[config.WEBUI_HEAD]) {
49
49
  delete headers[config.WEBUI_HEAD];
50
- reqSocket.destroy();
51
- return;
50
+ return reqSocket.destroy();
52
51
  }
53
52
  req.fromHttpServer = reqSocket.fromHttpServer = fromHttpServer;
54
53
  req.fromHttpsServer = reqSocket.fromHttpsServer = fromHttpsServer;
@@ -83,8 +82,7 @@ function tunnelProxy(server, proxy, type) {
83
82
  var clientInfo = util.parseClientInfo(req);
84
83
  reqSocket._disabledProxyRules = req._disabledProxyRules;
85
84
  reqSocket.clientIp = req.clientIp = util.getClientIp(req, clientInfo[0]);
86
- reqSocket.clientPort = req.clientPort =
87
- clientInfo[1] || util.getClientPort(req);
85
+ reqSocket.clientPort = req.clientPort = clientInfo[1] || util.getClientPort(req);
88
86
  req._remoteAddr = clientInfo[2] || util.getRemoteAddr(req);
89
87
  req._remotePort = clientInfo[3] || util.getRemotePort(req);
90
88
  delete headers[config.CLIENT_PORT_HEADER];
package/lib/upgrade.js CHANGED
@@ -105,7 +105,7 @@ function upgradeHandler(req, socket) {
105
105
  util.addTunnelData(socket, headers);
106
106
  socket._clientId = util.getComposerClientId(headers);
107
107
  var getBuffer = function (method, newHeaders, path) {
108
- var rawData = (method || 'GET') + ' ' + (path || socket.url || req.url) + ' ' + 'HTTP/1.1';
108
+ var rawData = (method || 'GET') + ' ' + (path || socket.url || req.url) + ' HTTP/1.1';
109
109
  newHeaders = formatHeaders(newHeaders || headers, req.rawHeaders);
110
110
  if (newHeaders = getRawHeaders(newHeaders)) {
111
111
  rawData += '\r\n' + newHeaders;
@@ -67,6 +67,73 @@ var PATH_SEP_RE = /[\\/]/;
67
67
  var CUR_PATH_RE = /^\.[\\/]/;
68
68
  var CLIENT_PORT_HEADER = 'x-whistle-client-port';
69
69
  var ALLOW_ACK = 'x-whistle-allow-tunnel-ack';
70
+ var PLUS_RE = /\+/g;
71
+ var TOKEN = '\r\u0000\n\u0003\r';
72
+ var PROP_SEP_RE = /(\\*)([|&]|\\[stnrfv])/g;
73
+ var TEMP_FILE_RE = /^[\da-f]{64}$/;
74
+
75
+ exports.isTempFile = function(str) {
76
+ return TEMP_FILE_RE.test(str);
77
+ };
78
+
79
+ var PROPS_CHAR = {
80
+ s: ' ',
81
+ t: '\t',
82
+ n: '\n',
83
+ r: '\r',
84
+ f: '\f',
85
+ v: '\v'
86
+ };
87
+
88
+ function replaceToken(s, val) {
89
+ return s.split(TOKEN).join(val);
90
+ }
91
+
92
+ exports.parseProps = function(str) {
93
+ return str.replace(PROP_SEP_RE, function(_, slash, val) {
94
+ var isChar = val.length > 1;
95
+ if (isChar) {
96
+ slash += '/';
97
+ val = val.substring(1);
98
+ } else if (!slash) {
99
+ return TOKEN;
100
+ }
101
+ var len = slash.length;
102
+ slash = slash.substring(0, Math.floor(len / 2));
103
+ if (isChar) {
104
+ return slash + (len % 2 ? PROPS_CHAR[val] : val);
105
+ }
106
+ return slash + (len % 2 ? val : TOKEN);
107
+ }).split(TOKEN);
108
+ };
109
+
110
+ var decoder = {
111
+ decodeURIComponent: function (s) {
112
+ s = replaceToken(s, '+');
113
+ return qs.unescape(s);
114
+ }
115
+ };
116
+ var rawDecoder = {
117
+ decodeURIComponent: function (s) {
118
+ return replaceToken(s, '+');
119
+ }
120
+ };
121
+ var rawDecoder2 = {
122
+ decodeURIComponent: function (s) {
123
+ return s;
124
+ }
125
+ };
126
+
127
+ exports.parseQuery = function (str, sep, eq, escape) {
128
+ try {
129
+ if (str.indexOf('+') === -1 || str.indexOf(TOKEN) !== -1) {
130
+ return qs.parse(str, sep, eq, escape ? rawDecoder2 : undefined);
131
+ }
132
+ str = str.replace(PLUS_RE, TOKEN);
133
+ return qs.parse(str, sep, eq, escape ? rawDecoder : decoder);
134
+ } catch (e) {}
135
+ return '';
136
+ };
70
137
 
71
138
  exports.ALLOW_ACK = ALLOW_ACK;
72
139
  exports.CONN_TIMEOUT = CONN_TIMEOUT;
@@ -894,7 +961,6 @@ var DIG_RE = /^([+-]?)([1-9]\d{0,15})$/;
894
961
  var NUM_RE = /^(?:0|[1-9]\d*)$/;
895
962
  var ARR_RE = /\[(0|[1-8]\d{0,15}|9\d{0,14})\]$/;
896
963
  var DOT_RE = /(\\+)\./g;
897
- var CR_RE = /\r/g;
898
964
 
899
965
  function isString(str) {
900
966
  return str && typeof str === 'string';
@@ -963,12 +1029,6 @@ function parseKey(key) {
963
1029
  return list;
964
1030
  }
965
1031
 
966
- function replaceDot(_, slash) {
967
- var len = slash.length;
968
- slash = slash.substring(0, Math.floor(len / 2));
969
- return slash + (len % 2 ? '\r' : '.');
970
- }
971
-
972
1032
  function parseKeys(key) {
973
1033
  if (!isString(key)) {
974
1034
  return key;
@@ -977,13 +1037,17 @@ function parseKeys(key) {
977
1037
  if (key.indexOf('.') === -1) {
978
1038
  return parseKey(key);
979
1039
  }
980
- key = key.replace(DOT_RE, replaceDot);
1040
+ key = key.replace(DOT_RE, function (_, slash) {
1041
+ var len = slash.length;
1042
+ slash = slash.substring(0, Math.floor(len / 2));
1043
+ return slash + (len % 2 ? TOKEN : '.');
1044
+ });
981
1045
  if (key.indexOf('.') === -1) {
982
- return parseKey(key.replace(CR_RE, '.'));
1046
+ return parseKey(replaceToken(key, '.'));
983
1047
  }
984
1048
  var result = [];
985
1049
  key.split('.').forEach(function(k) {
986
- k = parseKey(k.trim().replace(CR_RE, '.'));
1050
+ k = parseKey(replaceToken(k.trim(), '.'));
987
1051
  if (Array.isArray(k)) {
988
1052
  result = result.concat(k);
989
1053
  } else {
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;
@@ -1855,23 +1856,21 @@ function joinPath(root, dir) {
1855
1856
 
1856
1857
  exports.joinPath = joinPath;
1857
1858
 
1858
- function resolveProperties(list, result) {
1859
+ function parseRuleProps(list, result) {
1859
1860
  result = result || {};
1860
1861
  if (list) {
1861
- list
1862
- .map(getMatcherValue)
1863
- .join('|')
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.resolveProperties = resolveProperties;
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
- result = result || {};
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 || protoMgr.resProtocols.indexOf(name) !== -1) {
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
- protoMgr.resProtocols.forEach(merge);
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?)?\.(.+)$/i;
2684
- var RES_COOKIE_RE = /^res\.?C(?:ookies?)?\.(.+)$/i;
2685
- var REQ_BODY_RE = /^req\.?B(?:ody?)?\.(.+)$/i;
2686
- var RES_BODY_RE = /^res\.?B(?:ody?)?\.(.+)$/i;
2687
- var COOKIE_RE = /^cookies?\.(.+)$/i;
2688
- var QUERY_RE = /^(?:query|params|url\.?Params?)\.(.+)$/i;
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 (!keys || !keys.length) {
2770
- return;
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) {
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.1",
4
+ "version": "2.10.2",
5
5
  "dataDirname": ".whistle",
6
6
  "localUIHost": "local.whistlejs.com",
7
7
  "port": 8899,
@@ -1,7 +0,0 @@
1
- var proxy = require('../../lib/proxy');
2
-
3
- module.exports = function(req, res) {
4
- proxy.addLog(req.query);
5
- res.setHeader('content-type', 'image/png');
6
- res.end();
7
- };
@@ -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;