whistle 2.9.15 → 2.9.16

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.
@@ -3,6 +3,7 @@ var gzip = require('zlib').gzip;
3
3
  var tls = require('tls');
4
4
  var crypto = require('crypto');
5
5
  var Buffer = require('safe-buffer').Buffer;
6
+ var extend = require('extend');
6
7
  var common = require('../../../lib/util/common');
7
8
  var config = require('../../../lib/config');
8
9
  var util = require('../../../lib/util');
@@ -16,6 +17,7 @@ var getRawHeaders = hparser.getRawHeaders;
16
17
  var getRawHeaderNames = hparser.getRawHeaderNames;
17
18
  var parseReq = hparser.parse;
18
19
  var MAX_LENGTH = 1024 * 512;
20
+ var MAX_REQ_COUNT = 100;
19
21
  var TLS_PROTOS = 'https:,wss:,tls:'.split(',');
20
22
  var PROXY_OPTS = {
21
23
  host: config.host || '127.0.0.1',
@@ -45,38 +47,53 @@ function drain(socket) {
45
47
  socket.on('data', util.noop);
46
48
  }
47
49
 
48
- function handleConnect(options, cb) {
50
+ function getReqCount(count) {
51
+ return count > 0 ? Math.min(count, MAX_REQ_COUNT) : 1;
52
+ }
53
+
54
+ function handleConnect(options, cb, count) {
55
+ count = getReqCount(count);
49
56
  options.headers['x-whistle-policy'] = 'tunnel';
50
- config.connect({
51
- host: options.hostname,
52
- port: options.port || 443,
53
- proxyHost: PROXY_OPTS.host,
54
- proxyPort: PROXY_OPTS.port,
55
- headers: options.headers
56
- }, function(socket, svrRes, err) {
57
- if (err) {
58
- return cb && cb(err);
57
+ var origOpts = options;
58
+ var lastIndex = count - 1;
59
+ for (var i = 0; i < count; i++) {
60
+ var execCb;
61
+ if (i === lastIndex) {
62
+ execCb = cb;
63
+ } else {
64
+ options = extend({}, origOpts);
59
65
  }
60
- if (!err) {
61
- if (TLS_PROTOS.indexOf(options.protocol) !== -1) {
62
- socket = tls.connect({
63
- rejectUnauthorized: config.rejectUnauthorized,
64
- socket: socket,
65
- servername: options.hostname
66
- });
66
+ config.connect({
67
+ host: options.hostname,
68
+ port: options.port || 443,
69
+ proxyHost: PROXY_OPTS.host,
70
+ proxyPort: PROXY_OPTS.port,
71
+ headers: options.headers
72
+ }, function(socket, svrRes, err) {
73
+ if (err) {
74
+ return execCb && execCb(err);
67
75
  }
68
- drain(socket);
69
- var data = options.body;
70
- if (data && data.length) {
71
- socket.write(data);
72
- options.body = data = null;
76
+ if (!err) {
77
+ if (TLS_PROTOS.indexOf(options.protocol) !== -1) {
78
+ socket = tls.connect({
79
+ rejectUnauthorized: config.rejectUnauthorized,
80
+ socket: socket,
81
+ servername: options.hostname
82
+ });
83
+ }
84
+ drain(socket);
85
+ var data = options.body;
86
+ if (data && data.length) {
87
+ socket.write(data);
88
+ options.body = data = null;
89
+ }
73
90
  }
74
- }
75
- cb && cb(null, {
76
- statusCode: svrRes.statusCode,
77
- headers: svrRes.headers
78
- });
79
- }).on('error', cb || util.noop);
91
+ execCb && execCb(null, {
92
+ statusCode: svrRes.statusCode,
93
+ headers: svrRes.headers
94
+ });
95
+ }).on('error', execCb || util.noop);
96
+ }
80
97
  }
81
98
 
82
99
  function getReqRaw(options) {
@@ -86,52 +103,64 @@ function getReqRaw(options) {
86
103
  return raw.join('\r\n') + '\r\n\r\n';
87
104
  }
88
105
 
89
- function handleWebSocket(options, cb) {
106
+ function handleWebSocket(options, cb, count) {
107
+ count = getReqCount(count);
90
108
  if (options.protocol === 'https:' || options.protocol === 'wss:') {
91
109
  options.headers[config.HTTPS_FIELD] = 1;
92
110
  }
93
111
  var binary = !!options.headers['x-whistle-frame-binary'];
94
112
  delete options.headers['x-whistle-frame-binary'];
95
- util.connect(PROXY_OPTS, function(err, socket) {
96
- if (err) {
97
- cb && cb(err);
113
+ var origOpts = options;
114
+ var lastIndex = count - 1;
115
+ for (var i = 0; i < count; i++) {
116
+ var execCb;
117
+ if (i === lastIndex) {
118
+ execCb = cb;
98
119
  } else {
99
- socket.write(getReqRaw(options));
100
- var data = options.body;
101
- if ((!data || !data.length) && !cb) {
102
- return drain(socket);
103
- }
104
- parseReq(socket, function(e) {
105
- if (e) {
106
- socket.destroy();
107
- return cb && cb(e);
120
+ options = extend({}, origOpts);
121
+ }
122
+ util.connect(PROXY_OPTS, function(err, socket) {
123
+ if (err) {
124
+ execCb && execCb(err);
125
+ } else {
126
+ socket.write(getReqRaw(options));
127
+ var data = options.body;
128
+ if ((!data || !data.length) && !cb) {
129
+ return drain(socket);
108
130
  }
109
- var statusCode = socket.statusCode;
110
- if (statusCode == 101) {
111
- var sender = getSender(socket);
112
- if (data) {
113
- sender.send(data, {
114
- mask: true,
115
- binary: binary
116
- }, util.noop);
117
- options.body = data = null;
131
+ parseReq(socket, function(e) {
132
+ if (e) {
133
+ socket.destroy();
134
+ return execCb && execCb(e);
118
135
  }
119
- socket.body = '';
120
- drain(socket);
121
- } else {
122
- socket.destroy();
123
- }
124
- cb && cb(null, {
125
- statusCode: statusCode,
126
- headers: socket.headers || {},
127
- body: socket.body || ''
128
- });
129
- }, true);
130
- }
131
- });
136
+ var statusCode = socket.statusCode;
137
+ if (statusCode == 101) {
138
+ var sender = getSender(socket);
139
+ if (data) {
140
+ sender.send(data, {
141
+ mask: true,
142
+ binary: binary
143
+ }, util.noop);
144
+ options.body = data = null;
145
+ }
146
+ socket.body = '';
147
+ drain(socket);
148
+ } else {
149
+ socket.destroy();
150
+ }
151
+ execCb && execCb(null, {
152
+ statusCode: statusCode,
153
+ headers: socket.headers || {},
154
+ body: socket.body || ''
155
+ });
156
+ }, true);
157
+ }
158
+ });
159
+ }
132
160
  }
133
161
 
134
- function handleHttp(options, cb) {
162
+ function handleHttp(options, cb, count) {
163
+ count = getReqCount(count);
135
164
  if (options.protocol === 'https:') {
136
165
  options.headers[config.HTTPS_FIELD] = 1;
137
166
  }
@@ -139,46 +168,56 @@ function handleHttp(options, cb) {
139
168
  options.hostname = null;
140
169
  options.host = PROXY_OPTS.host;
141
170
  options.port = PROXY_OPTS.port;
142
- var client = http.request(options, function(res) {
143
- if (cb) {
144
- res.on('error', cb);
145
- var buffer;
146
- res.on('data', function(data) {
147
- if (buffer !== null) {
148
- buffer = buffer ? Buffer.concat([buffer, data]) : data;
149
- if (buffer.length > MAX_LENGTH) {
150
- buffer = null;
151
- }
152
- }
153
- });
154
- res.on('end', function() {
155
- zlib.unzip(res.headers['content-encoding'], buffer, function(err, body) {
156
- var headers = res.headers;
157
- if (typeof headers.trailer === 'string' && headers.trailer.indexOf(',') !== -1) {
158
- headers.trailer = headers.trailer.split(',');
159
- }
160
- var result = {
161
- statusCode: res.statusCode,
162
- headers: headers,
163
- trailers: res.trailers,
164
- rawHeaderNames: getRawHeaderNames(res.rawHeaders),
165
- rawTrailerNames: getRawHeaderNames(res.rawTrailers)
166
- };
167
- if (err) {
168
- result.body = err.stack;
169
- } else if (body) {
170
- result.base64 = body.toString('base64');
171
- }
172
- cb(null, result);
173
- });
174
- });
171
+ var origOpts = options;
172
+ var lastIndex = count - 1;
173
+ for (var i = 0; i < count; i++) {
174
+ var execCb;
175
+ if (i === lastIndex) {
176
+ execCb = cb;
175
177
  } else {
176
- drain(res);
178
+ options = extend({}, origOpts);
177
179
  }
178
- });
179
- client.on('error', cb || util.noop);
180
- client.end(options.body);
181
- options.body = null;
180
+ var client = http.request(options, function(res) {
181
+ if (execCb) {
182
+ res.on('error', execCb);
183
+ var buffer;
184
+ res.on('data', function(data) {
185
+ if (buffer !== null) {
186
+ buffer = buffer ? Buffer.concat([buffer, data]) : data;
187
+ if (buffer.length > MAX_LENGTH) {
188
+ buffer = null;
189
+ }
190
+ }
191
+ });
192
+ res.on('end', function() {
193
+ zlib.unzip(res.headers['content-encoding'], buffer, function(err, body) {
194
+ var headers = res.headers;
195
+ if (typeof headers.trailer === 'string' && headers.trailer.indexOf(',') !== -1) {
196
+ headers.trailer = headers.trailer.split(',');
197
+ }
198
+ var result = {
199
+ statusCode: res.statusCode,
200
+ headers: headers,
201
+ trailers: res.trailers,
202
+ rawHeaderNames: getRawHeaderNames(res.rawHeaders),
203
+ rawTrailerNames: getRawHeaderNames(res.rawTrailers)
204
+ };
205
+ if (err) {
206
+ result.body = err.stack;
207
+ } else if (body) {
208
+ result.base64 = body.toString('base64');
209
+ }
210
+ execCb(null, result);
211
+ });
212
+ });
213
+ } else {
214
+ drain(res);
215
+ }
216
+ });
217
+ client.on('error', execCb || util.noop);
218
+ client.end(options.body);
219
+ options.body = null;
220
+ }
182
221
  }
183
222
 
184
223
  function getCharset(headers) {
@@ -296,13 +335,15 @@ module.exports = function(req, res) {
296
335
  if (err) {
297
336
  return handleResponse && handleResponse(err);
298
337
  }
338
+ var count = req.body.repeatCount;
339
+ count = count > 0 ? count : req.body.repeatTimes;
299
340
  if (isWs) {
300
341
  options.method = 'GET';
301
- handleWebSocket(options, handleResponse);
342
+ handleWebSocket(options, handleResponse, count);
302
343
  } else if (isConn) {
303
- handleConnect(options, handleResponse);
344
+ handleConnect(options, handleResponse, count);
304
345
  } else {
305
- handleHttp(options, handleResponse);
346
+ handleHttp(options, handleResponse, count);
306
347
  }
307
348
  if (!handleResponse) {
308
349
  res.json({ec: 0, em: 'success'});
@@ -8,6 +8,6 @@
8
8
  </head>
9
9
  <body style="overscroll-behavior-x: none;">
10
10
  <div id="container" class="main"></div>
11
- <script src="js/index.js?v=2.9.15"></script>
11
+ <script src="js/index.js?v=2.9.16"></script>
12
12
  </body>
13
13
  </html>