whistle 2.10.0 → 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.
- package/assets/js/log.js +52 -31
- package/bin/use.js +236 -101
- package/bin/util.js +10 -7
- package/biz/webui/cgi-bin/get-data.js +0 -5
- package/biz/webui/cgi-bin/init.js +0 -2
- package/biz/webui/htdocs/index.html +2 -2
- package/biz/webui/htdocs/js/index.js +51 -50
- package/biz/webui/lib/index.js +18 -3
- package/lib/config.js +3 -0
- package/lib/https/ca.js +8 -9
- package/lib/https/index.js +106 -112
- package/lib/index.js +1 -3
- package/lib/inspectors/log.js +4 -0
- package/lib/inspectors/weinre.js +7 -2
- package/lib/rules/index.js +0 -1
- package/lib/rules/protocols.js +3 -9
- package/lib/rules/rules.js +20 -20
- package/lib/{util/log-server.js → service/console-log.js} +37 -34
- package/lib/service/index.js +2 -4
- package/lib/service/service.js +52 -7
- package/lib/tunnel.js +2 -4
- package/lib/upgrade.js +2 -2
- package/lib/util/common.js +74 -10
- package/lib/util/index.js +24 -36
- package/package.json +1 -1
- package/biz/webui/cgi-bin/log/set.js +0 -7
- package/lib/util/parse-query.js +0 -35
package/biz/webui/lib/index.js
CHANGED
|
@@ -56,7 +56,24 @@ var INSPECTOR_URL = '???_WHISTLE_PLUGIN_INSPECTOR_TAB_' + config.port + '???';
|
|
|
56
56
|
var KEY_RE_G = /\${[^{}\s]+}|{\S+}/g;
|
|
57
57
|
var COMMENT_RE = /#[^\r\n]*$/mg;
|
|
58
58
|
|
|
59
|
+
function hasLogin() {
|
|
60
|
+
return config.username && config.password;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function isTempFile(query) {
|
|
64
|
+
var files = query.files;
|
|
65
|
+
if (files && typeof files === 'string') {
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
return common.isTempFile(query.filename);
|
|
69
|
+
}
|
|
70
|
+
|
|
59
71
|
function sendToService(req, res) {
|
|
72
|
+
if (!hasLogin() && req.path === '/cgi-bin/temp/get' && !isTempFile(req.query)) {
|
|
73
|
+
res.setHeader('Content-Type', 'application/json; charset=utf-8');
|
|
74
|
+
res.end('{"ec":0,"value":"","forbidden":true}');
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
60
77
|
proxyEvent.loadService(function(err, options) {
|
|
61
78
|
if (err) {
|
|
62
79
|
common.sendRes(res, 500, err.stack || err);
|
|
@@ -393,10 +410,8 @@ function cgiHandler(req, res) {
|
|
|
393
410
|
app.all('/service/*', sendToService);
|
|
394
411
|
app.all('/cgi-bin/service/*', sendToService);
|
|
395
412
|
app.all('/cgi-bin/sessions/*', sendToService);
|
|
413
|
+
app.all('/cgi-bin/log/*', sendToService);
|
|
396
414
|
app.post('/cgi-bin/plugins/install', sendToService);
|
|
397
|
-
app.all('/favicon.ico', function(req, res) {
|
|
398
|
-
res.sendFile(htdocs.getImgFile('favicon.ico'));
|
|
399
|
-
});
|
|
400
415
|
|
|
401
416
|
function readPluginPage(req, res, plugin, html, config) {
|
|
402
417
|
res.type('html');
|
package/lib/config.js
CHANGED
|
@@ -153,6 +153,9 @@ config.CUSTOM_PLUGIN_PATH = path.join(getWhistlePath(), 'custom_plugins');
|
|
|
153
153
|
config.CUSTOM_CERTS_DIR = path.resolve(getWhistlePath(), 'custom_certs');
|
|
154
154
|
config.SAVED_SESSIONS_PATH = path.resolve(getWhistlePath(), 'saved_sessions');
|
|
155
155
|
config.DEV_PLUGINS_PATH = path.resolve(getWhistlePath(), 'dev_plugins');
|
|
156
|
+
config.rulesDir = path.join(config.baseDir, 'rules');
|
|
157
|
+
config.valuesDir = path.join(config.baseDir, 'values');
|
|
158
|
+
config.propertiesDir = path.join(config.baseDir, 'properties');
|
|
156
159
|
|
|
157
160
|
try {
|
|
158
161
|
fse.ensureDirSync(config.TEMP_FILES_PATH);
|
package/lib/https/ca.js
CHANGED
|
@@ -15,8 +15,6 @@ var common = require('../util/common');
|
|
|
15
15
|
var rulesUtil = require('../rules/util');
|
|
16
16
|
|
|
17
17
|
var pki = forge.pki;
|
|
18
|
-
var CUR_VERSION = process.version;
|
|
19
|
-
var requiredVersion = parseInt(CUR_VERSION.slice(1), 10) >= 6;
|
|
20
18
|
var HTTPS_DIR = mkdir(path.join(config.getDataDir(), 'certs'));
|
|
21
19
|
var ROOT_NEW_KEY_FILE = path.join(HTTPS_DIR, 'root_new.key');
|
|
22
20
|
var ROOT_NEW_CRT_FILE = path.join(HTTPS_DIR, 'root_new.crt');
|
|
@@ -40,6 +38,7 @@ var customCertCount = 0;
|
|
|
40
38
|
var cachePairs = new LRU({ max: 5120 });
|
|
41
39
|
var certsCache = new LRU({ max: 256 });
|
|
42
40
|
var remoteCerts = new LRU({ max: 1280 });
|
|
41
|
+
var KEY_SIZE = 2048;
|
|
43
42
|
var ILEGAL_CHAR_RE = /[^a-z\d-]/i;
|
|
44
43
|
// https://cloud.tencent.com/developer/ask/sof/58155
|
|
45
44
|
var RANDOM_SERIAL = '/' + Date.now() + '/' + process.pid + '/' + Math.floor(Math.random() * 100);
|
|
@@ -58,12 +57,12 @@ exports.remoteCerts = remoteCerts;
|
|
|
58
57
|
exports.createSecureContext = createSecureContext;
|
|
59
58
|
exports.CUSTOM_CERTS_DIR = CUSTOM_CERTS_DIR;
|
|
60
59
|
|
|
61
|
-
function
|
|
60
|
+
function notRootCa(name) {
|
|
62
61
|
return name !== 'root';
|
|
63
62
|
}
|
|
64
63
|
|
|
65
64
|
function checkFilename(name) {
|
|
66
|
-
return name && !ILLEGAL_PATH_RE.test(name) &&
|
|
65
|
+
return name && !ILLEGAL_PATH_RE.test(name) && notRootCa(name);
|
|
67
66
|
}
|
|
68
67
|
|
|
69
68
|
function resetAllCerts() {
|
|
@@ -84,7 +83,7 @@ if (timer && typeof timer.unref === 'function') {
|
|
|
84
83
|
timer.unref();
|
|
85
84
|
}
|
|
86
85
|
|
|
87
|
-
if (!useNewKey &&
|
|
86
|
+
if (!useNewKey && !checkCertificate()) {
|
|
88
87
|
try {
|
|
89
88
|
fs.unlinkSync(ROOT_KEY_FILE);
|
|
90
89
|
fs.unlinkSync(ROOT_CRT_FILE);
|
|
@@ -108,7 +107,7 @@ function isExpiredCert(crt) {
|
|
|
108
107
|
function checkCertificate() {
|
|
109
108
|
try {
|
|
110
109
|
var crt = pki.certificateFromPem(fs.readFileSync(ROOT_CRT_FILE));
|
|
111
|
-
if (crt.publicKey.n.toString(2).length <
|
|
110
|
+
if (crt.publicKey.n.toString(2).length < KEY_SIZE || isExpiredCert(crt.validity)) {
|
|
112
111
|
return false;
|
|
113
112
|
}
|
|
114
113
|
return /^whistle\.\d+$/.test(getCommonName(crt));
|
|
@@ -265,7 +264,7 @@ function parseAllCustomCerts() {
|
|
|
265
264
|
var validity = info.validity;
|
|
266
265
|
var altNames = info.altNames;
|
|
267
266
|
var dnsName = [];
|
|
268
|
-
var disabled = (
|
|
267
|
+
var disabled = (notRootCa(filename) && rulesUtil.isDisabledCertFile(filename)) || undefined;
|
|
269
268
|
altNames.forEach(function (item) {
|
|
270
269
|
if ((item.type === 2 || item.type === 7) && !pairs[item.value]) {
|
|
271
270
|
if (!disabled) {
|
|
@@ -439,7 +438,7 @@ function createRootCA() {
|
|
|
439
438
|
|
|
440
439
|
function createCACert(opts) {
|
|
441
440
|
opts = opts || {};
|
|
442
|
-
var keys = pki.rsa.generateKeyPair(
|
|
441
|
+
var keys = pki.rsa.generateKeyPair(KEY_SIZE);
|
|
443
442
|
var cert = createCert(keys.publicKey);
|
|
444
443
|
var now = Date.now() + common.padLeft(Math.floor(Math.random() * 1000), 3);
|
|
445
444
|
var attrs = [
|
|
@@ -757,7 +756,7 @@ exports.setActiveCert = function (opts) {
|
|
|
757
756
|
return;
|
|
758
757
|
}
|
|
759
758
|
var filename = opts.filename;
|
|
760
|
-
if (
|
|
759
|
+
if (notRootCa(filename) && allCustomCerts[filename]) {
|
|
761
760
|
rulesUtil.setDisabledCertFile(filename, opts.disabled);
|
|
762
761
|
parseAllCustomCerts();
|
|
763
762
|
}
|
package/lib/https/index.js
CHANGED
|
@@ -207,7 +207,7 @@ function resolveWebsocket(socket, wss) {
|
|
|
207
207
|
};
|
|
208
208
|
|
|
209
209
|
var plugin = pluginMgr.resolveWhistlePlugins(socket);
|
|
210
|
-
|
|
210
|
+
handleEnd(socket);
|
|
211
211
|
pluginMgr.getRules(socket, function (rulesMgr) {
|
|
212
212
|
if (rulesMgr) {
|
|
213
213
|
socket.pluginRules = rulesMgr;
|
|
@@ -394,7 +394,7 @@ function resolveWebsocket(socket, wss) {
|
|
|
394
394
|
proxySocket.on('error', handleProxyError);
|
|
395
395
|
reqSocket = proxySocket;
|
|
396
396
|
proxySocket.on('secureConnect', function () {
|
|
397
|
-
|
|
397
|
+
handleEnd(reqSocket);
|
|
398
398
|
pipeData();
|
|
399
399
|
});
|
|
400
400
|
} catch (e) {
|
|
@@ -403,7 +403,7 @@ function resolveWebsocket(socket, wss) {
|
|
|
403
403
|
return;
|
|
404
404
|
}
|
|
405
405
|
reqSocket = proxySocket;
|
|
406
|
-
|
|
406
|
+
handleEnd(reqSocket);
|
|
407
407
|
pipeData();
|
|
408
408
|
};
|
|
409
409
|
// 对应 internal-proxy 要用直接请求,方便用来穿透 nginx
|
|
@@ -557,7 +557,7 @@ function resolveWebsocket(socket, wss) {
|
|
|
557
557
|
return execCallback(e);
|
|
558
558
|
}
|
|
559
559
|
if (retryConnect) {
|
|
560
|
-
|
|
560
|
+
handleEnd(reqSocket);
|
|
561
561
|
} else {
|
|
562
562
|
retryConnect = function (e) {
|
|
563
563
|
if (!newIp && (newIp = util.getLocalhostIP(e, socket, socket._w2hostname, socket.hostIp))) {
|
|
@@ -621,7 +621,7 @@ function resolveWebsocket(socket, wss) {
|
|
|
621
621
|
var disable = socket.disable;
|
|
622
622
|
if (retryConnect) {
|
|
623
623
|
reqSocket.removeListener('error', retryConnect);
|
|
624
|
-
|
|
624
|
+
handleEnd(reqSocket);
|
|
625
625
|
retryConnect = null;
|
|
626
626
|
}
|
|
627
627
|
clearTimeout(timeout);
|
|
@@ -847,7 +847,7 @@ function resolveWebsocket(socket, wss) {
|
|
|
847
847
|
}
|
|
848
848
|
}
|
|
849
849
|
|
|
850
|
-
function
|
|
850
|
+
function handleEnd(socket) {
|
|
851
851
|
return util.onSocketEnd(socket, destroy);
|
|
852
852
|
}
|
|
853
853
|
var destroyed, reqDestroyed, resDestroyed;
|
|
@@ -1080,11 +1080,10 @@ function toHttp1(req, res) {
|
|
|
1080
1080
|
formatRawHeaders(svrRes, isH2)
|
|
1081
1081
|
);
|
|
1082
1082
|
var write = res.write;
|
|
1083
|
-
var handleError = function (e) {
|
|
1084
|
-
e && handleAbort();
|
|
1085
|
-
};
|
|
1086
1083
|
res.write = function (chunk) {
|
|
1087
|
-
return write.call(res, chunk,
|
|
1084
|
+
return write.call(res, chunk, function (e) {
|
|
1085
|
+
e && handleAbort();
|
|
1086
|
+
});
|
|
1088
1087
|
};
|
|
1089
1088
|
svrRes.pipe(res);
|
|
1090
1089
|
res.flushHeaders && res.flushHeaders();
|
|
@@ -1168,152 +1167,147 @@ module.exports = function (socket, next, isWebPort) {
|
|
|
1168
1167
|
|
|
1169
1168
|
util.onSocketEnd(socket, destroy);
|
|
1170
1169
|
|
|
1171
|
-
function abortIfUnavailable(s) {
|
|
1172
|
-
return s.on('error', destroy);
|
|
1173
|
-
}
|
|
1174
1170
|
var clientIp = socket.clientIp;
|
|
1175
1171
|
var clientPort = socket.clientPort;
|
|
1176
|
-
util.readOneChunk(
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
host: LOCALHOST
|
|
1188
|
-
},
|
|
1172
|
+
util.readOneChunk(socket, function (chunk) {
|
|
1173
|
+
headersStr = chunk && chunk.toString();
|
|
1174
|
+
var isHttp = chunk && HTTP_RE.test(headersStr);
|
|
1175
|
+
var statusLine = isHttp && RegExp['$&'];
|
|
1176
|
+
if (isHttp && CONNECT_RE.test(RegExp.$1)) {
|
|
1177
|
+
chunk = addClientInfo(socket, chunk, statusLine, clientIp, clientPort);
|
|
1178
|
+
util.connect(
|
|
1179
|
+
{
|
|
1180
|
+
port: config.port,
|
|
1181
|
+
host: config.host || LOCALHOST
|
|
1182
|
+
},
|
|
1189
1183
|
function (err, s) {
|
|
1190
1184
|
reqSocket = s;
|
|
1191
1185
|
if (err || socket._hasError) {
|
|
1192
1186
|
return destroy(err);
|
|
1193
1187
|
}
|
|
1188
|
+
reqSocket.on('error', destroy);
|
|
1194
1189
|
reqSocket.write(chunk);
|
|
1195
1190
|
reqSocket.pipe(socket).pipe(reqSocket);
|
|
1196
|
-
abortIfUnavailable(reqSocket);
|
|
1197
1191
|
socket.resume();
|
|
1198
1192
|
}
|
|
1199
1193
|
);
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1194
|
+
return;
|
|
1195
|
+
}
|
|
1196
|
+
if (!chunk) {
|
|
1203
1197
|
//没有数据
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1198
|
+
return isWebPort ? socket.destroy() : next(chunk);
|
|
1199
|
+
}
|
|
1200
|
+
if (isHttp) {
|
|
1201
|
+
if (isEnable('forHttps') || disable.captureHttp) {
|
|
1202
|
+
next(chunk);
|
|
1203
|
+
} else {
|
|
1204
|
+
socket.resume();
|
|
1205
|
+
server.emit('connection', socket);
|
|
1206
|
+
socket.emit(
|
|
1213
1207
|
'data',
|
|
1214
1208
|
addClientInfo(socket, chunk, statusLine, clientIp, clientPort)
|
|
1215
1209
|
);
|
|
1216
|
-
|
|
1217
|
-
|
|
1210
|
+
}
|
|
1211
|
+
} else if (isEnable('forHttp') || disable.captureHttps) {
|
|
1212
|
+
return next(chunk);
|
|
1213
|
+
} else {
|
|
1214
|
+
var isHttpH2 = HTTP2_RE.test(headersStr);
|
|
1215
|
+
if (!isHttpH2 && chunk[0] != 22) {
|
|
1218
1216
|
return next(chunk);
|
|
1219
|
-
}
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
}
|
|
1224
|
-
var useSNI, domain, serverKey;
|
|
1225
|
-
var handleConnect = function (port) {
|
|
1226
|
-
var promise =
|
|
1217
|
+
}
|
|
1218
|
+
var useSNI, domain, serverKey;
|
|
1219
|
+
var handleConnect = function (port) {
|
|
1220
|
+
var promise =
|
|
1227
1221
|
!isHttpH2 && !useSNI && serverAgent.existsServer(serverKey);
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1222
|
+
var httpsServer = promise && promise.cert && promise.server;
|
|
1223
|
+
if (httpsServer && httpsServer.setSecureContext) {
|
|
1224
|
+
var cert = serverAgent.createCertificate(domain);
|
|
1225
|
+
if (
|
|
1232
1226
|
cert.key !== promise.cert.key ||
|
|
1233
1227
|
cert.cert !== promise.cert.cert
|
|
1234
1228
|
) {
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
}
|
|
1229
|
+
try {
|
|
1230
|
+
cert._ctx = cert._ctx || ca.createSecureContext(cert);
|
|
1231
|
+
httpsServer.setSecureContext(cert._ctx);
|
|
1232
|
+
promise.cert = cert;
|
|
1233
|
+
} catch (e) {}
|
|
1241
1234
|
}
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1235
|
+
}
|
|
1236
|
+
util.connect(
|
|
1237
|
+
{
|
|
1238
|
+
port: port,
|
|
1239
|
+
host: LOCALHOST,
|
|
1240
|
+
localAddress: LOCALHOST
|
|
1241
|
+
},
|
|
1248
1242
|
function (err, s) {
|
|
1249
1243
|
reqSocket = s;
|
|
1250
1244
|
if (err || socket._hasError) {
|
|
1251
1245
|
return destroy(err);
|
|
1252
1246
|
}
|
|
1247
|
+
reqSocket.on('error', destroy);
|
|
1253
1248
|
socket._w2TunnelKey = reqSocket.localPort + ':' + reqSocket.remotePort;
|
|
1254
1249
|
tunnelTmplData.set(socket._w2TunnelKey, getTunnelData(socket, clientIp, clientPort, isHttpH2));
|
|
1255
1250
|
reqSocket.write(chunk);
|
|
1256
1251
|
reqSocket.pipe(socket).pipe(reqSocket);
|
|
1257
1252
|
socket.resume();
|
|
1258
|
-
abortIfUnavailable(reqSocket);
|
|
1259
1253
|
}
|
|
1260
1254
|
);
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1255
|
+
};
|
|
1256
|
+
var useNoSNIServer = function () {
|
|
1257
|
+
serverKey = requestCert ? ':' + domain : domain;
|
|
1258
|
+
serverAgent.createServer(serverKey, handlers, handleConnect, 0, 0);
|
|
1259
|
+
};
|
|
1266
1260
|
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
}
|
|
1275
|
-
getSNIServer(h2Handlers, handleConnect, disableH2, requestCert);
|
|
1276
|
-
} else if (isHttpH2) {
|
|
1277
|
-
getHttp2Server(h2Handlers, handleConnect);
|
|
1278
|
-
} else {
|
|
1279
|
-
useNoSNIServer();
|
|
1261
|
+
var handleRequest = function () {
|
|
1262
|
+
if (useSNI) {
|
|
1263
|
+
var disableH2 = !properties.isEnableHttp2();
|
|
1264
|
+
if (disable.http2) {
|
|
1265
|
+
disableH2 = true;
|
|
1266
|
+
} else if (enable.http2) {
|
|
1267
|
+
disableH2 = false;
|
|
1280
1268
|
}
|
|
1281
|
-
|
|
1282
|
-
if (isHttpH2) {
|
|
1283
|
-
|
|
1269
|
+
getSNIServer(h2Handlers, handleConnect, disableH2, requestCert);
|
|
1270
|
+
} else if (isHttpH2) {
|
|
1271
|
+
getHttp2Server(h2Handlers, handleConnect);
|
|
1272
|
+
} else {
|
|
1273
|
+
useNoSNIServer();
|
|
1284
1274
|
}
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1275
|
+
};
|
|
1276
|
+
if (isHttpH2) {
|
|
1277
|
+
return handleRequest();
|
|
1278
|
+
}
|
|
1279
|
+
useSNI = checkSNI(chunk);
|
|
1280
|
+
var servername = useSNI || socket.tunnelHostname;
|
|
1281
|
+
if (
|
|
1288
1282
|
!servername ||
|
|
1289
1283
|
(useSNI ? disable.captureSNI : (disable.captureNoSNI || (net.isIP(servername) && !isCaptureIp()))) ||
|
|
1290
1284
|
(socket.useProxifier && !ca.existsCustomCert(servername))
|
|
1291
1285
|
) {
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1286
|
+
return next(chunk);
|
|
1287
|
+
}
|
|
1288
|
+
var requestCert =
|
|
1295
1289
|
(enable.clientCert || enable.requestCert) &&
|
|
1296
1290
|
!disable.clientCert &&
|
|
1297
1291
|
!disable.requestCert;
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1292
|
+
domain = getDomain(servername);
|
|
1293
|
+
socket.curUrl = socket.fullUrl = 'https://' + servername;
|
|
1294
|
+
socket.useSNI = useSNI;
|
|
1295
|
+
socket.serverName = socket.servername = servername;
|
|
1296
|
+
socket.commonName = domain;
|
|
1297
|
+
loadCert(socket, function (cert) {
|
|
1298
|
+
if (socket._hasError) {
|
|
1299
|
+
return destroy();
|
|
1300
|
+
}
|
|
1301
|
+
if (cert === false) {
|
|
1302
|
+
return next(chunk);
|
|
1303
|
+
}
|
|
1304
|
+
if (cert) {
|
|
1305
|
+
domain = servername;
|
|
1306
|
+
}
|
|
1307
|
+
handleRequest();
|
|
1308
|
+
});
|
|
1309
|
+
}
|
|
1310
|
+
},
|
|
1317
1311
|
isWebPort ? 0 : TIMEOUT
|
|
1318
1312
|
);
|
|
1319
1313
|
};
|
package/lib/index.js
CHANGED
|
@@ -11,7 +11,6 @@ var setupHttps = require('./https').setup;
|
|
|
11
11
|
var httpsUtil = require('./https/ca');
|
|
12
12
|
var rulesUtil = require('./rules/util');
|
|
13
13
|
var initDataServer = require('./util/data-server');
|
|
14
|
-
var initLogServer = require('./util/log-server');
|
|
15
14
|
var pluginMgr = require('./plugins');
|
|
16
15
|
var config = require('./config');
|
|
17
16
|
var loadService = require('./service');
|
|
@@ -61,7 +60,6 @@ function proxy(callback, _server) {
|
|
|
61
60
|
tunnelProxy(server, proxyEvents);
|
|
62
61
|
upgradeProxy(server);
|
|
63
62
|
initDataServer(proxyEvents);
|
|
64
|
-
initLogServer(proxyEvents);
|
|
65
63
|
rulesUtil.setup(proxyEvents);
|
|
66
64
|
var properties = rulesUtil.properties;
|
|
67
65
|
if (config.disableAllRules) {
|
|
@@ -254,7 +252,7 @@ function handleGlobalException(err) {
|
|
|
254
252
|
code === 'ERR_HTTP_TRAILER_INVALID' ||
|
|
255
253
|
code === 'ERR_INTERNAL_ASSERTION' ||
|
|
256
254
|
code === 'ERR_INVALID_ARG_TYPE' ||
|
|
257
|
-
(err && /finishwrite/i.test(err.message)))
|
|
255
|
+
(err && /finishwrite|'_hadError'/i.test(err.message)))
|
|
258
256
|
) {
|
|
259
257
|
return;
|
|
260
258
|
}
|
package/lib/inspectors/log.js
CHANGED
|
@@ -29,7 +29,11 @@ module.exports = function (req, res) {
|
|
|
29
29
|
if (log) {
|
|
30
30
|
util.disableReqCache(req.headers);
|
|
31
31
|
var host = req.headers.host;
|
|
32
|
+
delete req.rules.log;
|
|
32
33
|
res.on('src', function (_res) {
|
|
34
|
+
if (!(log = req.rules.log) || !util.hasBody(_res)) {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
33
37
|
var topScript, isHtml;
|
|
34
38
|
if (util.supportHtmlTransform(_res, req)) {
|
|
35
39
|
isHtml = true;
|
package/lib/inspectors/weinre.js
CHANGED
|
@@ -21,17 +21,22 @@ function getScript(host, name, isHtml, req) {
|
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
module.exports = function (req, res) {
|
|
24
|
-
|
|
24
|
+
var weinre = req.rules.weinre;
|
|
25
|
+
if (weinre) {
|
|
25
26
|
util.disableReqCache(req.headers);
|
|
27
|
+
delete req.rules.weinre;
|
|
26
28
|
var host = req.headers.host;
|
|
27
29
|
res.on('src', function (_res) {
|
|
30
|
+
if (!(weinre = req.rules.weinre) || !util.hasBody(_res)) {
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
28
33
|
var isHtml = util.supportHtmlTransform(_res, req);
|
|
29
34
|
if (!isHtml && util.getContentType(_res.headers) !== 'JS') {
|
|
30
35
|
return;
|
|
31
36
|
}
|
|
32
37
|
!util.isEnable(req, 'keepAllCSP') && util.disableCSP(_res.headers);
|
|
33
38
|
!req._customCache && util.disableResStore(_res.headers);
|
|
34
|
-
var name = util.getPath(util.rule.getMatcher(
|
|
39
|
+
var name = util.getPath(util.rule.getMatcher(weinre));
|
|
35
40
|
var transform = new Transform();
|
|
36
41
|
transform._transform = function (chunk, _, callback) {
|
|
37
42
|
if (!chunk) {
|
package/lib/rules/index.js
CHANGED
|
@@ -63,7 +63,6 @@ exports.hasReqScript = rules.hasReqScript.bind(rules);
|
|
|
63
63
|
exports.resolveDisable = rules.resolveDisable.bind(rules);
|
|
64
64
|
exports.resolvePipe = rules.resolvePipe.bind(rules);
|
|
65
65
|
exports.resolveRule = rules.resolveRule.bind(rules);
|
|
66
|
-
exports.resolveRules = resolveReqRules;
|
|
67
66
|
exports.resolveResRules = rules.resolveResRules.bind(rules);
|
|
68
67
|
exports.resolveBodyFilter = rules.resolveBodyFilter.bind(rules);
|
|
69
68
|
exports.lookupHost = rules.lookupHost.bind(rules);
|
package/lib/rules/protocols.js
CHANGED
|
@@ -73,6 +73,7 @@ var protocols = [
|
|
|
73
73
|
'cipher',
|
|
74
74
|
'sniCallback'
|
|
75
75
|
];
|
|
76
|
+
var toolProtocols = ['log', 'weinre'];
|
|
76
77
|
|
|
77
78
|
var RULE_RE = /^(?:|x|xs)(?:file|rawfile|dust|tpl|jsonp):/;
|
|
78
79
|
var LOC_RE = /^locationHref:/;
|
|
@@ -86,7 +87,6 @@ var pureResProtocols = [
|
|
|
86
87
|
'resDelay',
|
|
87
88
|
'resSpeed',
|
|
88
89
|
'resType',
|
|
89
|
-
'resType',
|
|
90
90
|
'resCharset',
|
|
91
91
|
'resCookies',
|
|
92
92
|
'resCors',
|
|
@@ -108,7 +108,7 @@ var pureResProtocols = [
|
|
|
108
108
|
'htmlPrepend',
|
|
109
109
|
'jsPrepend',
|
|
110
110
|
'responseFor'
|
|
111
|
-
];
|
|
111
|
+
].concat(toolProtocols);
|
|
112
112
|
var resProtocols = [
|
|
113
113
|
'filter',
|
|
114
114
|
'enable',
|
|
@@ -155,7 +155,7 @@ var aliasProtocols = {
|
|
|
155
155
|
var protocolsWithoutG = protocols.slice(1);
|
|
156
156
|
var reqProtocols = protocols.filter(function (name) {
|
|
157
157
|
return pureResProtocols.indexOf(name) === -1;
|
|
158
|
-
});
|
|
158
|
+
}).concat(toolProtocols);
|
|
159
159
|
var reqProtosWithoutG = reqProtocols.filter(function (name) {
|
|
160
160
|
return name !== 'G';
|
|
161
161
|
});
|
|
@@ -266,12 +266,6 @@ function resetRules(rules) {
|
|
|
266
266
|
|
|
267
267
|
exports.resetRules = resetRules;
|
|
268
268
|
|
|
269
|
-
function isResRule(protocol) {
|
|
270
|
-
return resProtocols.indexOf(protocol) != -1;
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
exports.isResRule = isResRule;
|
|
274
|
-
|
|
275
269
|
function isWebProtocol(protocol) {
|
|
276
270
|
return protocol == 'http:' || protocol == 'https:';
|
|
277
271
|
}
|