whistle 2.9.100 → 2.9.101
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/README-en_US.md +1 -1
- package/README.md +1 -1
- package/assets/menu.html +5 -0
- package/assets/modal.html +5 -0
- package/assets/tab.html +5 -0
- package/biz/webui/cgi-bin/compose-data.js +50 -0
- package/biz/webui/cgi-bin/composer.js +71 -37
- package/biz/webui/htdocs/index.html +1 -1
- package/biz/webui/htdocs/js/index.js +21 -21
- package/lib/https/h2.js +15 -11
- package/lib/https/index.js +18 -14
- package/lib/inspectors/data.js +1 -5
- package/lib/inspectors/res.js +4 -1
- package/lib/rules/index.js +132 -65
- package/lib/rules/protocols.js +2 -0
- package/lib/rules/rules.js +12 -3
- package/lib/socket-mgr.js +6 -11
- package/lib/tunnel.js +5 -8
- package/lib/util/index.js +67 -69
- package/package.json +2 -2
package/README-en_US.md
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
[](http://nodejs.org/download/)
|
|
10
10
|
[](https://npmjs.org/package/whistle)
|
|
11
11
|
[](https://www.npmjs.com/package/whistle)
|
|
12
|
-
[](https://www.npmjs.com/package/whistle)
|
|
13
13
|
|
|
14
14
|
[中文](./README.md) · English
|
|
15
15
|
|
package/README.md
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
[](http://nodejs.org/download/)
|
|
11
11
|
[](https://npmjs.org/package/whistle)
|
|
12
12
|
[](https://www.npmjs.com/package/whistle)
|
|
13
|
-
[](https://www.npmjs.com/package/whistle)
|
|
14
14
|
|
|
15
15
|
中文 · [English](./README-en_US.md)
|
|
16
16
|
|
package/assets/menu.html
CHANGED
|
@@ -195,7 +195,12 @@
|
|
|
195
195
|
whistleBridge.copyText = options.copyText;
|
|
196
196
|
whistleBridge.pageId = options.pageId;
|
|
197
197
|
whistleBridge.compose = options.compose;
|
|
198
|
+
whistleBridge.composeInterrupt = options.createComposeInterrupt();
|
|
198
199
|
whistleBridge.decodeBase64 = options.decodeBase64;
|
|
200
|
+
whistleBridge.joinBase64 = options.joinBase64;
|
|
201
|
+
whistleBridge.getReqId = options.getReqId;
|
|
202
|
+
whistleBridge.onComposeData = options.onComposeData;
|
|
203
|
+
whistleBridge.offComposeData = options.offComposeData;
|
|
199
204
|
whistleBridge.importSessions = options.importSessions;
|
|
200
205
|
whistleBridge.exportSessions = options.exportSessions;
|
|
201
206
|
whistleBridge.importMockData = options.importMockData;
|
package/assets/modal.html
CHANGED
|
@@ -18,7 +18,12 @@
|
|
|
18
18
|
whistleBridge.copyText = options.copyText;
|
|
19
19
|
whistleBridge.pageId = options.pageId;
|
|
20
20
|
whistleBridge.compose = options.compose;
|
|
21
|
+
whistleBridge.composeInterrupt = options.createComposeInterrupt();
|
|
21
22
|
whistleBridge.decodeBase64 = options.decodeBase64;
|
|
23
|
+
whistleBridge.joinBase64 = options.joinBase64;
|
|
24
|
+
whistleBridge.getReqId = options.getReqId;
|
|
25
|
+
whistleBridge.onComposeData = options.onComposeData;
|
|
26
|
+
whistleBridge.offComposeData = options.offComposeData;
|
|
22
27
|
whistleBridge.importSessions = options.importSessions;
|
|
23
28
|
whistleBridge.exportSessions = options.exportSessions;
|
|
24
29
|
whistleBridge.importMockData = options.importMockData;
|
package/assets/tab.html
CHANGED
|
@@ -288,7 +288,12 @@
|
|
|
288
288
|
whistleBridge.copyText = options.copyText;
|
|
289
289
|
whistleBridge.pageId = options.pageId;
|
|
290
290
|
whistleBridge.compose = options.compose;
|
|
291
|
+
whistleBridge.composeInterrupt = options.createComposeInterrupt();
|
|
291
292
|
whistleBridge.decodeBase64 = options.decodeBase64;
|
|
293
|
+
whistleBridge.joinBase64 = options.joinBase64;
|
|
294
|
+
whistleBridge.getReqId = options.getReqId;
|
|
295
|
+
whistleBridge.onComposeData = options.onComposeData;
|
|
296
|
+
whistleBridge.offComposeData = options.offComposeData;
|
|
292
297
|
whistleBridge.importSessions = options.importSessions;
|
|
293
298
|
whistleBridge.exportSessions = options.exportSessions;
|
|
294
299
|
whistleBridge.importMockData = options.importMockData;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
var LRU = require('lru-cache');
|
|
2
|
+
|
|
3
|
+
var cache = new LRU({ max: 100, maxAge: 1000 * 60 });
|
|
4
|
+
var MAX_SIZE = 1024 * 1280;
|
|
5
|
+
|
|
6
|
+
function getData(reqId) {
|
|
7
|
+
return cache.get(reqId);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
exports = module.exports = function(req, res) {
|
|
11
|
+
var ids = req.query.ids;
|
|
12
|
+
var result = {};
|
|
13
|
+
ids = ids && typeof ids === 'string' ? ids.split(',') : ids;
|
|
14
|
+
if (!ids) {
|
|
15
|
+
return res.json(result);
|
|
16
|
+
}
|
|
17
|
+
ids.forEach(function(reqId) {
|
|
18
|
+
var curBuf = getData(reqId);
|
|
19
|
+
if (curBuf) {
|
|
20
|
+
if (curBuf._hasW2End) {
|
|
21
|
+
cache.del(reqId);
|
|
22
|
+
} else {
|
|
23
|
+
cache.set(reqId, '');
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
result[reqId] = curBuf ? curBuf.toString('base64') : curBuf;
|
|
27
|
+
});
|
|
28
|
+
res.json(result);
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
exports.setData = function(reqId, buffer, init) {
|
|
32
|
+
var curBuf = cache.get(reqId);
|
|
33
|
+
if (!init && curBuf == null) {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
if (curBuf) {
|
|
37
|
+
if (buffer && curBuf.length < MAX_SIZE) {
|
|
38
|
+
cache.set(reqId, Buffer.concat([curBuf, buffer]));
|
|
39
|
+
}
|
|
40
|
+
} else {
|
|
41
|
+
cache.set(reqId, buffer || '');
|
|
42
|
+
}
|
|
43
|
+
return true;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
exports.getData = getData;
|
|
47
|
+
|
|
48
|
+
exports.removeData = function(reqId) {
|
|
49
|
+
cache.del(reqId);
|
|
50
|
+
};
|
|
@@ -7,17 +7,17 @@ var extend = require('extend');
|
|
|
7
7
|
var common = require('../../../lib/util/common');
|
|
8
8
|
var config = require('../../../lib/config');
|
|
9
9
|
var util = require('../../../lib/util');
|
|
10
|
-
var zlib = require('../../../lib/util/zlib');
|
|
11
10
|
var properties = require('../../../lib/rules/util').properties;
|
|
12
11
|
var getSender = require('ws-parser').getSender;
|
|
13
12
|
var hparser = require('hparser');
|
|
13
|
+
var composeData = require('./compose-data');
|
|
14
14
|
var sendGzip = require('./util').sendGzip;
|
|
15
15
|
|
|
16
16
|
var formatHeaders = hparser.formatHeaders;
|
|
17
17
|
var getRawHeaders = hparser.getRawHeaders;
|
|
18
18
|
var getRawHeaderNames = hparser.getRawHeaderNames;
|
|
19
19
|
var parseReq = hparser.parse;
|
|
20
|
-
var MAX_LENGTH = 1024 *
|
|
20
|
+
var MAX_LENGTH = 1024 * 2048;
|
|
21
21
|
var MAX_REQ_COUNT = 100;
|
|
22
22
|
var TLS_PROTOS = 'https:,wss:,tls:'.split(',');
|
|
23
23
|
var PROXY_OPTS = {
|
|
@@ -155,8 +155,7 @@ function handleWebSocket(options, cb, count) {
|
|
|
155
155
|
}
|
|
156
156
|
execCb && execCb(null, {
|
|
157
157
|
statusCode: statusCode,
|
|
158
|
-
headers: socket.headers || {}
|
|
159
|
-
body: socket.body || ''
|
|
158
|
+
headers: socket.headers || {}
|
|
160
159
|
});
|
|
161
160
|
}, true);
|
|
162
161
|
}
|
|
@@ -164,7 +163,7 @@ function handleWebSocket(options, cb, count) {
|
|
|
164
163
|
}
|
|
165
164
|
}
|
|
166
165
|
|
|
167
|
-
function handleHttp(options, cb, count) {
|
|
166
|
+
function handleHttp(options, cb, count, reqId) {
|
|
168
167
|
count = getReqCount(count);
|
|
169
168
|
if (options.protocol === 'https:') {
|
|
170
169
|
options.headers[config.HTTPS_FIELD] = 1;
|
|
@@ -182,42 +181,77 @@ function handleHttp(options, cb, count) {
|
|
|
182
181
|
} else {
|
|
183
182
|
options = extend({}, origOpts);
|
|
184
183
|
}
|
|
185
|
-
var client = http.request(options, function(
|
|
186
|
-
if (execCb) {
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
184
|
+
var client = http.request(options, function(svrRes) {
|
|
185
|
+
if (!execCb) {
|
|
186
|
+
return drain(svrRes);
|
|
187
|
+
}
|
|
188
|
+
svrRes.on('error', execCb);
|
|
189
|
+
var buffer;
|
|
190
|
+
var enableStream;
|
|
191
|
+
var unzipStream = util.getUnzipStream(svrRes.headers);
|
|
192
|
+
var timer = reqId && setTimeout(function() {
|
|
193
|
+
composeData.setData(reqId, buffer, true);
|
|
194
|
+
enableStream = true;
|
|
195
|
+
timer = buffer = undefined;
|
|
196
|
+
handleResponse();
|
|
197
|
+
util.onResEnd(svrRes, function() {
|
|
198
|
+
var buf = composeData.getData(reqId);
|
|
199
|
+
if (buf) {
|
|
200
|
+
buf._hasW2End = true;
|
|
201
|
+
} else {
|
|
202
|
+
composeData.removeData(reqId);
|
|
195
203
|
}
|
|
196
204
|
});
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
205
|
+
}, 3000);
|
|
206
|
+
var handleResponse = function() {
|
|
207
|
+
if (buffer === null) {
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
timer && clearTimeout(timer);
|
|
211
|
+
var headers = svrRes.headers;
|
|
212
|
+
if (typeof headers.trailer === 'string' && headers.trailer.indexOf(',') !== -1) {
|
|
213
|
+
headers.trailer = headers.trailer.split(',');
|
|
214
|
+
}
|
|
215
|
+
var result = {
|
|
216
|
+
statusCode: svrRes.statusCode,
|
|
217
|
+
headers: headers,
|
|
218
|
+
trailers: svrRes.trailers,
|
|
219
|
+
rawHeaderNames: getRawHeaderNames(svrRes.rawHeaders),
|
|
220
|
+
rawTrailerNames: getRawHeaderNames(svrRes.rawTrailers),
|
|
221
|
+
reqId: timer ? undefined : reqId
|
|
222
|
+
};
|
|
223
|
+
result.base64 = buffer && buffer.toString('base64');
|
|
224
|
+
execCb(null, result);
|
|
225
|
+
buffer = null;
|
|
226
|
+
};
|
|
227
|
+
if (unzipStream) {
|
|
228
|
+
unzipStream.on('error', function(err) {
|
|
229
|
+
drain(svrRes);
|
|
230
|
+
execCb(err);
|
|
217
231
|
});
|
|
232
|
+
svrRes.pipe(unzipStream);
|
|
218
233
|
} else {
|
|
219
|
-
|
|
234
|
+
unzipStream = svrRes;
|
|
220
235
|
}
|
|
236
|
+
unzipStream.on('data', function(data) {
|
|
237
|
+
if (enableStream) {
|
|
238
|
+
if (!composeData.setData(reqId, data)) {
|
|
239
|
+
enableStream = false;
|
|
240
|
+
drain(svrRes);
|
|
241
|
+
svrRes.unpipe(unzipStream);
|
|
242
|
+
}
|
|
243
|
+
} else if (buffer !== null) {
|
|
244
|
+
buffer = buffer ? Buffer.concat([buffer, data]) : data;
|
|
245
|
+
if (buffer.length > MAX_LENGTH) {
|
|
246
|
+
handleResponse();
|
|
247
|
+
if (unzipStream !== svrRes) {
|
|
248
|
+
drain(svrRes);
|
|
249
|
+
svrRes.unpipe(unzipStream);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
});
|
|
254
|
+
unzipStream.on('end', handleResponse);
|
|
221
255
|
});
|
|
222
256
|
client.on('error', execCb || util.noop);
|
|
223
257
|
client.end(options.body);
|
|
@@ -356,7 +390,7 @@ module.exports = function(req, res) {
|
|
|
356
390
|
} else if (isConn) {
|
|
357
391
|
handleConnect(options, handleResponse, count);
|
|
358
392
|
} else {
|
|
359
|
-
handleHttp(options, handleResponse, count);
|
|
393
|
+
handleHttp(options, handleResponse, count, req.body.reqId);
|
|
360
394
|
}
|
|
361
395
|
if (!handleResponse) {
|
|
362
396
|
res.json({ec: 0, em: 'success'});
|