whistle 2.9.14 → 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.
package/bin/ca/cli.js ADDED
@@ -0,0 +1,95 @@
1
+ var net = require('net');
2
+ var fs = require('fs');
3
+ var path = require('path');
4
+ var installRootCA = require('./index');
5
+ var util = require('../util');
6
+ var fileMgr = require('../../lib/util/file-mgr');
7
+ var httpMgr = require('../../lib/util/http-mgr');
8
+ var commonUtil = require('../../lib/util/common');
9
+ var config = require('../../lib/config');
10
+
11
+ var NUM_RE = /^\d+$/;
12
+ var HOST_SUFFIX_RE = /\:(\d+|auto)?$/;
13
+ var HOST_RE = /^[a-z\d_-]+(?:\.[a-z\d_-]+)*$/i;
14
+ var URL_RE = /^https?:\/\/./i;
15
+ var MAX_LEN = 1024 * 1024;
16
+
17
+ function installCert(certFile, url) {
18
+ try {
19
+ installRootCA(fileMgr.convertSlash(certFile));
20
+ util.info('Install root CA (' + (url || certFile) + ') successful.');
21
+ } catch (e) {
22
+ util.error(e.message);
23
+ }
24
+ }
25
+
26
+ function install(addr) {
27
+ if (addr.file) {
28
+ return installCert(addr.file);
29
+ }
30
+ addr.needRawData = true;
31
+ addr.maxLength = MAX_LEN;
32
+ addr.headers = {
33
+ 'user-agent': 'whistle/' + config.name
34
+ };
35
+ httpMgr.request(addr, function(err, body, res) {
36
+ if (err) {
37
+ return util.error(err.message);
38
+ }
39
+ if (res.statusCode != 200) {
40
+ return util.error('Bad response (' + res.statusCode + ').');
41
+ }
42
+ if (!body || !body.length) {
43
+ return util.error('No content.');
44
+ }
45
+ var tempFile = path.join(commonUtil.getWhistlePath(), Date.now() + '-' + util.getHash(addr.url) + '.crt');
46
+ fs.writeFileSync(tempFile, body);
47
+ installCert(tempFile, addr.url);
48
+ fs.unlinkSync(tempFile);
49
+ });
50
+ }
51
+
52
+ module.exports = function(argv) {
53
+ var options = {};
54
+ argv.forEach(function(arg) {
55
+ if (NUM_RE.test(arg)) {
56
+ delete options.addr;
57
+ options.port = parseInt(arg, 10) || options.port;
58
+ } else if (net.isIP(arg)) {
59
+ delete options.addr;
60
+ options.host = arg || options.host;
61
+ } else if (HOST_SUFFIX_RE.test(arg)) {
62
+ delete options.port;
63
+ delete options.addr;
64
+ var port = RegExp.$1;
65
+ if (port > 0) {
66
+ options.port = parseInt(port, 10) || options.port;
67
+ }
68
+ var host = arg.slice(0, - port.length - 1);
69
+ if (host[0] === '[') {
70
+ host = host.substring(1);
71
+ }
72
+ var lastIndex = host.length - 1;
73
+ if (host[lastIndex] === ']') {
74
+ host = host.substring(0, lastIndex);
75
+ }
76
+ if (host && (net.isIP(host) || HOST_RE.test(host))) {
77
+ options.host = host || options.host;
78
+ }
79
+ } else {
80
+ delete options.port;
81
+ delete options.host;
82
+ if (URL_RE.test(arg)) {
83
+ options.addr = { url: arg };
84
+ } else {
85
+ options.addr = { file: arg };
86
+ }
87
+ }
88
+ });
89
+ if (!options.addr) {
90
+ var host = options.host || '127.0.0.1';
91
+ var port = options.port || util.getDefaultPort();
92
+ options.addr = { url: 'http://' + host + ':' + port + '/cgi-bin/rootca' };
93
+ }
94
+ install(options.addr);
95
+ };
@@ -0,0 +1 @@
1
+ export default function (certFile: String): void;
@@ -0,0 +1,43 @@
1
+ var spawnSync = require('child_process').spawnSync;
2
+
3
+ function checkSuccess(result) {
4
+ var stderr = result.stderr;
5
+ if (stderr && stderr.length) {
6
+ throw new Error(stderr + '');
7
+ }
8
+ }
9
+
10
+ function getKeyChain() {
11
+ var result = spawnSync('security', ['default-keychain']);
12
+ checkSuccess(result);
13
+ return (result.stdout + '').split('"')[1];
14
+ }
15
+
16
+ function installMac(certPath) {
17
+ var result = spawnSync('security', ['add-trusted-cert', '-k', getKeyChain(), certPath]);
18
+ checkSuccess(result);
19
+ var msg = result.stdout + '';
20
+ if (/Error:/i.test(msg)) {
21
+ throw new Error(msg);
22
+ }
23
+ }
24
+
25
+
26
+ function installWin(certFile) {
27
+ var result = spawnSync('certutil', ['-addstore', '-user', 'Root', certFile]);
28
+ checkSuccess(result);
29
+ if (/ERROR_CANCELLED/i.test(result.stdout + '')) {
30
+ throw new Error('The authorization was canceled by the user.');
31
+ }
32
+ }
33
+
34
+ module.exports = function(certFile) {
35
+ var platform = process.platform;
36
+ if (platform === 'darwin') {
37
+ return installMac(certFile);
38
+ }
39
+ if (platform === 'win32') {
40
+ return installWin(certFile);
41
+ }
42
+ throw new Error('Platform ' + platform + ' is unsupported to install root CA for now.');
43
+ };
package/bin/proxy/cli.js CHANGED
@@ -2,33 +2,33 @@ var net = require('net');
2
2
  var proxy = require('./index');
3
3
  var util = require('../util');
4
4
 
5
- var readConfig = util.readConfig;
6
5
  var OFF_RE = /^(?:o|0|-{0,2}off)$/i;
7
6
  var BYPASS_RE = /^(?:-{0,2}bypass|-x|-b)$/i;
8
7
  var NUM_RE = /^\d+$/;
9
8
  var HOST_SUFFIX_RE = /\:(\d+|auto)?$/;
10
9
  var HOST_RE = /^[a-z\d_-]+(?:\.[a-z\d_-]+)*$/i;
11
10
 
12
- function getDefaultPort() {
13
- var conf = readConfig();
14
- conf = conf && conf.options;
15
- var port = conf && conf.port;
16
- return port > 0 ? port : 8899;
17
- }
18
-
19
11
  function enableProxy(options) {
20
- if (proxy.enableProxy(options)) {
21
- util.info('Setting global proxy (' + options.host + ':' + options.port + ') successful.');
22
- } else {
23
- util.error('Failed to set global proxy (' + options.host + ':' + options.port + ').');
12
+ try {
13
+ if (proxy.enableProxy(options)) {
14
+ util.info('Setting global proxy (' + options.host + ':' + options.port + ') successful.');
15
+ } else {
16
+ util.error('Failed to set global proxy (' + options.host + ':' + options.port + ').');
17
+ }
18
+ } catch (e) {
19
+ util.error(e.message);
24
20
  }
25
21
  }
26
22
 
27
23
  function disableProxy() {
28
- if (proxy.disableProxy()) {
29
- util.info('Turn off global proxy successful.');
30
- } else {
31
- util.error('Failed to turn off global proxy.');
24
+ try {
25
+ if (proxy.disableProxy()) {
26
+ util.info('Turn off global proxy successful.');
27
+ } else {
28
+ util.error('Failed to turn off global proxy.');
29
+ }
30
+ } catch (e) {
31
+ util.error(e.message);
32
32
  }
33
33
  }
34
34
 
@@ -69,7 +69,7 @@ module.exports = function(argv) {
69
69
  }
70
70
  });
71
71
  if (!options.port) {
72
- options.port = getDefaultPort();
72
+ options.port = util.getDefaultPort();
73
73
  }
74
74
  options.host = options.host || '127.0.0.1';
75
75
  enableProxy(options);
package/bin/util.js CHANGED
@@ -7,12 +7,13 @@ var config = require('../lib/config');
7
7
  var colors = require('colors/safe');
8
8
  var path = require('path');
9
9
  var createHmac = require('crypto').createHmac;
10
+
10
11
  /*eslint no-console: "off"*/
11
12
  var CHECK_RUNNING_CMD = process.platform === 'win32' ?
12
13
  'tasklist /fi "PID eq %s" | findstr /i "node.exe"'
13
14
  : 'ps -f -p %s | grep "node"';
14
15
  var isWin = process.platform === 'win32';
15
-
16
+
16
17
  function isRunning(pid, callback) {
17
18
  pid ? cp.exec(util.format(CHECK_RUNNING_CMD, pid),
18
19
  function (err, stdout, stderr) {
@@ -88,6 +89,15 @@ function showUsage(isRunning, options, restart) {
88
89
  if (parseInt(process.version.slice(1), 10) < 6) {
89
90
  warn(colors.bold('\nWarning: The current Node version is too low, access https://nodejs.org to install the latest version, or may not be able to Capture HTTPS CONNECTs\n'));
90
91
  }
92
+ var bypass = options.init;
93
+ if (bypass == null) {
94
+ return;
95
+ }
96
+ return {
97
+ host: options.host || '127.0.0.1',
98
+ port: port,
99
+ bypass: typeof bypass === 'string' ? bypass : undefined
100
+ };
91
101
  }
92
102
 
93
103
  exports.showUsage = showUsage;
@@ -146,4 +156,11 @@ exports.readConfigList = readConfigList;
146
156
  exports.getHash = function(str) {
147
157
  var hmac = createHmac('sha256', 'a secret');
148
158
  return hmac.update(str).digest('hex');
149
- };
159
+ };
160
+
161
+ exports.getDefaultPort = function () {
162
+ var conf = readConfig();
163
+ conf = conf && conf.options;
164
+ var port = conf && conf.port;
165
+ return port > 0 ? port : 8899;
166
+ };
package/bin/whistle.js CHANGED
@@ -8,14 +8,29 @@ var showStatus = require('./status');
8
8
  var util = require('./util');
9
9
  var plugin = require('./plugin');
10
10
  var setProxy = require('./proxy/cli');
11
+ var installCA = require('./ca/cli');
11
12
 
12
- var showUsage = util.showUsage;
13
13
  var error = util.error;
14
14
  var info = util.info;
15
+ var hasInit;
16
+
17
+ function handleEnd(err, options, restart) {
18
+ options = util.showUsage(err, options, restart);
19
+ if (!options || !hasInit) {
20
+ return;
21
+ }
22
+ var host = options.host + ':' + options.port;
23
+ var argv = [host];
24
+ if (options.bypass) {
25
+ argv.push('-x', options.bypass);
26
+ }
27
+ setProxy(argv);
28
+ installCA([host]);
29
+ }
15
30
 
16
31
  function showStartupInfo(err, options, debugMode, restart) {
17
32
  if (!err || err === true) {
18
- return showUsage(err, options, restart);
33
+ return handleEnd(err, options, restart);
19
34
  }
20
35
  if (/listen EADDRINUSE/.test(err)) {
21
36
  options = util.formatOptions(options);
@@ -55,7 +70,7 @@ program.setConfig({
55
70
  showStartupInfo(err, options, true);
56
71
  return;
57
72
  }
58
- showUsage(false, options);
73
+ handleEnd(false, options);
59
74
  console.log('Press [Ctrl+C] to stop ' + config.name + '...');
60
75
  },
61
76
  startCallback: showStartupInfo,
@@ -85,6 +100,8 @@ program
85
100
  .description('Add rules from local js file (.whistle.js by default)');
86
101
  program.command('proxy')
87
102
  .description('Set global proxy');
103
+ program.command('ca')
104
+ .description('Install root CA');
88
105
  program.command('install')
89
106
  .description('Install whistle plugin');
90
107
  program.command('uninstall')
@@ -117,6 +134,7 @@ program
117
134
  .option('-R, --reqCacheSize [reqCacheSize]', 'set the cache size of request data (600 by default)', String, undefined)
118
135
  .option('-F, --frameCacheSize [frameCacheSize]', 'set the cache size of webSocket and socket\'s frames (512 by default)', String, undefined)
119
136
  .option('-A, --addon [pluginPaths]', 'add custom plugin paths', String, undefined)
137
+ .option('--init [bypass]', 'auto set global proxy (and bypass) and install root CA')
120
138
  .option('--config [workers]', 'start the cluster server and set worker number (os.cpus().length by default)', String, undefined)
121
139
  .option('--cluster [config]', 'load the startup config from a local file', String, undefined)
122
140
  .option('--dnsServer [dnsServer]', 'set custom dns servers', String, undefined)
@@ -135,6 +153,10 @@ var removeItem = function(list, name) {
135
153
  var i = list.indexOf(name);
136
154
  i !== -1 && list.splice(i, 1);
137
155
  };
156
+ if (argv.indexOf('--init') !== -1) {
157
+ hasInit = true;
158
+ process.env.WHISTLE_MODE = (process.env.WHISTLE_MODE || '') + '|persistentCapture';
159
+ }
138
160
  if (cmd === 'status') {
139
161
  var all = argv[3] === '--all' || argv[3] === '-l';
140
162
  if (argv[3] === '-S') {
@@ -143,6 +165,8 @@ if (cmd === 'status') {
143
165
  showStatus(all, storage);
144
166
  } else if (cmd === 'proxy') {
145
167
  setProxy(Array.prototype.slice.call(argv, 3));
168
+ } else if (cmd === 'ca') {
169
+ installCA(Array.prototype.slice.call(argv, 3));
146
170
  } else if (/^([a-z]{1,2})?uni(nstall)?$/.test(cmd)) {
147
171
  plugin.uninstall(Array.prototype.slice.call(argv, 3));
148
172
  } else if (/^([a-z]{1,2})?i(nstall)?$/.test(cmd)) {
@@ -2,7 +2,7 @@ var ca = require('../../../../lib/https/ca');
2
2
 
3
3
 
4
4
  module.exports = function(req, res) {
5
- ca.removeCert(req.body.filename);
5
+ ca.removeCert(req.body);
6
6
  var isparsed = req.query.dataType === 'parsed';
7
7
  res.json(isparsed ? ca.getCustomCertsInfo() : ca.getCustomCertsFiles());
8
8
  };
@@ -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'});
@@ -1,5 +1,9 @@
1
1
  var getRootCAFile = require('../../../lib/https/ca').getRootCAFile;
2
2
 
3
3
  module.exports = function(req, res) {
4
- res.download(getRootCAFile(), 'rootCA.' + (req.query.type === 'cer' ? 'cer' : 'crt'));
4
+ var type = req.query.type;
5
+ if (type !== 'cer' && type !== 'pem') {
6
+ type = 'crt';
7
+ }
8
+ res.download(getRootCAFile(), 'rootCA.' + type);
5
9
  };
Binary file
@@ -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.14"></script>
11
+ <script src="js/index.js?v=2.9.16"></script>
12
12
  </body>
13
13
  </html>