whistle 2.9.109 → 2.10.1
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 +8 -4
- package/bin/util.js +1 -1
- package/biz/index.js +12 -10
- package/biz/webui/cgi-bin/certs/active.js +6 -0
- package/biz/webui/cgi-bin/certs/remove.js +0 -1
- package/biz/webui/cgi-bin/certs/upload.js +0 -1
- package/biz/webui/cgi-bin/util.js +7 -20
- package/biz/webui/htdocs/index.html +1 -1
- package/biz/webui/htdocs/js/index.js +43 -43
- package/biz/webui/lib/index.js +10 -13
- package/lib/config.js +17 -36
- package/lib/handlers/file-proxy.js +2 -1
- package/lib/handlers/http-proxy.js +1 -1
- package/lib/https/ca.js +34 -27
- package/lib/https/h2.js +1 -1
- package/lib/https/index.js +21 -17
- package/lib/index.js +1 -1
- package/lib/init.js +13 -12
- package/lib/inspectors/req.js +13 -10
- package/lib/inspectors/res.js +375 -390
- package/lib/inspectors/rules.js +11 -0
- package/lib/plugins/compat.js +108 -0
- package/lib/plugins/get-plugins-sync.js +1 -4
- package/lib/plugins/index.js +92 -284
- package/lib/plugins/load-plugin.js +205 -223
- package/lib/plugins/module-paths.js +3 -4
- package/lib/plugins/proxy.js +4 -7
- package/lib/rules/index.js +69 -66
- package/lib/rules/protocols.js +6 -0
- package/lib/rules/rules.js +44 -32
- package/lib/rules/util.js +30 -0
- package/lib/service/composer.js +5 -5
- package/lib/service/util.js +7 -21
- package/lib/tunnel.js +15 -12
- package/lib/upgrade.js +9 -10
- package/lib/util/common.js +171 -48
- package/lib/util/file-mgr.js +3 -7
- package/lib/util/index.js +101 -143
- package/package.json +1 -1
- package/README-en_US.md +0 -80
- package/biz/webui/htdocs/img/assistant.svg +0 -1
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
var listenerCount = require('../util/patch').listenerCount;
|
|
2
2
|
var path = require('path');
|
|
3
3
|
var fs = require('fs');
|
|
4
|
+
var net = require('net');
|
|
5
|
+
var qs = require('querystring');
|
|
4
6
|
var express = require('express');
|
|
5
7
|
var os = require('os');
|
|
6
8
|
var format = require('util').format;
|
|
@@ -22,15 +24,19 @@ var rootRequire = require('../../require');
|
|
|
22
24
|
var extractSaz = require('../service/extract-saz');
|
|
23
25
|
var generateSaz = require('../service/generate-saz');
|
|
24
26
|
var getSharedStorage = require('./shared-storage');
|
|
27
|
+
var compat = require('./compat');
|
|
25
28
|
|
|
26
29
|
var getEncodeTransform = transproto.getEncodeTransform;
|
|
27
30
|
var getDecodeTransform = transproto.getDecodeTransform;
|
|
28
31
|
var setInternalOptions = common.setInternalOptions;
|
|
32
|
+
var toBuffer = common.toBuffer;
|
|
33
|
+
var readStream = common.readStream;
|
|
29
34
|
|
|
30
35
|
var LEVELS = ['log', 'error', 'warn', 'info', 'debug', 'trace'];
|
|
31
36
|
var HTTPS_RE = /^(?:https|wss):\/\//;
|
|
32
37
|
var MAX_BODY_SIZE = 1024 * 256;
|
|
33
38
|
var PING_INTERVAL = 22000;
|
|
39
|
+
var LOCALHOST = '127.0.0.1';
|
|
34
40
|
var sessionStorage = new LRU({
|
|
35
41
|
maxAge: 1000 * 60 * 12,
|
|
36
42
|
max: 1600
|
|
@@ -42,6 +48,10 @@ var formatHeaders = hparser.formatHeaders;
|
|
|
42
48
|
var getRawHeaderNames = hparser.getRawHeaderNames;
|
|
43
49
|
var getRawHeaders = hparser.getRawHeaders;
|
|
44
50
|
var STATUS_CODES = http.STATUS_CODES || {};
|
|
51
|
+
var clientIpKey = Symbol('clientIp');
|
|
52
|
+
var clientPortKey = Symbol('clientPort');
|
|
53
|
+
var remoteAddrKey = Symbol('remoteAddr');
|
|
54
|
+
var remotePortKey = Symbol('remotePort');
|
|
45
55
|
var pluginName;
|
|
46
56
|
|
|
47
57
|
var QUERY_RE = /\?.*$/;
|
|
@@ -59,19 +69,15 @@ var MAX_BUF_LEN = 1024 * 1024;
|
|
|
59
69
|
var TIMEOUT = 300;
|
|
60
70
|
var REQ_INTERVAL = 16;
|
|
61
71
|
var pluginOpts, storage, sharedStorage;
|
|
62
|
-
var pluginKeyMap = {};
|
|
63
72
|
var MASK_OPTIONS = { mask: true };
|
|
64
73
|
var BINARY_MASK_OPTIONS = { mask: true, binary: true };
|
|
65
74
|
var BINARY_OPTIONS = { binary: true };
|
|
66
75
|
/* eslint-disable no-undef */
|
|
67
|
-
var REQ_ID_KEY =
|
|
68
|
-
|
|
69
|
-
var
|
|
70
|
-
|
|
71
|
-
var
|
|
72
|
-
typeof Symbol === 'undefined' ? '$frame_' + Date.now() : Symbol();
|
|
73
|
-
var REQ_KEY = typeof Symbol === 'undefined' ? '$req_' + Date.now() : Symbol();
|
|
74
|
-
var CLOSED = typeof Symbol === 'undefined' ? '$colsed_' + Date.now() : Symbol();
|
|
76
|
+
var REQ_ID_KEY = Symbol('reqId');
|
|
77
|
+
var SESSION_KEY = Symbol('session');
|
|
78
|
+
var FRAME_KEY = Symbol('frame');
|
|
79
|
+
var REQ_KEY = Symbol('req');
|
|
80
|
+
var CLOSED = Symbol('closed');
|
|
75
81
|
var NOT_NAME_RE = /[^\w.-]/;
|
|
76
82
|
/* eslint-enable no-undef */
|
|
77
83
|
var index = 1000;
|
|
@@ -81,19 +87,16 @@ var certsCache = new LRU({ max: 256 });
|
|
|
81
87
|
var certsCallbacks = {};
|
|
82
88
|
var ctx;
|
|
83
89
|
var PLUGIN_HOOK_NAME_HEADER;
|
|
84
|
-
var
|
|
85
|
-
var GLOBAL_PLUGIN_VARS_HEAD;
|
|
86
|
-
var PLUGIN_VARS_HEAD;
|
|
87
|
-
var FROM_TUNNEL_HEADER;
|
|
88
|
-
var REMOTE_ADDR_HEAD;
|
|
89
|
-
var REMOTE_PORT_HEAD;
|
|
90
|
-
var SNI_TYPE_HEADER;
|
|
90
|
+
var CLIENT_INFO_HEADER;
|
|
91
91
|
var PROXY_ID_HEADER;
|
|
92
|
-
var REQ_FROM_HEADER;
|
|
93
92
|
var debugMode;
|
|
94
93
|
var pluginInited;
|
|
95
94
|
var writeDevLog;
|
|
96
95
|
|
|
96
|
+
var addRemoteInfo = function(req, headers) {
|
|
97
|
+
headers[CLIENT_INFO_HEADER] = [req[clientIpKey], req[clientPortKey], req[remoteAddrKey], req[remotePortKey]].join();
|
|
98
|
+
};
|
|
99
|
+
|
|
97
100
|
process._handlePforkUncaughtException = function (msg, e) {
|
|
98
101
|
msg = [
|
|
99
102
|
'From: ' + pluginName + pluginVersion,
|
|
@@ -154,13 +157,6 @@ var requestData = function (options, callback) {
|
|
|
154
157
|
});
|
|
155
158
|
};
|
|
156
159
|
|
|
157
|
-
var getValue = function (req, name) {
|
|
158
|
-
var value = req.headers[name] || '';
|
|
159
|
-
try {
|
|
160
|
-
return value ? decodeURIComponent(value) : '';
|
|
161
|
-
} catch (e) {}
|
|
162
|
-
return String(value);
|
|
163
|
-
};
|
|
164
160
|
var setContext = function (req) {
|
|
165
161
|
if (ctx) {
|
|
166
162
|
req.ctx = ctx;
|
|
@@ -168,7 +164,81 @@ var setContext = function (req) {
|
|
|
168
164
|
req.localStorage = storage;
|
|
169
165
|
req.Storage = Storage;
|
|
170
166
|
req.sharedStorage = sharedStorage;
|
|
171
|
-
|
|
167
|
+
// 原始请求信息 (Original request information)
|
|
168
|
+
var oReq = (req.originalReq = {});
|
|
169
|
+
var oRes = (req.originalRes = {});
|
|
170
|
+
var headers = req.headers;
|
|
171
|
+
var sessionInfo = common.getSessionInfo(headers);
|
|
172
|
+
if (!sessionInfo) {
|
|
173
|
+
var clientIp = headers[common.CLIENT_IP_HEADER];
|
|
174
|
+
req.clientIp = net.isIP(clientIp) ? clientIp : LOCALHOST;
|
|
175
|
+
req.clientPort = +headers[common.CLIENT_PORT_HEADER] || 0;
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
var fullUrl = sessionInfo.fullUrl;
|
|
179
|
+
oReq.url = oReq.fullUrl = req.fullUrl = fullUrl;
|
|
180
|
+
oReq.extraUrl = sessionInfo._extraUrl;
|
|
181
|
+
oReq.ruleProtocol = sessionInfo._ruleProtocol;
|
|
182
|
+
req.isHttps = oReq.isHttps = HTTPS_RE.test(fullUrl);
|
|
183
|
+
req._isUpgrade = sessionInfo._isUpgrade === '1';
|
|
184
|
+
req.notDecompressed = oReq.notDecompressed = sessionInfo._noDecompress === '1';
|
|
185
|
+
req.fromTunnel = oReq.fromTunnel = sessionInfo.fromTunnel === '1';
|
|
186
|
+
req.fromComposer = oReq.fromComposer = sessionInfo.fromComposer === '1';
|
|
187
|
+
oReq.existsCustomCert = sessionInfo._existsCustomCert == '1';
|
|
188
|
+
oReq.isUIRequest = req.isUIRequest = sessionInfo._isUIRequest == '1';
|
|
189
|
+
oReq.enableCapture = sessionInfo._enableCapture == '1';
|
|
190
|
+
oReq.isFromPlugin = req.fromPlugin = oReq.fromPlugin = sessionInfo.isPluginReq == '1';
|
|
191
|
+
req[clientIpKey] = req.clientIp = oReq.clientIp = sessionInfo.clientIp || LOCALHOST;
|
|
192
|
+
req[clientPortKey] = req.clientPort = oReq.clientPort = +sessionInfo.clientPort || 0;
|
|
193
|
+
req[remoteAddrKey] = oReq.remoteAddress = sessionInfo._remoteAddr || LOCALHOST;
|
|
194
|
+
req[remotePortKey] = oReq.remotePort = +sessionInfo._remotePort || 0;
|
|
195
|
+
oReq.isHttp2 = oReq.isH2 = !!headers[common.ALPN_PROTOCOL_HEADER];
|
|
196
|
+
oReq.relativeUrl = sessionInfo._relativeUrl;
|
|
197
|
+
oReq.ruleUrl = sessionInfo._ruleUrl;
|
|
198
|
+
oReq.realUrl = sessionInfo._finalUrl || oReq.url;
|
|
199
|
+
oReq.sniValue = sessionInfo.sniRuleValue;
|
|
200
|
+
oReq.pipeValue = sessionInfo._pipeValue;
|
|
201
|
+
oReq.hostValue = sessionInfo.host;
|
|
202
|
+
oReq.proxyValue = sessionInfo.proxy;
|
|
203
|
+
oReq.pacValue = sessionInfo.pac;
|
|
204
|
+
oReq.globalValue = sessionInfo.globalValue;
|
|
205
|
+
oReq.servername = oReq.serverName = sessionInfo.serverName;
|
|
206
|
+
oReq.commonName = sessionInfo.commonName;
|
|
207
|
+
oReq.method = sessionInfo.method || 'GET';
|
|
208
|
+
oReq.serverIp = oRes.serverIp = sessionInfo.hostIp;
|
|
209
|
+
oReq.statusCode = oRes.statusCode = sessionInfo._statusCode;
|
|
210
|
+
oReq.ruleValue = sessionInfo._ruleValue;
|
|
211
|
+
oReq.pluginVars = getPluginVars(sessionInfo._pluginVarsValue);
|
|
212
|
+
oReq.globalPluginVars = getPluginVars(sessionInfo._globalPluginVarsValue);
|
|
213
|
+
|
|
214
|
+
var originHost = headers[common.ORIGIN_HOST_HEADER]; // for web ui;
|
|
215
|
+
oReq.originHost = common.isString(originHost) ? originHost : '';
|
|
216
|
+
|
|
217
|
+
var pattern = sessionInfo._rawPattern;
|
|
218
|
+
if (pattern && pattern[1] === ',') {
|
|
219
|
+
oReq.isRexExp = oReq.isRegExp = pattern[0] === '1';
|
|
220
|
+
oReq.pattern = pattern.substring(2);
|
|
221
|
+
}
|
|
222
|
+
var sniType = sessionInfo._sniType;
|
|
223
|
+
var isSNI = !sniType;
|
|
224
|
+
if (sniType && sniType === '1') {
|
|
225
|
+
isSNI = true;
|
|
226
|
+
req.isHttpsServer = true;
|
|
227
|
+
}
|
|
228
|
+
req.useSNI = oReq.useSNI = req.isSNI = oReq.isSNI = isSNI;
|
|
229
|
+
oReq.headers = headers;
|
|
230
|
+
|
|
231
|
+
var certCacheInfo = sessionInfo.hasCertCache;
|
|
232
|
+
oReq.certCacheName = certCacheInfo;
|
|
233
|
+
oReq.certCacheTime = 0;
|
|
234
|
+
if (certCacheInfo) {
|
|
235
|
+
var sepIndex = certCacheInfo.indexOf('+');
|
|
236
|
+
if (sepIndex !== -1) {
|
|
237
|
+
oReq.certCacheName = certCacheInfo.substring(0, sepIndex);
|
|
238
|
+
oReq.certCacheTime = parseInt(certCacheInfo.substring(sepIndex + 1)) || 0;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
return compat.compatHeaders(req, sessionInfo);
|
|
172
242
|
};
|
|
173
243
|
|
|
174
244
|
var initState = function (req, name) {
|
|
@@ -410,11 +480,9 @@ var ADDITIONAL_FIELDS = [
|
|
|
410
480
|
'sessionStorage'
|
|
411
481
|
];
|
|
412
482
|
|
|
413
|
-
function getPluginVars(
|
|
414
|
-
var value = req.headers[key];
|
|
483
|
+
function getPluginVars(value) {
|
|
415
484
|
value = base64ToBuffer(value);
|
|
416
485
|
if (value) {
|
|
417
|
-
delete req.headers[key];
|
|
418
486
|
try {
|
|
419
487
|
value = JSON.parse(value.toString());
|
|
420
488
|
if (Array.isArray(value)) {
|
|
@@ -448,92 +516,17 @@ var initReq = function (req, res, isServer) {
|
|
|
448
516
|
return getFrames(req, cb);
|
|
449
517
|
};
|
|
450
518
|
|
|
451
|
-
var
|
|
452
|
-
var oReq =
|
|
453
|
-
var
|
|
454
|
-
setContext(req);
|
|
455
|
-
oReq.clientIp = req.clientIp;
|
|
519
|
+
var sessionInfo = setContext(req) || {};
|
|
520
|
+
var oReq = req.originalReq;
|
|
521
|
+
var reqId = sessionInfo.reqId;
|
|
456
522
|
if (isServer) {
|
|
457
|
-
var parseStatus =
|
|
458
|
-
req.customParser = oReq.customParser =
|
|
523
|
+
var parseStatus = sessionInfo.customParser;
|
|
524
|
+
req.customParser = oReq.customParser = !!parseStatus;
|
|
459
525
|
req.customParser && addParserApi(req, res, parseStatus, reqId);
|
|
460
526
|
}
|
|
461
|
-
var conf = pluginOpts.config;
|
|
462
527
|
req[REQ_ID_KEY] = oReq.id = reqId;
|
|
463
528
|
addSessionStorage(req, reqId);
|
|
464
|
-
oReq.
|
|
465
|
-
oReq.existsCustomCert = req.headers[pluginOpts.CUSTOM_CERT_HEADER] == '1';
|
|
466
|
-
oReq.isUIRequest = req.isUIRequest =
|
|
467
|
-
req.headers[pluginOpts.UI_REQUEST_HEADER] == '1';
|
|
468
|
-
oReq.enableCapture = req.headers[pluginOpts.ENABLE_CAPTURE_HEADER] == '1';
|
|
469
|
-
oReq.isFromPlugin = req.fromPlugin = oReq.fromPlugin = req.headers[pluginOpts.PLUGIN_REQUEST_HEADER] == '1';
|
|
470
|
-
oReq.ruleValue = getValue(req, pluginOpts.RULE_VALUE_HEADER);
|
|
471
|
-
oReq.ruleUrl = getValue(req, pluginOpts.RULE_URL_HEADER);
|
|
472
|
-
oReq.pipeValue = getValue(req, pluginOpts.PIPE_VALUE_HEADER);
|
|
473
|
-
oReq.sniValue = getValue(req, pluginOpts.SNI_VALUE_HEADER);
|
|
474
|
-
oReq.hostValue = getValue(req, pluginOpts.HOST_VALUE_HEADER);
|
|
475
|
-
oReq.extraUrl = getValue(req, pluginOpts.EXTRA_URL_HEADER);
|
|
476
|
-
var fullUrl = getValue(req, pluginOpts.FULL_URL_HEADER);
|
|
477
|
-
var pattern = getValue(req, 'x-whistle-raw-pattern_');
|
|
478
|
-
oReq.url = oReq.fullUrl = req.fullUrl = fullUrl;
|
|
479
|
-
req.isHttps = oReq.isHttps = HTTPS_RE.test(fullUrl);
|
|
480
|
-
oReq.remoteAddress = req.headers[REMOTE_ADDR_HEAD] || '127.0.0.1';
|
|
481
|
-
oReq.remotePort = parseInt(req.headers[REMOTE_PORT_HEAD], 10) || 0;
|
|
482
|
-
req.notDecompressed = oReq.notDecompressed = req.headers['x-whistle-disable-ws-decompress'] === '1';
|
|
483
|
-
req.fromTunnel = oReq.fromTunnel = req.headers[FROM_TUNNEL_HEADER] === '1';
|
|
484
|
-
delete req.headers[FROM_TUNNEL_HEADER];
|
|
485
|
-
delete req.headers[REMOTE_ADDR_HEAD];
|
|
486
|
-
delete req.headers[REMOTE_PORT_HEAD];
|
|
487
|
-
if (pattern) {
|
|
488
|
-
delete req.headers['x-whistle-raw-pattern_'];
|
|
489
|
-
if (pattern[1] === ',') {
|
|
490
|
-
oReq.isRexExp = oReq.isRegExp = pattern[0] === '1';
|
|
491
|
-
oReq.pattern = pattern.substring(2);
|
|
492
|
-
}
|
|
493
|
-
}
|
|
494
|
-
var from = req.headers[REQ_FROM_HEADER];
|
|
495
|
-
req.fromComposer = oReq.fromComposer = from === 'W2COMPOSER';
|
|
496
|
-
req.fromInternalPath = oReq.fromInternalPath = from === 'W2INTERNAL_PATH';
|
|
497
|
-
oReq.originHost = req.headers['x-whistle-origin-host']; // for web ui
|
|
498
|
-
oReq.servername = oReq.serverName = getValue(
|
|
499
|
-
req,
|
|
500
|
-
pluginOpts.SERVER_NAME_HEAD
|
|
501
|
-
);
|
|
502
|
-
var certCacheInfo = getValue(req, pluginOpts.CERT_CACHE_INFO);
|
|
503
|
-
oReq.certCacheName = certCacheInfo;
|
|
504
|
-
oReq.certCacheTime = 0;
|
|
505
|
-
if (certCacheInfo) {
|
|
506
|
-
var sepIndex = certCacheInfo.indexOf('+');
|
|
507
|
-
if (sepIndex !== -1) {
|
|
508
|
-
oReq.certCacheName = certCacheInfo.substring(0, sepIndex);
|
|
509
|
-
oReq.certCacheTime = parseInt(certCacheInfo.substring(sepIndex + 1)) || 0;
|
|
510
|
-
}
|
|
511
|
-
}
|
|
512
|
-
var sniType = req.headers[SNI_TYPE_HEADER];
|
|
513
|
-
var isSNI;
|
|
514
|
-
if (sniType) {
|
|
515
|
-
delete req.headers[SNI_TYPE_HEADER];
|
|
516
|
-
if (sniType === '1') {
|
|
517
|
-
isSNI = true;
|
|
518
|
-
req.isHttpsServer = true;
|
|
519
|
-
}
|
|
520
|
-
} else {
|
|
521
|
-
isSNI = true;
|
|
522
|
-
}
|
|
523
|
-
req.useSNI = oReq.useSNI = req.isSNI = oReq.isSNI = isSNI;
|
|
524
|
-
oReq.commonName = getValue(req, pluginOpts.COMMON_NAME_HEAD);
|
|
525
|
-
oReq.realUrl = getValue(req, pluginOpts.REAL_URL_HEADER) || oReq.url;
|
|
526
|
-
oReq.relativeUrl = getValue(req, pluginOpts.RELATIVE_URL_HEADER);
|
|
527
|
-
oReq.method = getValue(req, pluginOpts.METHOD_HEADER) || 'GET';
|
|
528
|
-
oReq.clientPort = getValue(req, pluginOpts.CLIENT_PORT_HEAD);
|
|
529
|
-
oReq.globalValue = getValue(req, pluginOpts.GLOBAL_VALUE_HEAD);
|
|
530
|
-
oReq.proxyValue = getValue(req, pluginOpts.PROXY_VALUE_HEADER);
|
|
531
|
-
oReq.pacValue = getValue(req, pluginOpts.PAC_VALUE_HEADER);
|
|
532
|
-
oReq.pluginVars = getPluginVars(req, PLUGIN_VARS_HEAD);
|
|
533
|
-
oReq.globalPluginVars = getPluginVars(req, GLOBAL_PLUGIN_VARS_HEAD);
|
|
534
|
-
oReq.serverIp = oRes.serverIp = getValue(req, pluginOpts.HOST_IP_HEADER) || '';
|
|
535
|
-
oReq.statusCode = oRes.statusCode = getValue(req, pluginOpts.STATUS_CODE_HEADER);
|
|
536
|
-
oReq.headers = extractHeaders(req, pluginKeyMap);
|
|
529
|
+
oReq.clientId = String(req.headers[common.CLIENT_ID_HEADER] || '');
|
|
537
530
|
};
|
|
538
531
|
var getOptions = function (opts, binary, toServer) {
|
|
539
532
|
if (opts) {
|
|
@@ -821,7 +814,7 @@ var initConnectReq = function (req, res) {
|
|
|
821
814
|
'Content-Length: ' + length,
|
|
822
815
|
'Proxy-Agent: ' + pluginOpts.shortName
|
|
823
816
|
];
|
|
824
|
-
if (err || !cb || !req.headers[
|
|
817
|
+
if (err || !cb || !req.headers[common.ACK_HEADER]) {
|
|
825
818
|
resCtn.push('\r\n', body);
|
|
826
819
|
res.write(resCtn.join('\r\n'));
|
|
827
820
|
return cb && cb();
|
|
@@ -865,13 +858,6 @@ function getHookName(req) {
|
|
|
865
858
|
return typeof name === 'string' ? name : null;
|
|
866
859
|
}
|
|
867
860
|
|
|
868
|
-
function isUpgrade(req) {
|
|
869
|
-
if (req.headers[UPGRADE_HEADER]) {
|
|
870
|
-
delete req.headers[UPGRADE_HEADER];
|
|
871
|
-
return true;
|
|
872
|
-
}
|
|
873
|
-
}
|
|
874
|
-
|
|
875
861
|
function handleError(socket, sender, receiver) {
|
|
876
862
|
var emitError = function (err) {
|
|
877
863
|
if (socket._emittedError) {
|
|
@@ -903,7 +889,10 @@ function getCustomBody(body, req, cb) {
|
|
|
903
889
|
return handleCb();
|
|
904
890
|
}
|
|
905
891
|
var encoding = headers['content-encoding'];
|
|
906
|
-
body
|
|
892
|
+
if (body && typeof body === 'object' && common.isUrlEncoded(req)) {
|
|
893
|
+
body = qs.stringify(body);
|
|
894
|
+
}
|
|
895
|
+
body = toBuffer(body) || '';
|
|
907
896
|
if (!GZIP_RE.test(encoding)) {
|
|
908
897
|
return handleCb();
|
|
909
898
|
}
|
|
@@ -919,7 +908,7 @@ function wrapTunnelWriter(socket, toServer) {
|
|
|
919
908
|
var sender = wsParser.getSender(socket, toServer);
|
|
920
909
|
handleError(socket, sender);
|
|
921
910
|
socket.write = function (chunk, encoding, cb) {
|
|
922
|
-
if ((chunk =
|
|
911
|
+
if ((chunk = toBuffer(chunk))) {
|
|
923
912
|
if (encoding === 'binary') {
|
|
924
913
|
return write.call(this, chunk, encoding, cb);
|
|
925
914
|
}
|
|
@@ -932,7 +921,7 @@ function wrapTunnelWriter(socket, toServer) {
|
|
|
932
921
|
};
|
|
933
922
|
if (toServer) {
|
|
934
923
|
socket.write = function (chunk, opts, cb) {
|
|
935
|
-
if ((chunk =
|
|
924
|
+
if ((chunk = toBuffer(chunk))) {
|
|
936
925
|
if (opts === 'binary') {
|
|
937
926
|
return write.call(this, chunk, opts, cb);
|
|
938
927
|
}
|
|
@@ -940,12 +929,12 @@ function wrapTunnelWriter(socket, toServer) {
|
|
|
940
929
|
}
|
|
941
930
|
};
|
|
942
931
|
socket.writeText = function (chunk) {
|
|
943
|
-
if ((chunk =
|
|
932
|
+
if ((chunk = toBuffer(chunk))) {
|
|
944
933
|
sender.send(chunk, getOptions(null, false, true));
|
|
945
934
|
}
|
|
946
935
|
};
|
|
947
936
|
socket.writeBin = function (chunk) {
|
|
948
|
-
if ((chunk =
|
|
937
|
+
if ((chunk = toBuffer(chunk))) {
|
|
949
938
|
sender.send(chunk, getOptions(null, true, true));
|
|
950
939
|
}
|
|
951
940
|
};
|
|
@@ -957,7 +946,7 @@ function wrapTunnelWriter(socket, toServer) {
|
|
|
957
946
|
};
|
|
958
947
|
} else {
|
|
959
948
|
socket.write = function (chunk, encoding, cb) {
|
|
960
|
-
if ((chunk =
|
|
949
|
+
if ((chunk = toBuffer(chunk))) {
|
|
961
950
|
if (encoding === 'binary') {
|
|
962
951
|
return write.call(this, chunk, encoding, cb);
|
|
963
952
|
}
|
|
@@ -1048,7 +1037,7 @@ function addFrameHandler(req, socket, maxWsPayload, fromClient, toServer) {
|
|
|
1048
1037
|
emit.call(socket, 'data', chunk, opts);
|
|
1049
1038
|
};
|
|
1050
1039
|
socket.write = function (chunk, opts, cb) {
|
|
1051
|
-
if ((chunk =
|
|
1040
|
+
if ((chunk = toBuffer(chunk))) {
|
|
1052
1041
|
if (opts === 'binary') {
|
|
1053
1042
|
return write.call(this, chunk, opts, cb);
|
|
1054
1043
|
}
|
|
@@ -1056,12 +1045,12 @@ function addFrameHandler(req, socket, maxWsPayload, fromClient, toServer) {
|
|
|
1056
1045
|
}
|
|
1057
1046
|
};
|
|
1058
1047
|
socket.writeText = function (chunk) {
|
|
1059
|
-
if ((chunk =
|
|
1048
|
+
if ((chunk = toBuffer(chunk))) {
|
|
1060
1049
|
sender.send(chunk, getOptions(null, false, toServer));
|
|
1061
1050
|
}
|
|
1062
1051
|
};
|
|
1063
1052
|
socket.writeBin = function (chunk) {
|
|
1064
|
-
if ((chunk =
|
|
1053
|
+
if ((chunk = toBuffer(chunk))) {
|
|
1065
1054
|
sender.send(chunk, getOptions(null, true, toServer));
|
|
1066
1055
|
}
|
|
1067
1056
|
};
|
|
@@ -1090,16 +1079,6 @@ function formatRawHeaders(headers, req) {
|
|
|
1090
1079
|
return formatHeaders(headers, rawNames);
|
|
1091
1080
|
}
|
|
1092
1081
|
|
|
1093
|
-
function extractHeaders(req, exlucdekyes) {
|
|
1094
|
-
var headers = {};
|
|
1095
|
-
Object.keys(req.headers).forEach(function (key) {
|
|
1096
|
-
if (!exlucdekyes[key]) {
|
|
1097
|
-
headers[key] = req.headers[key];
|
|
1098
|
-
}
|
|
1099
|
-
});
|
|
1100
|
-
return headers;
|
|
1101
|
-
}
|
|
1102
|
-
|
|
1103
1082
|
function addErrorHandler(req, client) {
|
|
1104
1083
|
var done;
|
|
1105
1084
|
client.on('error', function (err) {
|
|
@@ -1137,6 +1116,7 @@ function isBodyData(result) {
|
|
|
1137
1116
|
|
|
1138
1117
|
module.exports = async function (options, callback) {
|
|
1139
1118
|
var root = options.value;
|
|
1119
|
+
options.CLIENT_ID_HEADER = common.CLIENT_ID_HEADER;
|
|
1140
1120
|
options.extractSaz = extractSaz;
|
|
1141
1121
|
options.generateSaz = generateSaz;
|
|
1142
1122
|
options.zipBody = getCustomBody;
|
|
@@ -1162,7 +1142,6 @@ module.exports = async function (options, callback) {
|
|
|
1162
1142
|
options.parseUrl = parseUrl;
|
|
1163
1143
|
options.formatHeaders = formatRawHeaders;
|
|
1164
1144
|
options.wsParser = wsParser;
|
|
1165
|
-
options.RULE_PROTO_HEADER = 'x-whistle-rule-proto';
|
|
1166
1145
|
pluginVersion = '@' + options.version;
|
|
1167
1146
|
var wrapWsReader = function (socket, maxPayload) {
|
|
1168
1147
|
wrapTunnelReader(socket, true, maxPayload);
|
|
@@ -1206,6 +1185,7 @@ module.exports = async function (options, callback) {
|
|
|
1206
1185
|
var boundPort = config.port;
|
|
1207
1186
|
var PLUGIN_HOOKS = config.PLUGIN_HOOKS;
|
|
1208
1187
|
var RES_RULES_HEAD = config.RES_RULES_HEAD;
|
|
1188
|
+
var SHOW_LOGIN_BOX = config.SHOW_LOGIN_BOX;
|
|
1209
1189
|
var setResRules = function(headers, obj) {
|
|
1210
1190
|
var rules = formatRules(obj);
|
|
1211
1191
|
if (!rules) {
|
|
@@ -1218,34 +1198,19 @@ module.exports = async function (options, callback) {
|
|
|
1218
1198
|
});
|
|
1219
1199
|
headers[RES_RULES_HEAD] = encodeURIComponent(obj);
|
|
1220
1200
|
};
|
|
1221
|
-
|
|
1222
|
-
FROM_TUNNEL_HEADER = options.FROM_TUNNEL_HEADER;
|
|
1223
|
-
SNI_TYPE_HEADER = config.SNI_TYPE_HEADER;
|
|
1224
|
-
REMOTE_ADDR_HEAD = config.REMOTE_ADDR_HEAD;
|
|
1225
|
-
REMOTE_PORT_HEAD = config.REMOTE_PORT_HEAD;
|
|
1201
|
+
CLIENT_INFO_HEADER = config.CLIENT_INFO_HEADER;
|
|
1226
1202
|
PROXY_ID_HEADER = config.PROXY_ID_HEADER;
|
|
1227
|
-
REQ_FROM_HEADER = config.REQ_FROM_HEADER;
|
|
1228
|
-
options.REQ_FROM_HEADER = REQ_FROM_HEADER; // 兼容老逻辑
|
|
1229
1203
|
options.getTempFilePath = function(filePath) {
|
|
1230
1204
|
if (common.TEMP_PATH_RE.test(filePath)) {
|
|
1231
1205
|
return path.join(config.TEMP_FILES_PATH, RegExp.$1);
|
|
1232
1206
|
}
|
|
1233
1207
|
};
|
|
1234
1208
|
|
|
1235
|
-
GLOBAL_PLUGIN_VARS_HEAD = options.GLOBAL_PLUGIN_VARS_HEAD;
|
|
1236
|
-
PLUGIN_VARS_HEAD = options.PLUGIN_VARS_HEAD;
|
|
1237
|
-
UPGRADE_HEADER = config.UPGRADE_HEADER;
|
|
1238
|
-
delete config.UPGRADE_HEADER;
|
|
1239
1209
|
delete config.PLUGIN_HOOKS;
|
|
1240
1210
|
delete config.PROXY_ID_HEADER;
|
|
1241
|
-
delete config.
|
|
1242
|
-
delete config.REMOTE_PORT_HEAD;
|
|
1211
|
+
delete config.CLIENT_INFO_HEADER;
|
|
1243
1212
|
delete config.RES_RULES_HEAD;
|
|
1244
|
-
delete config.
|
|
1245
|
-
delete options.GLOBAL_PLUGIN_VARS_HEAD;
|
|
1246
|
-
delete options.PLUGIN_VARS_HEAD;
|
|
1247
|
-
delete options.FROM_TUNNEL_HEADER;
|
|
1248
|
-
delete options.SHOW_LOGIN_BOX;
|
|
1213
|
+
delete config.SHOW_LOGIN_BOX;
|
|
1249
1214
|
|
|
1250
1215
|
PLUGIN_HOOK_NAME_HEADER = config.PLUGIN_HOOK_NAME_HEADER;
|
|
1251
1216
|
options.shortName = pluginName.substring(pluginName.indexOf('/') + 1);
|
|
@@ -1264,12 +1229,6 @@ module.exports = async function (options, callback) {
|
|
|
1264
1229
|
sharedStorage = getSharedStorage(sharedFilePath);
|
|
1265
1230
|
options.sharedStorage = sharedStorage;
|
|
1266
1231
|
pluginOpts = options;
|
|
1267
|
-
Object.keys(options).forEach(function (key) {
|
|
1268
|
-
key = options[key];
|
|
1269
|
-
if (typeof key === 'string' && !key.indexOf('x-whistle-')) {
|
|
1270
|
-
pluginKeyMap[key] = 1;
|
|
1271
|
-
}
|
|
1272
|
-
});
|
|
1273
1232
|
var authKey = config.authKey;
|
|
1274
1233
|
delete config.authKey;
|
|
1275
1234
|
var headers = {
|
|
@@ -1296,7 +1255,7 @@ module.exports = async function (options, callback) {
|
|
|
1296
1255
|
alpnProtocol
|
|
1297
1256
|
) {
|
|
1298
1257
|
var type = uri && typeof uri;
|
|
1299
|
-
var headers, method;
|
|
1258
|
+
var headers, method, body;
|
|
1300
1259
|
if (type !== 'string') {
|
|
1301
1260
|
if (type === 'object') {
|
|
1302
1261
|
if (uri.headers) {
|
|
@@ -1304,6 +1263,7 @@ module.exports = async function (options, callback) {
|
|
|
1304
1263
|
}
|
|
1305
1264
|
method = typeof uri.method === 'string' ? uri.method : null;
|
|
1306
1265
|
opts = opts || uri;
|
|
1266
|
+
body = common.hasRequestBody(req) ? toBuffer(uri.body || uri.data) : null;
|
|
1307
1267
|
uri = uri.uri || uri.url || uri.href || curUrl;
|
|
1308
1268
|
} else {
|
|
1309
1269
|
if (type === 'function') {
|
|
@@ -1317,7 +1277,7 @@ module.exports = async function (options, callback) {
|
|
|
1317
1277
|
}
|
|
1318
1278
|
}
|
|
1319
1279
|
uri = parseUrl(uri);
|
|
1320
|
-
headers = headers ||
|
|
1280
|
+
headers = headers || req.headers;
|
|
1321
1281
|
if (isWs) {
|
|
1322
1282
|
headers.upgrade = headers.upgrade || 'websocket';
|
|
1323
1283
|
headers.connection = 'Upgrade';
|
|
@@ -1335,14 +1295,11 @@ module.exports = async function (options, callback) {
|
|
|
1335
1295
|
headers[PROXY_ID_HEADER] = 1;
|
|
1336
1296
|
uri.host = boundIp;
|
|
1337
1297
|
uri.port = boundPort;
|
|
1338
|
-
|
|
1339
|
-
headers[REMOTE_ADDR_HEAD] = req.originalReq.remoteAddress;
|
|
1340
|
-
headers[REMOTE_PORT_HEAD] = req.originalReq.remotePort;
|
|
1341
|
-
}
|
|
1298
|
+
addRemoteInfo(req, headers);
|
|
1342
1299
|
if (isHttps) {
|
|
1343
|
-
headers[
|
|
1300
|
+
headers[common.HTTPS_FIELD] = 1;
|
|
1344
1301
|
if (alpnProtocol) {
|
|
1345
|
-
headers[
|
|
1302
|
+
headers[common.ALPN_PROTOCOL_HEADER] = alpnProtocol;
|
|
1346
1303
|
}
|
|
1347
1304
|
}
|
|
1348
1305
|
isHttps = false;
|
|
@@ -1352,7 +1309,7 @@ module.exports = async function (options, callback) {
|
|
|
1352
1309
|
if (isHttps) {
|
|
1353
1310
|
if (opts.internalRequest) {
|
|
1354
1311
|
isHttps = false;
|
|
1355
|
-
headers[
|
|
1312
|
+
headers[common.HTTPS_FIELD] = 1;
|
|
1356
1313
|
} else {
|
|
1357
1314
|
uri.protocol = 'https:';
|
|
1358
1315
|
}
|
|
@@ -1361,7 +1318,7 @@ module.exports = async function (options, callback) {
|
|
|
1361
1318
|
delete uri.hostname;
|
|
1362
1319
|
uri.headers = formatRawHeaders(headers, req);
|
|
1363
1320
|
uri.agent = false;
|
|
1364
|
-
return [uri, cb, isHttps, opts];
|
|
1321
|
+
return [uri, cb, isHttps, opts, body];
|
|
1365
1322
|
};
|
|
1366
1323
|
|
|
1367
1324
|
var authPort,
|
|
@@ -1852,12 +1809,11 @@ module.exports = async function (options, callback) {
|
|
|
1852
1809
|
customHeaders[SHOW_LOGIN_BOX] = '1';
|
|
1853
1810
|
}
|
|
1854
1811
|
if (result === false) {
|
|
1855
|
-
customHeaders[
|
|
1812
|
+
customHeaders[common.AUTH_STATUS] = '1';
|
|
1856
1813
|
if (location) {
|
|
1857
1814
|
customHeaders.location = location;
|
|
1858
1815
|
} else if (htmlUrl) {
|
|
1859
|
-
customHeaders[
|
|
1860
|
-
encodeURIComponent(htmlUrl);
|
|
1816
|
+
customHeaders[common.AUTH_URL] = encodeURIComponent(htmlUrl);
|
|
1861
1817
|
} else if (typeof htmlBody === 'string') {
|
|
1862
1818
|
htmlBody = Buffer.from(htmlBody);
|
|
1863
1819
|
if (htmlBody.length > MAX_BODY_SIZE) {
|
|
@@ -2052,13 +2008,11 @@ module.exports = async function (options, callback) {
|
|
|
2052
2008
|
switch (getHookName(req)) {
|
|
2053
2009
|
case PLUGIN_HOOKS.AUTH:
|
|
2054
2010
|
if (authServer) {
|
|
2055
|
-
setContext(req);
|
|
2056
2011
|
authServer.emit('request', req, res);
|
|
2057
2012
|
}
|
|
2058
2013
|
break;
|
|
2059
2014
|
case PLUGIN_HOOKS.SNI:
|
|
2060
2015
|
if (sniServer) {
|
|
2061
|
-
setContext(req);
|
|
2062
2016
|
sniServer.emit('request', req, res);
|
|
2063
2017
|
}
|
|
2064
2018
|
break;
|
|
@@ -2071,7 +2025,7 @@ module.exports = async function (options, callback) {
|
|
|
2071
2025
|
case PLUGIN_HOOKS.HTTP:
|
|
2072
2026
|
if (httpServer) {
|
|
2073
2027
|
initReq(req, res, true);
|
|
2074
|
-
var alpnProtocol = req.headers[
|
|
2028
|
+
var alpnProtocol = req.headers[common.ALPN_PROTOCOL_HEADER];
|
|
2075
2029
|
var curUrl = req.originalReq.realUrl;
|
|
2076
2030
|
var svrRes = '';
|
|
2077
2031
|
var reqRules, resRules;
|
|
@@ -2115,25 +2069,30 @@ module.exports = async function (options, callback) {
|
|
|
2115
2069
|
uri = args[0];
|
|
2116
2070
|
cb = args[1];
|
|
2117
2071
|
opts = args[3];
|
|
2072
|
+
var reqBuff = args[4];
|
|
2118
2073
|
req.setRules = req.setReqRules = res.setReqRules = noop;
|
|
2119
2074
|
setReqRules(uri, getReqRules(opts, reqRules));
|
|
2120
2075
|
reqRules = null;
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2076
|
+
if (reqBuff && (!uri.headers || uri.headers['content-length'] != null)) {
|
|
2077
|
+
uri.headers = uri.headers || {};
|
|
2078
|
+
uri.headers['content-length'] = reqBuff.length;
|
|
2079
|
+
}
|
|
2080
|
+
var request = args[2] ? httpsRequest : httpRequest;
|
|
2081
|
+
var client = request(uri, function (_res) {
|
|
2082
|
+
svrRes = _res;
|
|
2083
|
+
res.once('_wroteHead', function () {
|
|
2084
|
+
appendTrailers(_res, res, opts && opts.trailers, req);
|
|
2085
|
+
});
|
|
2086
|
+
if (typeof cb === 'function') {
|
|
2087
|
+
cb.call(this, _res);
|
|
2088
|
+
} else {
|
|
2089
|
+
res.writeHead();
|
|
2090
|
+
_res.pipe(res);
|
|
2091
|
+
}
|
|
2092
|
+
}
|
|
2135
2093
|
);
|
|
2136
2094
|
addErrorHandler(req, client);
|
|
2095
|
+
reqBuff && client.end(reqBuff);
|
|
2137
2096
|
return client;
|
|
2138
2097
|
};
|
|
2139
2098
|
req.passThrough = function (uri, newTrailers) {
|
|
@@ -2158,11 +2117,7 @@ module.exports = async function (options, callback) {
|
|
|
2158
2117
|
var _request = function(reqBody, _uri) {
|
|
2159
2118
|
var client = req.request(_uri || uri, function (_res) {
|
|
2160
2119
|
var _response = function(resBody, trailers) {
|
|
2161
|
-
res.writeHead(
|
|
2162
|
-
_res.statusCode,
|
|
2163
|
-
_res.statusMessage,
|
|
2164
|
-
_res.headers
|
|
2165
|
-
);
|
|
2120
|
+
res.writeHead(_res.statusCode, _res.statusMessage, _res.headers);
|
|
2166
2121
|
appendTrailers(_res, res, trailers || newTrailers, req);
|
|
2167
2122
|
if (resBody === undefined) {
|
|
2168
2123
|
_res.pipe(res);
|
|
@@ -2186,7 +2141,7 @@ module.exports = async function (options, callback) {
|
|
|
2186
2141
|
if (transformRes) {
|
|
2187
2142
|
transformRes(common.wrapReadStream(_res), handleNextRes);
|
|
2188
2143
|
} else if (handleRes) {
|
|
2189
|
-
|
|
2144
|
+
readStream(_res, function(rawBuffer) {
|
|
2190
2145
|
resBuf = rawBuffer;
|
|
2191
2146
|
handleRes(rawBuffer, handleNextRes, _res);
|
|
2192
2147
|
});
|
|
@@ -2215,7 +2170,7 @@ module.exports = async function (options, callback) {
|
|
|
2215
2170
|
if (transformReq) {
|
|
2216
2171
|
transformReq(common.wrapReadStream(req), handleNextReq);
|
|
2217
2172
|
} else if (handleReq) {
|
|
2218
|
-
|
|
2173
|
+
readStream(req, function(rawBuffer) {
|
|
2219
2174
|
reqBuf = rawBuffer;
|
|
2220
2175
|
handleReq(rawBuffer, handleNextReq, req);
|
|
2221
2176
|
});
|
|
@@ -2285,11 +2240,7 @@ module.exports = async function (options, callback) {
|
|
|
2285
2240
|
resRules = rules;
|
|
2286
2241
|
return true;
|
|
2287
2242
|
};
|
|
2288
|
-
req.writeHead = socket.writeHead = function (
|
|
2289
|
-
code,
|
|
2290
|
-
msg,
|
|
2291
|
-
headers
|
|
2292
|
-
) {
|
|
2243
|
+
req.writeHead = socket.writeHead = function (code, msg, headers) {
|
|
2293
2244
|
code = code > 0 ? code : svrRes.statusCode || 101;
|
|
2294
2245
|
if (msg && typeof msg !== 'string') {
|
|
2295
2246
|
headers = headers || msg;
|
|
@@ -2443,7 +2394,6 @@ module.exports = async function (options, callback) {
|
|
|
2443
2394
|
}
|
|
2444
2395
|
|
|
2445
2396
|
server.on('connect', function (req, socket, head) {
|
|
2446
|
-
var isUp = isUpgrade(req);
|
|
2447
2397
|
var pipeServer;
|
|
2448
2398
|
switch (getHookName(req)) {
|
|
2449
2399
|
case PLUGIN_HOOKS.REQ_READ:
|
|
@@ -2482,7 +2432,7 @@ module.exports = async function (options, callback) {
|
|
|
2482
2432
|
socket.setRules = req.setResRules = socket.setResRules = noop;
|
|
2483
2433
|
req.writeHead = socket.writeHead = noop;
|
|
2484
2434
|
req.connect = function (uri, cb, opts) {
|
|
2485
|
-
var headers =
|
|
2435
|
+
var headers = req.headers;
|
|
2486
2436
|
var policy = headers['x-whistle-policy'];
|
|
2487
2437
|
if (common.isTunnelHost(uri)) {
|
|
2488
2438
|
headers.host = uri;
|
|
@@ -2518,11 +2468,7 @@ module.exports = async function (options, callback) {
|
|
|
2518
2468
|
headers[PROXY_ID_HEADER] = req[REQ_ID_KEY];
|
|
2519
2469
|
uri.host = boundIp;
|
|
2520
2470
|
uri.port = boundPort;
|
|
2521
|
-
|
|
2522
|
-
headers[REMOTE_ADDR_HEAD] =
|
|
2523
|
-
req.originalReq.remoteAddress;
|
|
2524
|
-
headers[REMOTE_PORT_HEAD] = req.originalReq.remotePort;
|
|
2525
|
-
}
|
|
2471
|
+
addRemoteInfo(req, headers);
|
|
2526
2472
|
} else {
|
|
2527
2473
|
uri.host = opts.host;
|
|
2528
2474
|
uri.port = opts.port > 0 ? opts.port : 80;
|
|
@@ -2542,7 +2488,7 @@ module.exports = async function (options, callback) {
|
|
|
2542
2488
|
});
|
|
2543
2489
|
return;
|
|
2544
2490
|
}
|
|
2545
|
-
if (_res.headers[
|
|
2491
|
+
if (_res.headers[common.ALLOW_ACK]) {
|
|
2546
2492
|
svrSock.write('1');
|
|
2547
2493
|
}
|
|
2548
2494
|
if (typeof cb === 'function') {
|
|
@@ -2567,12 +2513,12 @@ module.exports = async function (options, callback) {
|
|
|
2567
2513
|
}
|
|
2568
2514
|
break;
|
|
2569
2515
|
case PLUGIN_HOOKS.TUNNEL_REQ_READ:
|
|
2570
|
-
|
|
2516
|
+
initConnectReq(req, socket);
|
|
2517
|
+
pipeServer = req._isUpgrade ? wsReqRead : tunnelReqRead;
|
|
2571
2518
|
if (pipeServer) {
|
|
2572
|
-
initConnectReq(req, socket);
|
|
2573
2519
|
req.sendEstablished(function () {
|
|
2574
2520
|
socket.headers = req.headers;
|
|
2575
|
-
if (
|
|
2521
|
+
if (req._isUpgrade ? wsReqWrite : tunnelReqWrite) {
|
|
2576
2522
|
wrapTunnelWriter(socket);
|
|
2577
2523
|
}
|
|
2578
2524
|
pipeServer.emit('connect', req, socket, head);
|
|
@@ -2580,11 +2526,11 @@ module.exports = async function (options, callback) {
|
|
|
2580
2526
|
}
|
|
2581
2527
|
break;
|
|
2582
2528
|
case PLUGIN_HOOKS.TUNNEL_REQ_WRITE:
|
|
2583
|
-
|
|
2529
|
+
initConnectReq(req, socket);
|
|
2530
|
+
pipeServer = req._isUpgrade ? wsReqWrite : tunnelReqWrite;
|
|
2584
2531
|
if (pipeServer) {
|
|
2585
|
-
initConnectReq(req, socket);
|
|
2586
2532
|
req.sendEstablished(function () {
|
|
2587
|
-
if (
|
|
2533
|
+
if (req._isUpgrade ? wsReqRead : tunnelReqRead) {
|
|
2588
2534
|
wrapTunnelReader(socket);
|
|
2589
2535
|
}
|
|
2590
2536
|
pipeServer.emit('connect', req, socket, head);
|
|
@@ -2592,12 +2538,12 @@ module.exports = async function (options, callback) {
|
|
|
2592
2538
|
}
|
|
2593
2539
|
break;
|
|
2594
2540
|
case PLUGIN_HOOKS.TUNNEL_RES_READ:
|
|
2595
|
-
|
|
2541
|
+
initConnectReq(req, socket);
|
|
2542
|
+
pipeServer = req._isUpgrade ? wsResRead : tunnelResRead;
|
|
2596
2543
|
if (pipeServer) {
|
|
2597
|
-
initConnectReq(req, socket);
|
|
2598
2544
|
req.sendEstablished(function () {
|
|
2599
2545
|
socket.headers = req.headers;
|
|
2600
|
-
if (
|
|
2546
|
+
if (req._isUpgrade ? wsResWrite : tunnelResWrite) {
|
|
2601
2547
|
wrapTunnelWriter(socket);
|
|
2602
2548
|
}
|
|
2603
2549
|
pipeServer.emit('connect', req, socket, head);
|
|
@@ -2605,11 +2551,11 @@ module.exports = async function (options, callback) {
|
|
|
2605
2551
|
}
|
|
2606
2552
|
break;
|
|
2607
2553
|
case PLUGIN_HOOKS.TUNNEL_RES_WRITE:
|
|
2608
|
-
|
|
2554
|
+
initConnectReq(req, socket);
|
|
2555
|
+
pipeServer = req._isUpgrade ? wsResWrite : tunnelResWrite;
|
|
2609
2556
|
if (pipeServer) {
|
|
2610
|
-
initConnectReq(req, socket);
|
|
2611
2557
|
req.sendEstablished(function () {
|
|
2612
|
-
if (
|
|
2558
|
+
if (req._isUpgrade ? wsResRead : tunnelResRead) {
|
|
2613
2559
|
wrapTunnelReader(socket);
|
|
2614
2560
|
}
|
|
2615
2561
|
pipeServer.emit('connect', req, socket, head);
|
|
@@ -2627,6 +2573,40 @@ module.exports = async function (options, callback) {
|
|
|
2627
2573
|
initProxy(async function(proxy) {
|
|
2628
2574
|
options.connect = proxy.connect;
|
|
2629
2575
|
options.request = proxy.request;
|
|
2576
|
+
options.streamUtils = {
|
|
2577
|
+
readRawBuffer: readStream,
|
|
2578
|
+
readBuffer: function(stream, cb) {
|
|
2579
|
+
readStream(stream, function() {
|
|
2580
|
+
stream.getBuffer(function(err, buffer) {
|
|
2581
|
+
if (err) {
|
|
2582
|
+
return stream.emit('error', err);
|
|
2583
|
+
}
|
|
2584
|
+
cb(buffer);
|
|
2585
|
+
});
|
|
2586
|
+
});
|
|
2587
|
+
},
|
|
2588
|
+
readText: function(stream, cb) {
|
|
2589
|
+
readStream(stream, function() {
|
|
2590
|
+
stream.getText(function(err, buffer) {
|
|
2591
|
+
if (err) {
|
|
2592
|
+
return stream.emit('error', err);
|
|
2593
|
+
}
|
|
2594
|
+
cb(buffer);
|
|
2595
|
+
});
|
|
2596
|
+
});
|
|
2597
|
+
},
|
|
2598
|
+
readJson: function(stream, cb) {
|
|
2599
|
+
readStream(stream, function() {
|
|
2600
|
+
stream.getJson(function(err, data) {
|
|
2601
|
+
if (err) {
|
|
2602
|
+
return stream.emit('error', err);
|
|
2603
|
+
}
|
|
2604
|
+
cb(data);
|
|
2605
|
+
});
|
|
2606
|
+
});
|
|
2607
|
+
}
|
|
2608
|
+
};
|
|
2609
|
+
options.readStream = readStream;
|
|
2630
2610
|
options.requestInternal = function(options, cb) {
|
|
2631
2611
|
if (typeof options === 'string') {
|
|
2632
2612
|
options = { url: options };
|
|
@@ -2641,6 +2621,8 @@ module.exports = async function (options, callback) {
|
|
|
2641
2621
|
port: config.port
|
|
2642
2622
|
}), cb);
|
|
2643
2623
|
};
|
|
2624
|
+
compat.compatKeys(options);
|
|
2625
|
+
compat.compatKeys(config);
|
|
2644
2626
|
var initial = loadModule(path.join(options.value, 'initial.js')) ||
|
|
2645
2627
|
loadModule(path.join(options.value, 'initialize.js'));
|
|
2646
2628
|
if (initial && typeof initial !== 'function') {
|