whistle 2.10.9 → 2.10.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/js/log.js +4 -0
- package/bin/api.js +3 -1
- package/bin/util.js +1 -1
- package/bin/whistle.js +5 -0
- package/biz/webui/cgi-bin/get-data.js +0 -1
- package/biz/webui/cgi-bin/init.js +0 -1
- package/biz/webui/cgi-bin/status.js +2 -1
- package/biz/webui/cgi-bin/util.js +1 -1
- package/biz/webui/cgi-bin/values/add.js +15 -13
- package/biz/webui/htdocs/index.html +1 -1
- package/biz/webui/htdocs/js/index.js +50 -51
- package/biz/webui/lib/index.js +39 -30
- package/index.js +10 -12
- package/lib/config.js +25 -79
- package/lib/handlers/file-proxy.js +1 -1
- package/lib/https/ca.js +18 -17
- package/lib/https/h2.js +54 -35
- package/lib/https/index.js +124 -107
- package/lib/inspectors/data.js +9 -3
- package/lib/inspectors/log.js +14 -33
- package/lib/inspectors/req.js +3 -6
- package/lib/inspectors/res.js +2 -5
- package/lib/inspectors/rules.js +11 -6
- package/lib/inspectors/weinre.js +1 -1
- package/lib/plugins/index.js +45 -54
- package/lib/plugins/load-plugin.js +31 -40
- package/lib/rules/dns.js +1 -1
- package/lib/rules/index.js +3 -1
- package/lib/rules/protocols.js +2 -4
- package/lib/rules/rules.js +3 -5
- package/lib/rules/util.js +2 -7
- package/lib/service/compose-data.js +2 -1
- package/lib/service/composer.js +12 -10
- package/lib/service/service.js +3 -5
- package/lib/socket-mgr.js +5 -2
- package/lib/tunnel.js +9 -5
- package/lib/util/common.js +190 -37
- package/lib/util/data-server.js +5 -1
- package/lib/util/drain.js +5 -6
- package/lib/util/file-mgr.js +1 -1
- package/lib/util/http-mgr.js +6 -2
- package/lib/util/index.js +48 -69
- package/lib/util/speed-transform.js +2 -2
- package/lib/util/transproto.js +4 -3
- package/lib/util/whistle-transform.js +2 -2
- package/lib/util/zlib.js +1 -1
- package/package.json +4 -4
package/lib/util/common.js
CHANGED
|
@@ -74,6 +74,13 @@ var PROP_SEP_RE = /(\\*)([|&]|\\[stnrfv])/g;
|
|
|
74
74
|
var TEMP_FILE_RE = /^(?:\/?temp\/)?([\da-f]{64})(?:\.[\w.-]+)?$/;
|
|
75
75
|
var TEMP_FILES_PATH = path.join(getWhistlePath(), 'temp_files');
|
|
76
76
|
var SAVED_SESSIONS_FILE_RE = /_([1-9]\d*)_(\d+)$/;
|
|
77
|
+
var REG_EXP_RE = /^\/(.+)\/(i?u?|ui)$/;
|
|
78
|
+
|
|
79
|
+
function isRegExp(regExp) {
|
|
80
|
+
return REG_EXP_RE.test(regExp);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
exports.isRegExp = isRegExp;
|
|
77
84
|
|
|
78
85
|
exports.getSavedFileItem = function(filename) {
|
|
79
86
|
var result = SAVED_SESSIONS_FILE_RE.exec(filename);
|
|
@@ -469,13 +476,22 @@ exports.addTrailerNames = function (
|
|
|
469
476
|
});
|
|
470
477
|
};
|
|
471
478
|
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
if (state.endEmitted) {
|
|
479
|
+
function onReadEnd(stream, callback) {
|
|
480
|
+
if (stream.readableEnded) {
|
|
475
481
|
return callback();
|
|
476
482
|
}
|
|
477
|
-
|
|
478
|
-
}
|
|
483
|
+
stream.once('end', callback);
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
function onWriteEnd(stream, callback) {
|
|
487
|
+
if (stream.writableFinished) {
|
|
488
|
+
return callback();
|
|
489
|
+
}
|
|
490
|
+
stream.once('finish', callback);
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
exports.onReadEnd = onReadEnd;
|
|
494
|
+
exports.onWriteEnd = onWriteEnd;
|
|
479
495
|
|
|
480
496
|
var UPGRADE_RE = /^\s*upgrade\s*$/i;
|
|
481
497
|
var WS_RE = /^\s*websocket\s*$/i;
|
|
@@ -725,7 +741,7 @@ function readStream(stream, callback) {
|
|
|
725
741
|
stream.on('data', function(chunk) {
|
|
726
742
|
buffer.push(chunk);
|
|
727
743
|
});
|
|
728
|
-
stream
|
|
744
|
+
onReadEnd(stream, function() {
|
|
729
745
|
var buf;
|
|
730
746
|
var text;
|
|
731
747
|
var json;
|
|
@@ -899,12 +915,11 @@ exports.onSocketEnd = function(socket, callback) {
|
|
|
899
915
|
callback = null;
|
|
900
916
|
}
|
|
901
917
|
};
|
|
902
|
-
if (socket.aborted || socket.destroyed || socket._hasError) {
|
|
918
|
+
if (socket.aborted || socket.destroyed || socket.closed || socket._hasError) {
|
|
903
919
|
return execCallback();
|
|
904
920
|
}
|
|
905
921
|
socket.on('error', execCallback);
|
|
906
922
|
socket.once('close', execCallback);
|
|
907
|
-
socket.once('end', execCallback);
|
|
908
923
|
socket.once('timeout', execCallback);
|
|
909
924
|
};
|
|
910
925
|
|
|
@@ -1579,6 +1594,14 @@ function safeEncodeURIComponent(ch) {
|
|
|
1579
1594
|
return ch;
|
|
1580
1595
|
}
|
|
1581
1596
|
|
|
1597
|
+
function safeDecodeURIComponent(str) {
|
|
1598
|
+
try {
|
|
1599
|
+
return decodeURIComponent(str);
|
|
1600
|
+
} catch (e) {}
|
|
1601
|
+
|
|
1602
|
+
return str;
|
|
1603
|
+
}
|
|
1604
|
+
|
|
1582
1605
|
exports.safeEncodeURIComponent = safeEncodeURIComponent;
|
|
1583
1606
|
|
|
1584
1607
|
/**
|
|
@@ -1889,36 +1912,46 @@ exports.connectInner = function (options, cb, config) {
|
|
|
1889
1912
|
auth = 'Basic ' + auth.toString('base64');
|
|
1890
1913
|
setRawHeader(headers, 'proxy-authorization', auth);
|
|
1891
1914
|
}
|
|
1915
|
+
var req;
|
|
1892
1916
|
var timer = setTimeout(function () {
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
req.destroy();
|
|
1896
|
-
req.socket && req.socket.destroy();
|
|
1897
|
-
}
|
|
1917
|
+
req.emit('error', TIMEOUT_ERR);
|
|
1918
|
+
req.destroy();
|
|
1898
1919
|
}, CONN_TIMEOUT);
|
|
1899
|
-
var
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
.on('connect', function (res, socket) {
|
|
1920
|
+
var clearTimer = function (err) {
|
|
1921
|
+
if (timer) {
|
|
1922
|
+
err && req.destroy();
|
|
1903
1923
|
clearTimeout(timer);
|
|
1904
|
-
|
|
1905
|
-
|
|
1924
|
+
timer = null;
|
|
1925
|
+
}
|
|
1926
|
+
};
|
|
1927
|
+
req = httpModule.request(proxyOptions);
|
|
1928
|
+
req.on('error', clearTimer);
|
|
1929
|
+
req.on('connect', function (res, socket) {
|
|
1930
|
+
if (!timer) {
|
|
1931
|
+
return;
|
|
1932
|
+
}
|
|
1933
|
+
clearTimer();
|
|
1934
|
+
socket.on('error', function() {
|
|
1935
|
+
socket.destroy();
|
|
1936
|
+
});
|
|
1937
|
+
var status = res.statusCode;
|
|
1938
|
+
if (status !== 200) {
|
|
1939
|
+
socket.destroy();
|
|
1940
|
+
process.nextTick(function () {
|
|
1906
1941
|
var err = new Error(
|
|
1907
1942
|
'Tunneling socket could not be established, statusCode=' +
|
|
1908
|
-
|
|
1943
|
+
status
|
|
1909
1944
|
);
|
|
1910
|
-
err.statusCode =
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
cb(socket, res);
|
|
1921
|
-
})
|
|
1945
|
+
err.statusCode = status;
|
|
1946
|
+
req.emit('error', err);
|
|
1947
|
+
});
|
|
1948
|
+
return;
|
|
1949
|
+
}
|
|
1950
|
+
if (res.headers[ALLOW_ACK]) {
|
|
1951
|
+
socket.write('1');
|
|
1952
|
+
}
|
|
1953
|
+
cb(socket, res);
|
|
1954
|
+
})
|
|
1922
1955
|
.end();
|
|
1923
1956
|
return req;
|
|
1924
1957
|
};
|
|
@@ -2052,11 +2085,7 @@ exports.getSessionInfo = function(headers) {
|
|
|
2052
2085
|
var value = data[LAST_RAW_INDEX + index];
|
|
2053
2086
|
if (value) {
|
|
2054
2087
|
rawResult[key] = value;
|
|
2055
|
-
|
|
2056
|
-
result[key] = decodeURIComponent(value);
|
|
2057
|
-
} catch (e) {
|
|
2058
|
-
result[key] = value;
|
|
2059
|
-
}
|
|
2088
|
+
result[key] = safeDecodeURIComponent(value);
|
|
2060
2089
|
}
|
|
2061
2090
|
});
|
|
2062
2091
|
result._ = rawResult;
|
|
@@ -2112,3 +2141,127 @@ function getHttpMeta(f1, f2, f3, headers, rawHeaders) {
|
|
|
2112
2141
|
}
|
|
2113
2142
|
|
|
2114
2143
|
exports.getHttpMeta = getHttpMeta;
|
|
2144
|
+
|
|
2145
|
+
|
|
2146
|
+
var PATTERN_FIELDS = ['url', 'm', 'method', 'reqH', 'reqHeader', 'reqHeaders',
|
|
2147
|
+
'b', 'body', 'reqBody', 's', 'statusCode', 'status', 'resH', 'resHeader', 'resHeaders'];
|
|
2148
|
+
|
|
2149
|
+
function getHeaderKey(key) {
|
|
2150
|
+
return !key || typeof key !== 'string' || /[^\w!#$%&'*+.^`|~-]/.test(key) ? '' : key.toLowerCase();
|
|
2151
|
+
}
|
|
2152
|
+
|
|
2153
|
+
function createFilter(item, name, key) {
|
|
2154
|
+
var protocol = (item.exclude ? 'ex' : 'in') + 'cludeFilter://';
|
|
2155
|
+
name = name ? name + (key ? '.' : ':') : '';
|
|
2156
|
+
key = key ? key + ':' : '';
|
|
2157
|
+
return protocol + name + key + item.value;
|
|
2158
|
+
}
|
|
2159
|
+
|
|
2160
|
+
function wrapRegexp(value, item) {
|
|
2161
|
+
var flags = item.ignoreCase || item.matchCase === false ? 'i' : '';
|
|
2162
|
+
return { value: '/' + value.replace(/\//g, '\\$&') + '/' + flags, exclude: item.exclude};
|
|
2163
|
+
}
|
|
2164
|
+
|
|
2165
|
+
function formatPath(url) {
|
|
2166
|
+
if (/^\^?\/\//.test(url)) {
|
|
2167
|
+
return url;
|
|
2168
|
+
}
|
|
2169
|
+
return url.replace(/^(\^?(?:https?:\/\/|wss?:\/\/)?)([/?.])/, function(all, prefix, flag) {
|
|
2170
|
+
return flag === '/' ? prefix + '**/' : (prefix[0] === '^' ? prefix : '^' + prefix) + '**/**' + flag;
|
|
2171
|
+
});
|
|
2172
|
+
}
|
|
2173
|
+
|
|
2174
|
+
function formatUrlPattern(item) {
|
|
2175
|
+
var value = item.value;
|
|
2176
|
+
var type = item.type;
|
|
2177
|
+
var prefix;
|
|
2178
|
+
if (/^\s*(keyword|contains?)\s*$/i.test(type)) {
|
|
2179
|
+
return wrapRegexp(item.value.replace(/[|/\\{}()[\]^$+?*.]/g, '\\$&'), item);
|
|
2180
|
+
}
|
|
2181
|
+
if (/^\s*regexp?\s*$/i.test(type)) {
|
|
2182
|
+
return wrapRegexp(item.value.replace(/\//g, '\\$&'), item);
|
|
2183
|
+
}
|
|
2184
|
+
if (/^\s*(wildcard|star)\s*$/i.test(type)) {
|
|
2185
|
+
return { value: formatPath(item.value.replace(/^\^*/, '^')), exclude: item.exclude };
|
|
2186
|
+
}
|
|
2187
|
+
if (value[0] === '?') {
|
|
2188
|
+
prefix = '^**/**';
|
|
2189
|
+
} else if (value[0] !== '/' || value[1] === '/' || isRegExp(value)) {
|
|
2190
|
+
return { value: formatPath(value) };
|
|
2191
|
+
}
|
|
2192
|
+
return { value: (prefix || '**') + value };
|
|
2193
|
+
}
|
|
2194
|
+
|
|
2195
|
+
function createPattern(list) {
|
|
2196
|
+
if (!list) {
|
|
2197
|
+
return '';
|
|
2198
|
+
}
|
|
2199
|
+
if (!Array.isArray(list)) {
|
|
2200
|
+
list = [list];
|
|
2201
|
+
}
|
|
2202
|
+
var len = list.length;
|
|
2203
|
+
if (!len) {
|
|
2204
|
+
return '';
|
|
2205
|
+
}
|
|
2206
|
+
var result = [];
|
|
2207
|
+
var urlPattern;
|
|
2208
|
+
var key;
|
|
2209
|
+
var add = function(item, name, key) {
|
|
2210
|
+
var p = createFilter(item, name, key);
|
|
2211
|
+
if (result.indexOf(p) === -1) {
|
|
2212
|
+
result.push(p);
|
|
2213
|
+
}
|
|
2214
|
+
};
|
|
2215
|
+
list.forEach(function(item) {
|
|
2216
|
+
if (!item || !item.value) {
|
|
2217
|
+
return;
|
|
2218
|
+
}
|
|
2219
|
+
var name = item.name || 'url';
|
|
2220
|
+
if (PATTERN_FIELDS.indexOf(name) === -1) {
|
|
2221
|
+
return;
|
|
2222
|
+
}
|
|
2223
|
+
if (typeof item.value !== 'string') {
|
|
2224
|
+
item.value = String(item.value);
|
|
2225
|
+
}
|
|
2226
|
+
if (/\s/.test(item.value)) {
|
|
2227
|
+
return;
|
|
2228
|
+
}
|
|
2229
|
+
switch(name) {
|
|
2230
|
+
case 'url':
|
|
2231
|
+
item = formatUrlPattern(item);
|
|
2232
|
+
if (urlPattern || item.exclude) {
|
|
2233
|
+
add(item);
|
|
2234
|
+
} else {
|
|
2235
|
+
urlPattern = item.value;
|
|
2236
|
+
}
|
|
2237
|
+
return;
|
|
2238
|
+
case 'm':
|
|
2239
|
+
case 'method':
|
|
2240
|
+
return add(item, 'm');
|
|
2241
|
+
case 'reqH':
|
|
2242
|
+
case 'reqHeader':
|
|
2243
|
+
case 'reqHeaders':
|
|
2244
|
+
key = getHeaderKey(item.key);
|
|
2245
|
+
return key && add(item, 'reqH', key);
|
|
2246
|
+
case 'b':
|
|
2247
|
+
case 'body':
|
|
2248
|
+
case 'reqBody':
|
|
2249
|
+
return add(item, 'b');
|
|
2250
|
+
case 's':
|
|
2251
|
+
case 'statusCode':
|
|
2252
|
+
case 'status':
|
|
2253
|
+
return add(item, 's');
|
|
2254
|
+
case 'resH':
|
|
2255
|
+
case 'resHeader':
|
|
2256
|
+
case 'resHeaders':
|
|
2257
|
+
key = getHeaderKey(item.key);
|
|
2258
|
+
return key && add(item, 'resH', key);
|
|
2259
|
+
}
|
|
2260
|
+
});
|
|
2261
|
+
if (urlPattern || result.length) {
|
|
2262
|
+
result.unshift(urlPattern || '*');
|
|
2263
|
+
}
|
|
2264
|
+
return result.join(' ');
|
|
2265
|
+
}
|
|
2266
|
+
|
|
2267
|
+
exports.createPattern = createPattern;
|
package/lib/util/data-server.js
CHANGED
|
@@ -323,7 +323,7 @@ function handleRequest(req, data) {
|
|
|
323
323
|
delete data.abort;
|
|
324
324
|
}
|
|
325
325
|
};
|
|
326
|
-
|
|
326
|
+
util.onReadEnd(req, removeAbort);
|
|
327
327
|
req.on('error', removeAbort);
|
|
328
328
|
req.on('abort', removeAbort);
|
|
329
329
|
data.version = version;
|
|
@@ -743,6 +743,10 @@ module.exports = function init(_proxy) {
|
|
|
743
743
|
}
|
|
744
744
|
}
|
|
745
745
|
|
|
746
|
+
if (filterType === 'SSE') {
|
|
747
|
+
return rawType === 'text/event-stream';
|
|
748
|
+
}
|
|
749
|
+
|
|
746
750
|
var curType = util.getContentType(rawType);
|
|
747
751
|
for (i = 0, len = TYPES.length; i < len; i++) {
|
|
748
752
|
type = TYPES[i];
|
package/lib/util/drain.js
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
|
-
var
|
|
1
|
+
var common = require('./common');
|
|
2
2
|
|
|
3
|
-
var noop =
|
|
3
|
+
var noop = common.noop;
|
|
4
|
+
var onReadEnd = common.onReadEnd;
|
|
4
5
|
|
|
5
6
|
module.exports = function (stream, endHandler) {
|
|
6
7
|
if (stream._hasAlreadyDrain || (!stream.noReqBody && stream.useH2)) {
|
|
7
8
|
return typeof endHandler == 'function' && endHandler();
|
|
8
9
|
}
|
|
9
10
|
stream._hasAlreadyDrain = true;
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
emitEndStream.on('end', endHandler);
|
|
13
|
-
stream.pipe(emitEndStream);
|
|
11
|
+
onReadEnd(stream, endHandler);
|
|
12
|
+
stream.on('data', noop).on('error', noop);
|
|
14
13
|
};
|
package/lib/util/file-mgr.js
CHANGED
package/lib/util/http-mgr.js
CHANGED
|
@@ -143,7 +143,11 @@ function sendReq(options, callback) {
|
|
|
143
143
|
|
|
144
144
|
var timer, client;
|
|
145
145
|
var handleCallback = function (err, res) {
|
|
146
|
+
if (timer == null) {
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
146
149
|
clearTimeout(timer);
|
|
150
|
+
timer = null;
|
|
147
151
|
if (httpModule) {
|
|
148
152
|
httpModule = null;
|
|
149
153
|
callback(err, res);
|
|
@@ -249,7 +253,7 @@ function request(options, callback) {
|
|
|
249
253
|
handleCallback(err, res, getBody(body, len));
|
|
250
254
|
}
|
|
251
255
|
});
|
|
252
|
-
res.
|
|
256
|
+
res.once('end', function() {
|
|
253
257
|
handleCallback(null, res, getBody(body, len));
|
|
254
258
|
});
|
|
255
259
|
};
|
|
@@ -325,7 +329,7 @@ function readFile(url, callback) {
|
|
|
325
329
|
}
|
|
326
330
|
});
|
|
327
331
|
stream.on('error', listener);
|
|
328
|
-
stream.
|
|
332
|
+
stream.once('end', listener);
|
|
329
333
|
});
|
|
330
334
|
}
|
|
331
335
|
|
package/lib/util/index.js
CHANGED
|
@@ -24,7 +24,7 @@ var ReplacePatternTransform = require('./replace-pattern-transform');
|
|
|
24
24
|
var common = require('./common');
|
|
25
25
|
var proc = require('./process');
|
|
26
26
|
var parseUrl = require('./parse-url');
|
|
27
|
-
var h2Consts =
|
|
27
|
+
var h2Consts = require('http2').constants;
|
|
28
28
|
|
|
29
29
|
var protocols = protoMgr.protocols;
|
|
30
30
|
var resProtocols = protoMgr.resProtocols;
|
|
@@ -39,7 +39,6 @@ var pendingFiles = {};
|
|
|
39
39
|
var localIpCache = new LRU({ max: 120 });
|
|
40
40
|
var LOCALHOST = '127.0.0.1';
|
|
41
41
|
var aliasProtocols = protoMgr.aliasProtocols;
|
|
42
|
-
var CONTEXT = vm.createContext();
|
|
43
42
|
var END_SLASH_RE = /[/\\]$/;
|
|
44
43
|
var GEN_URL_RE = /^\s*(?:https?:)?\/\/\w[^\s]*\s*$/i;
|
|
45
44
|
var CORS_KEY_RE = /^(?:enable|use-credentials|useCredentials|credentials)$/i;
|
|
@@ -50,17 +49,12 @@ var STYLE_START = toBuffer('<style>');
|
|
|
50
49
|
var STYLE_END = toBuffer('</style>');
|
|
51
50
|
var PROXY_RE = /^x?(?:socks|https?-proxy|proxy|internal(?:-https)?-proxy)$/;
|
|
52
51
|
var SEP_RE = /[|&]/;
|
|
53
|
-
var ctxTimer;
|
|
54
52
|
var END_RE = /[/\\]$/;
|
|
55
53
|
var EXPIRED_SEC = -123456;
|
|
56
54
|
var EXP_COOKIE = { maxAge: EXPIRED_SEC, path: '/' };
|
|
57
55
|
var EXP_SECURE_COOKIE = { maxAge: EXPIRED_SEC, path: '/', secure: true };
|
|
58
56
|
var EXP_COOKIE_D = { maxAge: EXPIRED_SEC, path: '/' };
|
|
59
57
|
var EXP_SECURE_COOKIE_D = { maxAge: EXPIRED_SEC, path: '/', secure: true };
|
|
60
|
-
var resetContext = function () {
|
|
61
|
-
ctxTimer = null;
|
|
62
|
-
CONTEXT = vm.createContext();
|
|
63
|
-
};
|
|
64
58
|
var TIMEOUT_ERR = common.TIMEOUT_ERR;
|
|
65
59
|
var SUB_MATCH_RE = /\$[&\d]/;
|
|
66
60
|
var PROTO_NAME_RE = /^([\w.-]+):\/\//;
|
|
@@ -89,6 +83,7 @@ var getMatcher = common.getMatcher;
|
|
|
89
83
|
var getMatcherValue = common.getMatcherValue;
|
|
90
84
|
var getRemoteAddr = common.getRemoteAddr;
|
|
91
85
|
var getRemotePort = common.getRemotePort;
|
|
86
|
+
var isRegExp = common.isRegExp;
|
|
92
87
|
var workerIndex = process.env && process.env.workerIndex;
|
|
93
88
|
var INTERNAL_ID = Date.now().toString(16) + Math.floor(Math.random() * 10000000).toString(16);
|
|
94
89
|
var pluginMgr;
|
|
@@ -175,6 +170,7 @@ exports.PLUGIN_INSPECTOR_CONFIG = Symbol('inspectorConfig');
|
|
|
175
170
|
exports.drain = require('./drain');
|
|
176
171
|
exports.isWin = process.platform === 'win32';
|
|
177
172
|
exports.isUtf8 = isUtf8;
|
|
173
|
+
exports.isRegExp = isRegExp;
|
|
178
174
|
exports.WhistleTransform = require('./whistle-transform');
|
|
179
175
|
exports.ReplacePatternTransform = ReplacePatternTransform;
|
|
180
176
|
exports.replacePattern = replacePattern;
|
|
@@ -425,7 +421,7 @@ exports.compare = compare;
|
|
|
425
421
|
var scriptCache = {};
|
|
426
422
|
var VM_OPTIONS = {
|
|
427
423
|
displayErrors: false,
|
|
428
|
-
timeout:
|
|
424
|
+
timeout: 72
|
|
429
425
|
};
|
|
430
426
|
var MAX_SCRIPT_SIZE = 1024 * 256;
|
|
431
427
|
var MAX_SCRIPT_CACHE_COUNT = 64;
|
|
@@ -471,34 +467,20 @@ function getScript(content) {
|
|
|
471
467
|
return script.script;
|
|
472
468
|
}
|
|
473
469
|
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
if (!ctxTimer) {
|
|
479
|
-
ctxTimer = setTimeout(resetContext, 30000);
|
|
480
|
-
}
|
|
481
|
-
}
|
|
470
|
+
var customConsole = {};
|
|
471
|
+
['fatal', 'error', 'warn', 'info', 'log', 'debug'].forEach(function (level) {
|
|
472
|
+
customConsole[level] = logger[level];
|
|
473
|
+
});
|
|
482
474
|
|
|
483
|
-
exports.
|
|
475
|
+
exports.runInContext = function(script, context) {
|
|
484
476
|
try {
|
|
485
|
-
if (
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
level
|
|
489
|
-
) {
|
|
490
|
-
CONTEXT.console[level] = logger[level];
|
|
491
|
-
});
|
|
492
|
-
Object.keys(context).forEach(function (key) {
|
|
493
|
-
CONTEXT[key] = context[key];
|
|
494
|
-
});
|
|
495
|
-
script.runInContext(CONTEXT, VM_OPTIONS);
|
|
477
|
+
if (script = getScript(script)) {
|
|
478
|
+
context = Object.assign({ console: Object.create(customConsole) }, context);
|
|
479
|
+
script.runInNewContext(context, VM_OPTIONS);
|
|
496
480
|
}
|
|
497
481
|
return true;
|
|
498
482
|
} catch (e) {
|
|
499
483
|
logger.error(e);
|
|
500
|
-
} finally {
|
|
501
|
-
clearContext();
|
|
502
484
|
}
|
|
503
485
|
};
|
|
504
486
|
|
|
@@ -603,14 +585,6 @@ function formatDate(now) {
|
|
|
603
585
|
|
|
604
586
|
exports.formatDate = formatDate;
|
|
605
587
|
|
|
606
|
-
var REG_EXP_RE = /^\/(.+)\/(i?u?|ui)$/;
|
|
607
|
-
|
|
608
|
-
function isRegExp(regExp) {
|
|
609
|
-
return REG_EXP_RE.test(regExp);
|
|
610
|
-
}
|
|
611
|
-
|
|
612
|
-
exports.isRegExp = isRegExp;
|
|
613
|
-
|
|
614
588
|
var ORIG_REG_EXP = /^\/(.+)\/([igmu]{0,4})$/;
|
|
615
589
|
var FLAGS_RE = /[igmu]{2}/;
|
|
616
590
|
|
|
@@ -723,14 +697,13 @@ function isAuthCapture(req) {
|
|
|
723
697
|
|
|
724
698
|
exports.isAuthCapture = isAuthCapture;
|
|
725
699
|
|
|
726
|
-
exports.toRegExp = function
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
regExp = null;
|
|
700
|
+
exports.toRegExp = function(regExp, ignoreCase) {
|
|
701
|
+
if (isRegExp(regExp)) {
|
|
702
|
+
try {
|
|
703
|
+
return new RegExp(RegExp.$1, ignoreCase ? 'i' : RegExp.$2);
|
|
704
|
+
} catch (e) {}
|
|
732
705
|
}
|
|
733
|
-
return
|
|
706
|
+
return null;
|
|
734
707
|
};
|
|
735
708
|
|
|
736
709
|
var isString = common.isString;
|
|
@@ -967,8 +940,6 @@ function getPath(url, noProtocol) {
|
|
|
967
940
|
return url;
|
|
968
941
|
}
|
|
969
942
|
|
|
970
|
-
exports.getPath = getPath;
|
|
971
|
-
|
|
972
943
|
function getFilename(url) {
|
|
973
944
|
if (typeof url == 'string' && (url = getPath(url).trim())) {
|
|
974
945
|
var index = url.lastIndexOf('/');
|
|
@@ -1489,48 +1460,47 @@ function getRawType(data) {
|
|
|
1489
1460
|
|
|
1490
1461
|
exports.getRawType = getRawType;
|
|
1491
1462
|
|
|
1492
|
-
function getContentType(
|
|
1493
|
-
if (
|
|
1494
|
-
|
|
1463
|
+
function getContentType(type) {
|
|
1464
|
+
if (type && typeof type != 'string') {
|
|
1465
|
+
type = type['content-type'] || type.contentType;
|
|
1495
1466
|
}
|
|
1496
|
-
|
|
1497
|
-
if (!
|
|
1467
|
+
type = _getRawType(type);
|
|
1468
|
+
if (!type) {
|
|
1498
1469
|
return;
|
|
1499
1470
|
}
|
|
1500
|
-
if (
|
|
1471
|
+
if (type.indexOf('image/') != -1) {
|
|
1472
|
+
return 'IMG';
|
|
1473
|
+
}
|
|
1474
|
+
if (type.indexOf('javascript') != -1) {
|
|
1501
1475
|
return 'JS';
|
|
1502
1476
|
}
|
|
1503
1477
|
|
|
1504
|
-
if (
|
|
1478
|
+
if (type.indexOf('css') != -1) {
|
|
1505
1479
|
return 'CSS';
|
|
1506
1480
|
}
|
|
1507
1481
|
|
|
1508
|
-
if (
|
|
1482
|
+
if (type.indexOf('html') != -1) {
|
|
1509
1483
|
return 'HTML';
|
|
1510
1484
|
}
|
|
1511
1485
|
|
|
1512
|
-
if (
|
|
1486
|
+
if (type.indexOf('json') != -1) {
|
|
1513
1487
|
return 'JSON';
|
|
1514
1488
|
}
|
|
1515
1489
|
|
|
1516
|
-
if (
|
|
1490
|
+
if (type.indexOf('xml') != -1) {
|
|
1517
1491
|
return 'XML';
|
|
1518
1492
|
}
|
|
1519
1493
|
|
|
1520
|
-
if (
|
|
1494
|
+
if (type.indexOf('text/') != -1) {
|
|
1521
1495
|
return 'TEXT';
|
|
1522
1496
|
}
|
|
1523
|
-
|
|
1524
|
-
if (contentType.indexOf('image/') != -1) {
|
|
1525
|
-
return 'IMG';
|
|
1526
|
-
}
|
|
1527
1497
|
}
|
|
1528
1498
|
|
|
1529
1499
|
exports.getContentType = getContentType;
|
|
1530
1500
|
|
|
1531
|
-
function isText(
|
|
1532
|
-
|
|
1533
|
-
return
|
|
1501
|
+
function isText(type) {
|
|
1502
|
+
type = type && getContentType(type);
|
|
1503
|
+
return type && type !== 'IMG';
|
|
1534
1504
|
}
|
|
1535
1505
|
|
|
1536
1506
|
exports.isText = isText;
|
|
@@ -1654,7 +1624,7 @@ function getPipeIconvStream(headers) {
|
|
|
1654
1624
|
};
|
|
1655
1625
|
|
|
1656
1626
|
res.on('data', resolveCharset);
|
|
1657
|
-
res
|
|
1627
|
+
onReadEnd(res, resolveCharset);
|
|
1658
1628
|
});
|
|
1659
1629
|
|
|
1660
1630
|
pipeStream.addTail(function (src, next) {
|
|
@@ -2649,7 +2619,10 @@ exports.getReqId = function (now) {
|
|
|
2649
2619
|
};
|
|
2650
2620
|
|
|
2651
2621
|
exports.onSocketEnd = common.onSocketEnd;
|
|
2652
|
-
|
|
2622
|
+
|
|
2623
|
+
var onReadEnd = common.onReadEnd;
|
|
2624
|
+
exports.onReadEnd = onReadEnd;
|
|
2625
|
+
exports.onWriteEnd = common.onWriteEnd;
|
|
2653
2626
|
|
|
2654
2627
|
exports.getEmptyRes = function getRes() {
|
|
2655
2628
|
var res = common.createTransform();
|
|
@@ -2983,7 +2956,7 @@ exports.disableReqProps = function (req) {
|
|
|
2983
2956
|
delete headers['user-agent'];
|
|
2984
2957
|
}
|
|
2985
2958
|
|
|
2986
|
-
if (disable.gzip || isEnable(req, 'captureStream')) {
|
|
2959
|
+
if (disable.gzip || disable.zip || isEnable(req, 'captureStream')) {
|
|
2987
2960
|
delete headers['accept-encoding'];
|
|
2988
2961
|
}
|
|
2989
2962
|
|
|
@@ -3623,7 +3596,7 @@ function readOneChunk(stream, callback, timeout) {
|
|
|
3623
3596
|
timer = setTimeout(handler, timeout);
|
|
3624
3597
|
}
|
|
3625
3598
|
stream.on('data', handler);
|
|
3626
|
-
stream
|
|
3599
|
+
onReadEnd(stream, handler);
|
|
3627
3600
|
}
|
|
3628
3601
|
|
|
3629
3602
|
exports.readOneChunk = readOneChunk;
|
|
@@ -4031,3 +4004,9 @@ exports.joinBuffer = function(buf, chunk) {
|
|
|
4031
4004
|
exports.formatBuffer = function(buf, len) {
|
|
4032
4005
|
return Array.isArray(buf) ? Buffer.concat(buf, len) : buf;
|
|
4033
4006
|
};
|
|
4007
|
+
|
|
4008
|
+
exports.endSocket = function (socket) {
|
|
4009
|
+
if (!socket.destroyed && !socket.writableEnded) {
|
|
4010
|
+
socket.end();
|
|
4011
|
+
}
|
|
4012
|
+
};
|
|
@@ -6,11 +6,11 @@ function SpeedTransform(options, req) {
|
|
|
6
6
|
Transform.call(this);
|
|
7
7
|
options = options || {};
|
|
8
8
|
this._req = req;
|
|
9
|
-
var value = parseInt((options.speed * 1000) / 8);
|
|
9
|
+
var value = parseInt((options.speed * 1000) / 8, 10);
|
|
10
10
|
if (value > 0) {
|
|
11
11
|
this._speed = value;
|
|
12
12
|
}
|
|
13
|
-
if ((value = parseInt(options.delay)) > 0) {
|
|
13
|
+
if ((value = parseInt(options.delay, 10)) > 0) {
|
|
14
14
|
this._delay = value;
|
|
15
15
|
}
|
|
16
16
|
}
|
package/lib/util/transproto.js
CHANGED
|
@@ -71,15 +71,15 @@ function Parser() {
|
|
|
71
71
|
}
|
|
72
72
|
var data = parseChunk();
|
|
73
73
|
if (data === false) {
|
|
74
|
-
return self.onEnd
|
|
74
|
+
return self.onEnd();
|
|
75
75
|
}
|
|
76
76
|
if (!data) {
|
|
77
77
|
if (chunk === false) {
|
|
78
78
|
return;
|
|
79
79
|
}
|
|
80
|
-
return self.onContinue
|
|
80
|
+
return self.onContinue();
|
|
81
81
|
}
|
|
82
|
-
self.onData
|
|
82
|
+
self.onData(data);
|
|
83
83
|
self.write(false);
|
|
84
84
|
};
|
|
85
85
|
}
|
|
@@ -91,6 +91,7 @@ exports.getDecodeTransform = function () {
|
|
|
91
91
|
parser.onEnd = function () {
|
|
92
92
|
data && trans.push(data);
|
|
93
93
|
trans.push(null);
|
|
94
|
+
data = null;
|
|
94
95
|
};
|
|
95
96
|
parser.onContinue = function () {
|
|
96
97
|
if (transCb) {
|
|
@@ -9,11 +9,11 @@ var DOCTYPE = Buffer.from('<!DOCTYPE html>\r\n');
|
|
|
9
9
|
function WhistleTransform(options, req) {
|
|
10
10
|
Transform.call(this);
|
|
11
11
|
options = options || {};
|
|
12
|
-
var value = parseInt((options.speed * 1000) / 8);
|
|
12
|
+
var value = parseInt((options.speed * 1000) / 8, 10);
|
|
13
13
|
if (value > 0) {
|
|
14
14
|
this._speed = value;
|
|
15
15
|
}
|
|
16
|
-
if ((value = parseInt(options.delay)) > 0) {
|
|
16
|
+
if ((value = parseInt(options.delay, 10)) > 0) {
|
|
17
17
|
this._delay = value;
|
|
18
18
|
}
|
|
19
19
|
this._noDoctype = options.noDoctype;
|