diff --git a/.eslintrc.js b/.eslintrc.js index 900d2edbd..6f71dd4c2 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -6,7 +6,7 @@ module.exports = { "rules": { "indent": [ "error", - "tab" + 2 ], "quotes": [ "error", diff --git a/bin/whistle.js b/bin/whistle.js index 40fe586fa..653767f25 100755 --- a/bin/whistle.js +++ b/bin/whistle.js @@ -8,97 +8,97 @@ var util = require('../lib/util'); var colors = require('colors/safe'); function getIpList() { - var ipList = []; - var ifaces = os.networkInterfaces(); - Object.keys(ifaces).forEach(function(ifname) { - ifaces[ifname].forEach(function (iface) { - if (iface.family == 'IPv4') { - ipList.push(iface.address); + var ipList = []; + var ifaces = os.networkInterfaces(); + Object.keys(ifaces).forEach(function(ifname) { + ifaces[ifname].forEach(function (iface) { + if (iface.family == 'IPv4') { + ipList.push(iface.address); } }); }); - return ipList; + return ipList; } function error(msg) { - console.log(colors.red(msg)); + console.log(colors.red(msg)); } function warn(msg) { - console.log(colors.yellow(msg)); + console.log(colors.yellow(msg)); } function info(msg) { - console.log(colors.green(msg)); + console.log(colors.green(msg)); } function showUsage(isRunning, options, restart) { - var port = options.port || config.port; - if (isRunning) { - warn('[!] ' + config.name + ' is running'); + var port = options.port || config.port; + if (isRunning) { + warn('[!] ' + config.name + ' is running'); } else { - info('[i] ' + config.name + (restart ? ' restarted' : ' started')); + info('[i] ' + config.name + (restart ? ' restarted' : ' started')); } - info('[i] First, use your device to visit the following URL list, gets the ' + colors.bold('IP') + ' of the URL you can visit:'); - info(getIpList().map(function(ip) { - return ' http://' + colors.bold(ip) + (port ? ':' + port : '') + '/'; + info('[i] First, use your device to visit the following URL list, gets the ' + colors.bold('IP') + ' of the URL you can visit:'); + info(getIpList().map(function(ip) { + return ' http://' + colors.bold(ip) + (port ? ':' + port : '') + '/'; }).join('\n')); - warn(' Note: If the following URLs are unable to access, check the server\'s firewall settings'); - warn(' For more information, please visit ' + colors.bold('https://github.com/avwo/whistle')); - info('[i] Second, configure your device to use ' + config.name + ' as its HTTP and HTTPS proxy on ' + colors.bold('IP:') + port); - info('[i] Last, use ' + colors.bold('Chrome') + ' to visit ' + colors.bold('http://' + (options.localUIHost || config.localUIHost) + '/') + ' to get started'); + warn(' Note: If the following URLs are unable to access, check the server\'s firewall settings'); + warn(' For more information, please visit ' + colors.bold('https://github.com/avwo/whistle')); + info('[i] Second, configure your device to use ' + config.name + ' as its HTTP and HTTPS proxy on ' + colors.bold('IP:') + port); + info('[i] Last, use ' + colors.bold('Chrome') + ' to visit ' + colors.bold('http://' + (options.localUIHost || config.localUIHost) + '/') + ' to get started'); } function showStartupInfo(err, options, debugMode, restart) { - if (!err || err === true) { - return showUsage(err, options, restart); + if (!err || err === true) { + return showUsage(err, options, restart); } - if (/listen EADDRINUSE/.test(err)) { - error('[!] Failed to bind proxy port ' + (options.port || config.port) + ': The port is already in use'); - info('[i] Please check if ' + config.name + ' is already running, you can ' + (debugMode ? 'stop whistle with `w2 stop` first' : 'restart whistle with `w2 restart`')); - info(' or if another application is using the port, you can change the port with ' + (debugMode ? '`w2 run -p newPort`\n' : '`w2 start -p newPort`\n')); + if (/listen EADDRINUSE/.test(err)) { + error('[!] Failed to bind proxy port ' + (options.port || config.port) + ': The port is already in use'); + info('[i] Please check if ' + config.name + ' is already running, you can ' + (debugMode ? 'stop whistle with `w2 stop` first' : 'restart whistle with `w2 restart`')); + info(' or if another application is using the port, you can change the port with ' + (debugMode ? '`w2 run -p newPort`\n' : '`w2 start -p newPort`\n')); } else if (err.code == 'EACCES' || err.code == 'EPERM') { - error('[!] Cannot start ' + config.name + ' owned by root'); - info('[i] Try to run command with `sudo`\n'); + error('[!] Cannot start ' + config.name + ' owned by root'); + info('[i] Try to run command with `sudo`\n'); } - error(err.stack ? 'Date: ' + util.formatDate() + '\n' + err.stack : err); + error(err.stack ? 'Date: ' + util.formatDate() + '\n' + err.stack : err); } program.setConfig({ - main: function(options) { - var hash = options && options.storage && encodeURIComponent(options.storage); - return path.join(__dirname, '../index.js') + (hash ? '#' + hash + '#' : ''); + main: function(options) { + var hash = options && options.storage && encodeURIComponent(options.storage); + return path.join(__dirname, '../index.js') + (hash ? '#' + hash + '#' : ''); }, - name: config.name, - version: config.version, - runCallback: function(err, options) { - if (err) { - showStartupInfo(err, options, true); - return; + name: config.name, + version: config.version, + runCallback: function(err, options) { + if (err) { + showStartupInfo(err, options, true); + return; } - showUsage(false, options); - console.log('Press [Ctrl+C] to stop ' + config.name + '...'); + showUsage(false, options); + console.log('Press [Ctrl+C] to stop ' + config.name + '...'); }, - startCallback: showStartupInfo, - restartCallback: function(err, options) { - showStartupInfo(err, options, false, true); + startCallback: showStartupInfo, + restartCallback: function(err, options) { + showStartupInfo(err, options, false, true); }, - stopCallback: function(err) { - if (err === true) { - info('[i] ' + config.name + ' killed.'); + stopCallback: function(err) { + if (err === true) { + info('[i] ' + config.name + ' killed.'); } else if (err) { - if (err.code === 'EPERM') { - error('[!] Cannot kill ' + config.name + ' owned by root'); - info('[i] Try to run command with `sudo`'); + if (err.code === 'EPERM') { + error('[!] Cannot kill ' + config.name + ' owned by root'); + info('[i] Try to run command with `sudo`'); } else { - error('[!] ' + err.message); + error('[!] ' + err.message); } } else { - warn('[!] No running ' + config.name); + warn('[!] No running ' + config.name); } } }); diff --git a/biz/index.js b/biz/index.js index 736ceafc4..702d3c706 100644 --- a/biz/index.js +++ b/biz/index.js @@ -4,68 +4,68 @@ var http = require('http'); var util = require('../lib/util'); function request(req, res, port, weinre) { - var options = url.parse(util.getFullUrl(req)); - if (options.protocol == 'https:') { - options.protocol = 'http:'; - req.headers['x-whistle-https'] = 'true'; + var options = url.parse(util.getFullUrl(req)); + if (options.protocol == 'https:') { + options.protocol = 'http:'; + req.headers['x-whistle-https'] = 'true'; } - options.host = '127.0.0.1'; - options.method = req.method; - options.hostname = null; - options.protocol = null; - if (port) { - options.port = port; + options.host = '127.0.0.1'; + options.method = req.method; + options.hostname = null; + options.protocol = null; + if (port) { + options.port = port; } - req.headers['x-forwarded-for'] = req.clientIp; - options.headers = req.headers; - req.pipe(http.request(options, function(_res) { - if (weinre && options.pathname == '/target/target-script-min.js') { - _res.headers['access-control-allow-origin'] = '*'; + req.headers['x-forwarded-for'] = req.clientIp; + options.headers = req.headers; + req.pipe(http.request(options, function(_res) { + if (weinre && options.pathname == '/target/target-script-min.js') { + _res.headers['access-control-allow-origin'] = '*'; } - if (util.getStatusCode(_res.statusCode)) { - res.writeHead(_res.statusCode, _res.headers); - res.src(_res); - _res.trailers && res.addTrailers(_res.trailers); + if (util.getStatusCode(_res.statusCode)) { + res.writeHead(_res.statusCode, _res.headers); + res.src(_res); + _res.trailers && res.addTrailers(_res.trailers); } else { - util.sendStatusCodeError(res, _res); + util.sendStatusCodeError(res, _res); } })); } module.exports = function(req, res, next) { - var config = this.config; - var host = (req.headers.host || '').split(':'); - var port = host[1] || 80; - host = host[0]; - if (net.isIP(host) && util.isLocalAddress(host)) { - if (port == config.port || port == config.uiport) { - host = config.localUIHost; + var config = this.config; + var host = (req.headers.host || '').split(':'); + var port = host[1] || 80; + host = host[0]; + if (net.isIP(host) && util.isLocalAddress(host)) { + if (port == config.port || port == config.uiport) { + host = config.localUIHost; } else if (port == config.weinreport) { - host = config.WEINRE_HOST; + host = config.WEINRE_HOST; } } - var pluginMgr = this.pluginMgr; - var pluginHomePage; - if (host == config.localUIHost) { - request(req, res, config.uiport); + var pluginMgr = this.pluginMgr; + var pluginHomePage; + if (host == config.localUIHost) { + request(req, res, config.uiport); } else if (host == config.WEINRE_HOST) { - request(req, res, config.weinreport, true); + request(req, res, config.weinreport, true); } else if (pluginHomePage = pluginMgr.getPluginByHomePage(util.getFullUrl(req))) { - pluginMgr.loadPlugin(pluginHomePage, function(err, ports) { - if (err || !ports.uiPort) { - res.response(util.wrapResponse({ - statusCode: err ? 503 : 501, - headers: { - 'content-type': 'text/plain; charset=utf-8' + pluginMgr.loadPlugin(pluginHomePage, function(err, ports) { + if (err || !ports.uiPort) { + res.response(util.wrapResponse({ + statusCode: err ? 503 : 501, + headers: { + 'content-type': 'text/plain; charset=utf-8' }, - body: err || 'Not implemented' + body: err || 'Not implemented' })); - return; + return; } - request(req, res, ports.uiPort); + request(req, res, ports.uiPort); }); } else { - next(); + next(); } }; diff --git a/biz/init.js b/biz/init.js index 9c97d39a8..62223b460 100644 --- a/biz/init.js +++ b/biz/init.js @@ -1,6 +1,6 @@ module.exports = function init(proxy) { - var config = proxy.config; - require(config.uipath)(proxy); - require('./weinre/app')(config); + var config = proxy.config; + require(config.uipath)(proxy); + require('./weinre/app')(config); }; \ No newline at end of file diff --git a/biz/webui/cgi-bin/check-update.js b/biz/webui/cgi-bin/check-update.js index f46ad0413..05a9d0b76 100644 --- a/biz/webui/cgi-bin/check-update.js +++ b/biz/webui/cgi-bin/check-update.js @@ -2,39 +2,39 @@ var properties = require('../lib/properties'); var config = require('../lib/config'); function compare(v1, v2) { - if (typeof v1 != 'string') { - return false; + if (typeof v1 != 'string') { + return false; } - if (typeof v2 != 'string') { - return true; + if (typeof v2 != 'string') { + return true; } - v1 = v1.split('.'); - v2 = v2.split('.'); - var v1Major = parseInt(v1[0], 10) || 0; - var v2Major = parseInt(v2[0], 10) || 0; + v1 = v1.split('.'); + v2 = v2.split('.'); + var v1Major = parseInt(v1[0], 10) || 0; + var v2Major = parseInt(v2[0], 10) || 0; - if (v1Major < v2Major) { - return false; + if (v1Major < v2Major) { + return false; } - if (v1Major > v2Major) { - return true; + if (v1Major > v2Major) { + return true; } - return parseInt(v1[1], 10) > parseInt(v2[1], 10); + return parseInt(v1[1], 10) > parseInt(v2[1], 10); } module.exports = function(req, res) { - var version = config.version; - var doNotShowAgainVersion = properties.get('doNotShowAgainVersion'); - var latestVersion = properties.get('latestVersion'); + var version = config.version; + var doNotShowAgainVersion = properties.get('doNotShowAgainVersion'); + var latestVersion = properties.get('latestVersion'); - res.json({ - ec: 0, - em: 'success', - showUpdate: compare(latestVersion, version) && compare(latestVersion, doNotShowAgainVersion), - version: config.version, - latestVersion: latestVersion + res.json({ + ec: 0, + em: 'success', + showUpdate: compare(latestVersion, version) && compare(latestVersion, doNotShowAgainVersion), + version: config.version, + latestVersion: latestVersion }); }; diff --git a/biz/webui/cgi-bin/composer.js b/biz/webui/cgi-bin/composer.js index 99c914062..ea39725ec 100644 --- a/biz/webui/cgi-bin/composer.js +++ b/biz/webui/cgi-bin/composer.js @@ -4,62 +4,62 @@ var config = require('../lib/config'); var util = require('../lib/util'); function parseHeaders(headers) { - if (!headers || typeof headers != 'string') { - return {}; + if (!headers || typeof headers != 'string') { + return {}; } - try { - return util.lowerCaseify(JSON.parse(headers)); + try { + return util.lowerCaseify(JSON.parse(headers)); } catch(e) {} - return util.parseHeaders(headers); + return util.parseHeaders(headers); } module.exports = function(req, res) { - var _url = req.body.url; + var _url = req.body.url; - if (_url && typeof _url == 'string') { - _url = _url.replace(/#.*$/, ''); - var options = url.parse(util.setProtocol(_url)); - var headers = parseHeaders(req.body.headers); - if (!headers['user-agent']) { - headers['user-agent'] = 'whistle/' + config.version; + if (_url && typeof _url == 'string') { + _url = _url.replace(/#.*$/, ''); + var options = url.parse(util.setProtocol(_url)); + var headers = parseHeaders(req.body.headers); + if (!headers['user-agent']) { + headers['user-agent'] = 'whistle/' + config.version; } - if (options.protocol == 'https:') { - headers[config.HTTPS_FIELD] = 1; - if (options.port == 443) { - options.port = ''; + if (options.protocol == 'https:') { + headers[config.HTTPS_FIELD] = 1; + if (options.port == 443) { + options.port = ''; } } else if (options.port == 80) { - options.port = ''; + options.port = ''; } - headers.host = options.hostname; - if (options.port) { - headers.host += ':' + options.port; + headers.host = options.hostname; + if (options.port) { + headers.host += ':' + options.port; } - options.protocol = null; - options.hostname = null; - options.method = req.body.method; - options.host = '127.0.0.1'; - options.port = config.port; - options.headers = headers; - if (headers['content-length'] != null) { - req.body.body = new Buffer(req.body.body || ''); - headers['content-length'] = req.body.body.length; + options.protocol = null; + options.hostname = null; + options.method = req.body.method; + options.host = '127.0.0.1'; + options.port = config.port; + options.headers = headers; + if (headers['content-length'] != null) { + req.body.body = new Buffer(req.body.body || ''); + headers['content-length'] = req.body.body.length; } - headers[config.CLIENT_IP_HEAD] = util.getClientIp(req); + headers[config.CLIENT_IP_HEAD] = util.getClientIp(req); - http.request(options, function(res) { - res.on('error', util.noop); - util.drain(res); + http.request(options, function(res) { + res.on('error', util.noop); + util.drain(res); }) .on('error', util.noop) .end(req.body.body); } - res.json({ec: 0, em: 'success'}); + res.json({ec: 0, em: 'success'}); }; \ No newline at end of file diff --git a/biz/webui/cgi-bin/do-not-show-again.js b/biz/webui/cgi-bin/do-not-show-again.js index 1bd4ea823..d8da5ed84 100644 --- a/biz/webui/cgi-bin/do-not-show-again.js +++ b/biz/webui/cgi-bin/do-not-show-again.js @@ -1,7 +1,7 @@ var properties = require('../lib/properties'); module.exports = function(req, res) { - properties.set('doNotShowAgainVersion', properties.get('latestVersion')); - res.json({ec: 0, em: 'success'}); + properties.set('doNotShowAgainVersion', properties.get('latestVersion')); + res.json({ec: 0, em: 'success'}); }; diff --git a/biz/webui/cgi-bin/get-data.js b/biz/webui/cgi-bin/get-data.js index 22221c0e8..86d279274 100644 --- a/biz/webui/cgi-bin/get-data.js +++ b/biz/webui/cgi-bin/get-data.js @@ -3,16 +3,16 @@ var logger = proxy.logger; var getData = require('../lib/data'); module.exports = function(req, res) { - var data = req.query; - if (data.ids && typeof data.ids == 'string') { - data.ids = data.ids.split(','); + var data = req.query; + if (data.ids && typeof data.ids == 'string') { + data.ids = data.ids.split(','); } else { - data.ids = null; + data.ids = null; } - res.json({ - ec: 0, - log: proxy.getLogs(data.startLogTime, data.count), - svrLog: logger.getLogs(data.startSvrLogTime, data.count), - data: getData(data) + res.json({ + ec: 0, + log: proxy.getLogs(data.startLogTime, data.count), + svrLog: logger.getLogs(data.startSvrLogTime, data.count), + data: getData(data) }); }; \ No newline at end of file diff --git a/biz/webui/cgi-bin/hide-https-connects.js b/biz/webui/cgi-bin/hide-https-connects.js index 20d9f53b3..7366e57ee 100644 --- a/biz/webui/cgi-bin/hide-https-connects.js +++ b/biz/webui/cgi-bin/hide-https-connects.js @@ -1,6 +1,6 @@ var properties = require('../lib/properties'); module.exports = function(req, res) { - properties.set('hideHttpsConnects', req.body.hideHttpsConnects == 1); - res.json({ec: 0, em: 'success'}); + properties.set('hideHttpsConnects', req.body.hideHttpsConnects == 1); + res.json({ec: 0, em: 'success'}); }; diff --git a/biz/webui/cgi-bin/init.js b/biz/webui/cgi-bin/init.js index 1e0e2624b..52fe5816e 100644 --- a/biz/webui/cgi-bin/init.js +++ b/biz/webui/cgi-bin/init.js @@ -7,20 +7,20 @@ var pluginMgr = require('../lib/proxy').pluginMgr; module.exports = function(req, res) { - res.json({ - version: config.version, - latestVersion: properties.get('latestVersion'), - server: util.getServerInfo(req), - rules: getRules(), - values: getValues(), - hideHttpsConnects: properties.get('hideHttpsConnects'), - interceptHttpsConnects: properties.get('interceptHttpsConnects'), - filterText: properties.get('filterText'), - plugins: pluginMgr.getPlugins(), - disabledAllRules: properties.get('disabledAllRules'), - disabledPlugins: properties.get('disabledPlugins') || {}, - disabledPluginsRules: properties.get('disabledPluginsRules') || {}, - disabledAllPlugins: properties.get('disabledAllPlugins'), - localUIHost: config.localUIHost + res.json({ + version: config.version, + latestVersion: properties.get('latestVersion'), + server: util.getServerInfo(req), + rules: getRules(), + values: getValues(), + hideHttpsConnects: properties.get('hideHttpsConnects'), + interceptHttpsConnects: properties.get('interceptHttpsConnects'), + filterText: properties.get('filterText'), + plugins: pluginMgr.getPlugins(), + disabledAllRules: properties.get('disabledAllRules'), + disabledPlugins: properties.get('disabledPlugins') || {}, + disabledPluginsRules: properties.get('disabledPluginsRules') || {}, + disabledAllPlugins: properties.get('disabledAllPlugins'), + localUIHost: config.localUIHost }); }; \ No newline at end of file diff --git a/biz/webui/cgi-bin/intercept-https-connects.js b/biz/webui/cgi-bin/intercept-https-connects.js index af3b27004..6d2e2f364 100644 --- a/biz/webui/cgi-bin/intercept-https-connects.js +++ b/biz/webui/cgi-bin/intercept-https-connects.js @@ -1,6 +1,6 @@ var properties = require('../lib/properties'); module.exports = function(req, res) { - properties.set('interceptHttpsConnects', req.body.interceptHttpsConnects == 1); - res.json({ec: 0, em: 'success'}); + properties.set('interceptHttpsConnects', req.body.interceptHttpsConnects == 1); + res.json({ec: 0, em: 'success'}); }; diff --git a/biz/webui/cgi-bin/log/get.js b/biz/webui/cgi-bin/log/get.js index cf3fee330..5120de985 100644 --- a/biz/webui/cgi-bin/log/get.js +++ b/biz/webui/cgi-bin/log/get.js @@ -2,5 +2,5 @@ var proxy = require('../../lib/proxy'); module.exports = function(req, res) { - res.json(proxy.getLogs(req.query.startTime)); + res.json(proxy.getLogs(req.query.startTime)); }; \ No newline at end of file diff --git a/biz/webui/cgi-bin/log/set.js b/biz/webui/cgi-bin/log/set.js index 3e5566824..3cc31e5e4 100644 --- a/biz/webui/cgi-bin/log/set.js +++ b/biz/webui/cgi-bin/log/set.js @@ -1,7 +1,7 @@ var proxy = require('../../lib/proxy'); module.exports = function(req, res) { - proxy.addLog(req.query); - res.setHeader('content-type', 'image/png'); - res.end(); + proxy.addLog(req.query); + res.setHeader('content-type', 'image/png'); + res.end(); }; \ No newline at end of file diff --git a/biz/webui/cgi-bin/lookup-tunnel-dns.js b/biz/webui/cgi-bin/lookup-tunnel-dns.js index 03067b8a3..d6737ff52 100644 --- a/biz/webui/cgi-bin/lookup-tunnel-dns.js +++ b/biz/webui/cgi-bin/lookup-tunnel-dns.js @@ -4,33 +4,33 @@ var rules = require('../lib/proxy').rules; var util = require('../lib/util'); module.exports = function(req, res) { - var tunnelUrl = properties.get('showHostIpInResHeaders') ? req.query.url : null; - if (typeof tunnelUrl != 'string') { - tunnelUrl = null; + var tunnelUrl = properties.get('showHostIpInResHeaders') ? req.query.url : null; + if (typeof tunnelUrl != 'string') { + tunnelUrl = null; } else if (tunnelUrl) { - tunnelUrl = url.parse(tunnelUrl); - tunnelUrl = tunnelUrl.host ? 'https://' + tunnelUrl.host : null; + tunnelUrl = url.parse(tunnelUrl); + tunnelUrl = tunnelUrl.host ? 'https://' + tunnelUrl.host : null; } - if (!tunnelUrl) { - return res.json({ec: 2, em: 'server busy'}); + if (!tunnelUrl) { + return res.json({ec: 2, em: 'server busy'}); } - var _rules = rules.resolveRules(tunnelUrl); - var proxyUrl = util.rule.getProxy(_rules.rule); - if (proxyUrl) { - tunnelUrl = 'https:' + util.removeProtocol(proxyUrl); + var _rules = rules.resolveRules(tunnelUrl); + var proxyUrl = util.rule.getProxy(_rules.rule); + if (proxyUrl) { + tunnelUrl = 'https:' + util.removeProtocol(proxyUrl); } else if (_rules.rule) { - var _url = util.setProtocol(util.rule.getMatcher(_rules.rule), true); - if (/^https:/i.test(_url)) { - tunnelUrl = _url; + var _url = util.setProtocol(util.rule.getMatcher(_rules.rule), true); + if (/^https:/i.test(_url)) { + tunnelUrl = _url; } } - rules.resolveHost(tunnelUrl, function(err, host) { - if (err) { - res.json({ec: 2, em: 'server busy'}); + rules.resolveHost(tunnelUrl, function(err, host) { + if (err) { + res.json({ec: 2, em: 'server busy'}); } else { - res.json({ec: 0, em: 'success', host: host}); + res.json({ec: 0, em: 'success', host: host}); } }); }; \ No newline at end of file diff --git a/biz/webui/cgi-bin/plugins/disable-all-plugins.js b/biz/webui/cgi-bin/plugins/disable-all-plugins.js index 53417f07c..c1386d5e2 100644 --- a/biz/webui/cgi-bin/plugins/disable-all-plugins.js +++ b/biz/webui/cgi-bin/plugins/disable-all-plugins.js @@ -2,7 +2,7 @@ var properties = require('../../lib/properties'); var pluginMgr = require('../../lib/proxy').pluginMgr; module.exports = function(req, res) { - properties.set('disabledAllPlugins', req.body.disabledAllPlugins == 1); - pluginMgr.updateRules(); - res.json({ec: 0, em: 'success'}); + properties.set('disabledAllPlugins', req.body.disabledAllPlugins == 1); + pluginMgr.updateRules(); + res.json({ec: 0, em: 'success'}); }; \ No newline at end of file diff --git a/biz/webui/cgi-bin/plugins/disable-plugin.js b/biz/webui/cgi-bin/plugins/disable-plugin.js index 9123904dd..f628900ff 100644 --- a/biz/webui/cgi-bin/plugins/disable-plugin.js +++ b/biz/webui/cgi-bin/plugins/disable-plugin.js @@ -2,13 +2,13 @@ var properties = require('../../lib/properties'); var pluginMgr = require('../../lib/proxy').pluginMgr; module.exports = function(req, res) { - var disabledPlugins = properties.get('disabledPlugins') || {}; - if (req.body.disabled == 1) { - disabledPlugins[req.body.name] = 1; + var disabledPlugins = properties.get('disabledPlugins') || {}; + if (req.body.disabled == 1) { + disabledPlugins[req.body.name] = 1; } else { - delete disabledPlugins[req.body.name]; + delete disabledPlugins[req.body.name]; } - properties.set('disabledPlugins', disabledPlugins); - pluginMgr.updateRules(); - res.json({ec: 0, data: disabledPlugins}); + properties.set('disabledPlugins', disabledPlugins); + pluginMgr.updateRules(); + res.json({ec: 0, data: disabledPlugins}); }; \ No newline at end of file diff --git a/biz/webui/cgi-bin/plugins/get-plugins.js b/biz/webui/cgi-bin/plugins/get-plugins.js index 01f4ca4ab..b1d08722a 100644 --- a/biz/webui/cgi-bin/plugins/get-plugins.js +++ b/biz/webui/cgi-bin/plugins/get-plugins.js @@ -3,7 +3,7 @@ var pluginMgr = require('../../lib/proxy').pluginMgr; module.exports = function(req, res) { - res.json({ec: 0, plugins: pluginMgr.getPlugins(), + res.json({ec: 0, plugins: pluginMgr.getPlugins(), disabledPlugins: properties.get('disabledPlugins') || {}, disabledAllPlugins: properties.get('disabledAllPlugins')}); }; \ No newline at end of file diff --git a/biz/webui/cgi-bin/rootca.js b/biz/webui/cgi-bin/rootca.js index 7a3c3e875..24ea05eee 100644 --- a/biz/webui/cgi-bin/rootca.js +++ b/biz/webui/cgi-bin/rootca.js @@ -1,5 +1,5 @@ var httpsUtil = require('../lib/https-util'); module.exports = function(req, res) { - res.download(httpsUtil.getRootCAFile(), 'rootCA.crt'); + res.download(httpsUtil.getRootCAFile(), 'rootCA.crt'); }; \ No newline at end of file diff --git a/biz/webui/cgi-bin/rules/add.js b/biz/webui/cgi-bin/rules/add.js index 2b82314bc..abbdabf9a 100644 --- a/biz/webui/cgi-bin/rules/add.js +++ b/biz/webui/cgi-bin/rules/add.js @@ -1,6 +1,6 @@ var rules = require('../../lib/rules'); module.exports = function(req, res) { - rules.add(req.body.name, req.body.value); - res.json({ec: 0, em: 'success'}); + rules.add(req.body.name, req.body.value); + res.json({ec: 0, em: 'success'}); }; \ No newline at end of file diff --git a/biz/webui/cgi-bin/rules/allow-multiple-choice.js b/biz/webui/cgi-bin/rules/allow-multiple-choice.js index 9cc3cf2c8..58abbaab4 100644 --- a/biz/webui/cgi-bin/rules/allow-multiple-choice.js +++ b/biz/webui/cgi-bin/rules/allow-multiple-choice.js @@ -1,7 +1,7 @@ var properties = require('../../lib/properties'); module.exports = function(req, res) { - properties.set('allowMultipleChoice', req.body.allowMultipleChoice == 1); - res.json({ec: 0, em: 'success'}); + properties.set('allowMultipleChoice', req.body.allowMultipleChoice == 1); + res.json({ec: 0, em: 'success'}); }; diff --git a/biz/webui/cgi-bin/rules/disable-all-rules.js b/biz/webui/cgi-bin/rules/disable-all-rules.js index 092dede55..446b4aca8 100644 --- a/biz/webui/cgi-bin/rules/disable-all-rules.js +++ b/biz/webui/cgi-bin/rules/disable-all-rules.js @@ -2,7 +2,7 @@ var properties = require('../../lib/properties'); var rules = require('../../lib/rules'); module.exports = function(req, res) { - properties.set('disabledAllRules', req.body.disabledAllRules == 1); - rules.parseRules(); - res.json({ec: 0, em: 'success'}); + properties.set('disabledAllRules', req.body.disabledAllRules == 1); + rules.parseRules(); + res.json({ec: 0, em: 'success'}); }; \ No newline at end of file diff --git a/biz/webui/cgi-bin/rules/disable-default.js b/biz/webui/cgi-bin/rules/disable-default.js index bd6b56fc8..252a51f09 100644 --- a/biz/webui/cgi-bin/rules/disable-default.js +++ b/biz/webui/cgi-bin/rules/disable-default.js @@ -1,6 +1,6 @@ var rules = require('../../lib/rules'); module.exports = function(req, res) { - rules.disableDefault(); - res.json({ec: 0, em: 'success', defaultRulesIsDisabled: rules.defaultRulesIsDisabled(), list: rules.getSelectedList()}); + rules.disableDefault(); + res.json({ec: 0, em: 'success', defaultRulesIsDisabled: rules.defaultRulesIsDisabled(), list: rules.getSelectedList()}); }; \ No newline at end of file diff --git a/biz/webui/cgi-bin/rules/enable-default.js b/biz/webui/cgi-bin/rules/enable-default.js index 18ac5c636..b830c4c3f 100644 --- a/biz/webui/cgi-bin/rules/enable-default.js +++ b/biz/webui/cgi-bin/rules/enable-default.js @@ -1,7 +1,7 @@ var rules = require('../../lib/rules'); module.exports = function(req, res) { - rules.enableDefault(); - rules.setDefault(req.body.value); - res.json({ec: 0, em: 'success', defaultRulesIsDisabled: rules.defaultRulesIsDisabled(), list: rules.getSelectedList()}); + rules.enableDefault(); + rules.setDefault(req.body.value); + res.json({ec: 0, em: 'success', defaultRulesIsDisabled: rules.defaultRulesIsDisabled(), list: rules.getSelectedList()}); }; \ No newline at end of file diff --git a/biz/webui/cgi-bin/rules/get-sys-hosts.js b/biz/webui/cgi-bin/rules/get-sys-hosts.js index 1de77372a..08d439378 100644 --- a/biz/webui/cgi-bin/rules/get-sys-hosts.js +++ b/biz/webui/cgi-bin/rules/get-sys-hosts.js @@ -1,7 +1,7 @@ var rules = require('../../lib/rules'); module.exports = function(req, res) { - rules.getSysHosts(function(err, hosts) { - res.json({ec: err ? 2 : 0, em: err ? err.stack : 'success', hosts: hosts}); + rules.getSysHosts(function(err, hosts) { + res.json({ec: err ? 2 : 0, em: err ? err.stack : 'success', hosts: hosts}); }); }; \ No newline at end of file diff --git a/biz/webui/cgi-bin/rules/index.js b/biz/webui/cgi-bin/rules/index.js index f0fabc903..9d5f73bcc 100644 --- a/biz/webui/cgi-bin/rules/index.js +++ b/biz/webui/cgi-bin/rules/index.js @@ -2,15 +2,15 @@ var rules = require('../../lib/rules'); var properties = require('../../lib/properties'); module.exports = function get() { - return { - defaultRulesIsDisabled: rules.defaultRulesIsDisabled(), - defaultRules: rules.getDefault(), - current: properties.get('currentRulesFile'), - fontSize: properties.get('fontSize'), - showLineNumbers: properties.get('showLineNumbers'), - theme: properties.get('theme'), - syncWithSysHosts: properties.get('syncWithSysHosts'), - allowMultipleChoice: properties.get('allowMultipleChoice'), - list: rules.list() + return { + defaultRulesIsDisabled: rules.defaultRulesIsDisabled(), + defaultRules: rules.getDefault(), + current: properties.get('currentRulesFile'), + fontSize: properties.get('fontSize'), + showLineNumbers: properties.get('showLineNumbers'), + theme: properties.get('theme'), + syncWithSysHosts: properties.get('syncWithSysHosts'), + allowMultipleChoice: properties.get('allowMultipleChoice'), + list: rules.list() }; }; \ No newline at end of file diff --git a/biz/webui/cgi-bin/rules/list.js b/biz/webui/cgi-bin/rules/list.js index 655957d70..54bb1b25c 100644 --- a/biz/webui/cgi-bin/rules/list.js +++ b/biz/webui/cgi-bin/rules/list.js @@ -1,5 +1,5 @@ var get = require('./index'); module.exports = function(req, res) { - res.json(get()); + res.json(get()); }; \ No newline at end of file diff --git a/biz/webui/cgi-bin/rules/move-down.js b/biz/webui/cgi-bin/rules/move-down.js index 1c9349614..ffce4f608 100644 --- a/biz/webui/cgi-bin/rules/move-down.js +++ b/biz/webui/cgi-bin/rules/move-down.js @@ -1,6 +1,6 @@ var rules = require('../../lib/rules'); module.exports = function(req, res) { - rules.moveDown(req.body.name); - res.json({ec: 0, em: 'success'}); + rules.moveDown(req.body.name); + res.json({ec: 0, em: 'success'}); }; \ No newline at end of file diff --git a/biz/webui/cgi-bin/rules/move-up.js b/biz/webui/cgi-bin/rules/move-up.js index df6424d17..6fad97db5 100644 --- a/biz/webui/cgi-bin/rules/move-up.js +++ b/biz/webui/cgi-bin/rules/move-up.js @@ -1,6 +1,6 @@ var rules = require('../../lib/rules'); module.exports = function(req, res) { - rules.moveUp(req.body.name); - res.json({ec: 0, em: 'success'}); + rules.moveUp(req.body.name); + res.json({ec: 0, em: 'success'}); }; \ No newline at end of file diff --git a/biz/webui/cgi-bin/rules/remove.js b/biz/webui/cgi-bin/rules/remove.js index 3a615e40b..b83f75fe3 100644 --- a/biz/webui/cgi-bin/rules/remove.js +++ b/biz/webui/cgi-bin/rules/remove.js @@ -1,6 +1,6 @@ var rules = require('../../lib/rules'); module.exports = function(req, res) { - rules.remove(req.body.name); - res.json({ec: 0, em: 'success'}); + rules.remove(req.body.name); + res.json({ec: 0, em: 'success'}); }; \ No newline at end of file diff --git a/biz/webui/cgi-bin/rules/rename.js b/biz/webui/cgi-bin/rules/rename.js index ec387a53f..270ad84e4 100644 --- a/biz/webui/cgi-bin/rules/rename.js +++ b/biz/webui/cgi-bin/rules/rename.js @@ -1,6 +1,6 @@ var rules = require('../../lib/rules'); module.exports = function(req, res) { - rules.rename(req.body.name, req.body.newName); - res.json({ec: 0, em: 'success'}); + rules.rename(req.body.name, req.body.newName); + res.json({ec: 0, em: 'success'}); }; \ No newline at end of file diff --git a/biz/webui/cgi-bin/rules/select.js b/biz/webui/cgi-bin/rules/select.js index d98a4db87..d549caf88 100644 --- a/biz/webui/cgi-bin/rules/select.js +++ b/biz/webui/cgi-bin/rules/select.js @@ -1,7 +1,7 @@ var rules = require('../../lib/rules'); module.exports = function(req, res) { - rules.add(req.body.name, req.body.value); - rules.select(req.body.name); - res.json({ec: 0, em: 'success', defaultRulesIsDisabled: rules.defaultRulesIsDisabled(), list: rules.getSelectedList()}); + rules.add(req.body.name, req.body.value); + rules.select(req.body.name); + res.json({ec: 0, em: 'success', defaultRulesIsDisabled: rules.defaultRulesIsDisabled(), list: rules.getSelectedList()}); }; \ No newline at end of file diff --git a/biz/webui/cgi-bin/rules/set-current.js b/biz/webui/cgi-bin/rules/set-current.js index 938ccc028..82ffbd44b 100644 --- a/biz/webui/cgi-bin/rules/set-current.js +++ b/biz/webui/cgi-bin/rules/set-current.js @@ -1,6 +1,6 @@ var properties = require('../../lib/properties'); module.exports = function(req, res) { - properties.set('currentRulesFile', req.body.name); - res.json({ec: 0, em: 'success'}); + properties.set('currentRulesFile', req.body.name); + res.json({ec: 0, em: 'success'}); }; diff --git a/biz/webui/cgi-bin/rules/set-font-size.js b/biz/webui/cgi-bin/rules/set-font-size.js index 2a93b0b3a..b15ee7906 100644 --- a/biz/webui/cgi-bin/rules/set-font-size.js +++ b/biz/webui/cgi-bin/rules/set-font-size.js @@ -1,6 +1,6 @@ var properties = require('../../lib/properties'); module.exports = function(req, res) { - properties.set('fontSize', req.body.fontSize); - res.json({ec: 0, em: 'success'}); + properties.set('fontSize', req.body.fontSize); + res.json({ec: 0, em: 'success'}); }; diff --git a/biz/webui/cgi-bin/rules/set-sys-hosts.js b/biz/webui/cgi-bin/rules/set-sys-hosts.js index 834791447..7fa56bdd7 100644 --- a/biz/webui/cgi-bin/rules/set-sys-hosts.js +++ b/biz/webui/cgi-bin/rules/set-sys-hosts.js @@ -1,7 +1,7 @@ var rules = require('../../lib/rules'); module.exports = function(req, res) { - rules.setSysHosts(req.body.hosts, function(err, hosts) { - res.json({ec: err ? 2 : 0, em: err ? err.stack : 'success'}); + rules.setSysHosts(req.body.hosts, function(err, hosts) { + res.json({ec: err ? 2 : 0, em: err ? err.stack : 'success'}); }); }; \ No newline at end of file diff --git a/biz/webui/cgi-bin/rules/set-theme.js b/biz/webui/cgi-bin/rules/set-theme.js index af5e1df16..d4bfb542a 100644 --- a/biz/webui/cgi-bin/rules/set-theme.js +++ b/biz/webui/cgi-bin/rules/set-theme.js @@ -1,7 +1,7 @@ var properties = require('../../lib/properties'); module.exports = function(req, res) { - properties.set('theme', req.body.theme); - res.json({ec: 0, em: 'success'}); + properties.set('theme', req.body.theme); + res.json({ec: 0, em: 'success'}); }; diff --git a/biz/webui/cgi-bin/rules/show-line-numbers.js b/biz/webui/cgi-bin/rules/show-line-numbers.js index d7861cf42..3fb8b8357 100644 --- a/biz/webui/cgi-bin/rules/show-line-numbers.js +++ b/biz/webui/cgi-bin/rules/show-line-numbers.js @@ -1,6 +1,6 @@ var properties = require('../../lib/properties'); module.exports = function(req, res) { - properties.set('showLineNumbers', req.body.showLineNumbers == 1); - res.json({ec: 0, em: 'success'}); + properties.set('showLineNumbers', req.body.showLineNumbers == 1); + res.json({ec: 0, em: 'success'}); }; diff --git a/biz/webui/cgi-bin/rules/sync-with-sys-hosts.js b/biz/webui/cgi-bin/rules/sync-with-sys-hosts.js index 9261be21b..854ce447a 100644 --- a/biz/webui/cgi-bin/rules/sync-with-sys-hosts.js +++ b/biz/webui/cgi-bin/rules/sync-with-sys-hosts.js @@ -1,7 +1,7 @@ var properties = require('../../lib/properties'); module.exports = function(req, res) { - properties.set('syncWithSysHosts', req.body.syncWithSysHosts == 1); - res.json({ec: 0, em: 'success'}); + properties.set('syncWithSysHosts', req.body.syncWithSysHosts == 1); + res.json({ec: 0, em: 'success'}); }; diff --git a/biz/webui/cgi-bin/rules/unselect.js b/biz/webui/cgi-bin/rules/unselect.js index b760e205e..f7abb1922 100644 --- a/biz/webui/cgi-bin/rules/unselect.js +++ b/biz/webui/cgi-bin/rules/unselect.js @@ -1,7 +1,7 @@ var rules = require('../../lib/rules'); module.exports = function(req, res) { - rules.add(req.body.name, req.body.value); - rules.unselect(req.body.name); - res.json({ec: 0, em: 'success', defaultRulesIsDisabled: rules.defaultRulesIsDisabled(), list: rules.getSelectedList()}); + rules.add(req.body.name, req.body.value); + rules.unselect(req.body.name); + res.json({ec: 0, em: 'success', defaultRulesIsDisabled: rules.defaultRulesIsDisabled(), list: rules.getSelectedList()}); }; \ No newline at end of file diff --git a/biz/webui/cgi-bin/server-info.js b/biz/webui/cgi-bin/server-info.js index 7a3715714..c0091b09e 100644 --- a/biz/webui/cgi-bin/server-info.js +++ b/biz/webui/cgi-bin/server-info.js @@ -2,5 +2,5 @@ var util = require('./util'); module.exports = function(req, res) { - res.json({ec: 0, server: util.getServerInfo(req)}); + res.json({ec: 0, server: util.getServerInfo(req)}); }; \ No newline at end of file diff --git a/biz/webui/cgi-bin/set-filter.js b/biz/webui/cgi-bin/set-filter.js index 153d59ba5..70ce2af03 100644 --- a/biz/webui/cgi-bin/set-filter.js +++ b/biz/webui/cgi-bin/set-filter.js @@ -1,6 +1,6 @@ var rulesUtil = require('../lib/rules-util'); module.exports = function(req, res) { - rulesUtil.setFilter(req.body.filter); - res.json({ec: 0, em: 'success'}); + rulesUtil.setFilter(req.body.filter); + res.json({ec: 0, em: 'success'}); }; \ No newline at end of file diff --git a/biz/webui/cgi-bin/show-host-ip-in-res-headers.js b/biz/webui/cgi-bin/show-host-ip-in-res-headers.js index e11ff9f26..fc8421b18 100644 --- a/biz/webui/cgi-bin/show-host-ip-in-res-headers.js +++ b/biz/webui/cgi-bin/show-host-ip-in-res-headers.js @@ -1,6 +1,6 @@ var properties = require('../lib/properties'); module.exports = function(req, res) { - properties.set('showHostIpInResHeaders', req.body.showHostIpInResHeaders == 1); - res.json({ec: 0, em: 'success'}); + properties.set('showHostIpInResHeaders', req.body.showHostIpInResHeaders == 1); + res.json({ec: 0, em: 'success'}); }; \ No newline at end of file diff --git a/biz/webui/cgi-bin/util.js b/biz/webui/cgi-bin/util.js index de6e91d6c..72c37095a 100644 --- a/biz/webui/cgi-bin/util.js +++ b/biz/webui/cgi-bin/util.js @@ -3,27 +3,27 @@ var config = require('../lib/config'); var properties = require('../lib/properties'); exports.getServerInfo = function getServerInfo(req) { - var info = { - version: config.version, - nodeVersion: process.version, - latestVersion: properties.get('latestVersion'), - host: os.hostname(), - port: config.port, - weinrePort: config.weinreport, - ipv4: [], - ipv6: [], - mac: req.ip + (config.storage ? '\n' + config.storage : '') + var info = { + version: config.version, + nodeVersion: process.version, + latestVersion: properties.get('latestVersion'), + host: os.hostname(), + port: config.port, + weinrePort: config.weinreport, + ipv4: [], + ipv6: [], + mac: req.ip + (config.storage ? '\n' + config.storage : '') }; - var ifaces = os.networkInterfaces(); - Object.keys(ifaces).forEach(function(ifname) { - ifaces[ifname].forEach(function (iface) { - if (iface.internal) { - return; + var ifaces = os.networkInterfaces(); + Object.keys(ifaces).forEach(function(ifname) { + ifaces[ifname].forEach(function (iface) { + if (iface.internal) { + return; } - info[iface.family == 'IPv4' ? 'ipv4' : 'ipv6'].push(iface.address); + info[iface.family == 'IPv4' ? 'ipv4' : 'ipv6'].push(iface.address); }); }); - return info; + return info; }; diff --git a/biz/webui/cgi-bin/values/add.js b/biz/webui/cgi-bin/values/add.js index 60e1627ad..c6d285f7d 100644 --- a/biz/webui/cgi-bin/values/add.js +++ b/biz/webui/cgi-bin/values/add.js @@ -1,6 +1,6 @@ var values = require('../../lib/values'); module.exports = function(req, res) { - values.add(req.body.name, req.body.value); - res.json({ec: 0, em: 'success'}); + values.add(req.body.name, req.body.value); + res.json({ec: 0, em: 'success'}); }; \ No newline at end of file diff --git a/biz/webui/cgi-bin/values/get.js b/biz/webui/cgi-bin/values/get.js index bd55641d9..f38e0fcd3 100644 --- a/biz/webui/cgi-bin/values/get.js +++ b/biz/webui/cgi-bin/values/get.js @@ -2,10 +2,10 @@ var values = require('../../lib/values'); var properties = require('../../lib/properties'); module.exports = function(req, res) { - res.json({ - fontSize: properties.get('valuesFontSize'), - theme: properties.get('valuesTheme'), - showLineNumbers: properties.get('valuesShowLineNumbers'), - values: values.list() + res.json({ + fontSize: properties.get('valuesFontSize'), + theme: properties.get('valuesTheme'), + showLineNumbers: properties.get('valuesShowLineNumbers'), + values: values.list() }); }; \ No newline at end of file diff --git a/biz/webui/cgi-bin/values/index.js b/biz/webui/cgi-bin/values/index.js index c86ade245..61a38afbf 100644 --- a/biz/webui/cgi-bin/values/index.js +++ b/biz/webui/cgi-bin/values/index.js @@ -2,11 +2,11 @@ var values = require('../../lib/values'); var properties = require('../../lib/properties'); module.exports = function get() { - return { - current: properties.get('currentValuesFile'), - fontSize: properties.get('valuesFontSize'), - showLineNumbers: properties.get('valuesShowLineNumbers'), - theme: properties.get('valuesTheme'), - list: values.list() + return { + current: properties.get('currentValuesFile'), + fontSize: properties.get('valuesFontSize'), + showLineNumbers: properties.get('valuesShowLineNumbers'), + theme: properties.get('valuesTheme'), + list: values.list() }; }; \ No newline at end of file diff --git a/biz/webui/cgi-bin/values/list.js b/biz/webui/cgi-bin/values/list.js index 655957d70..54bb1b25c 100644 --- a/biz/webui/cgi-bin/values/list.js +++ b/biz/webui/cgi-bin/values/list.js @@ -1,5 +1,5 @@ var get = require('./index'); module.exports = function(req, res) { - res.json(get()); + res.json(get()); }; \ No newline at end of file diff --git a/biz/webui/cgi-bin/values/move-down.js b/biz/webui/cgi-bin/values/move-down.js index 658343c26..45a26d36a 100644 --- a/biz/webui/cgi-bin/values/move-down.js +++ b/biz/webui/cgi-bin/values/move-down.js @@ -1,6 +1,6 @@ var values = require('../../lib/values'); module.exports = function(req, res) { - values.moveDown(req.body.name); - res.json({ec: 0, em: 'success'}); + values.moveDown(req.body.name); + res.json({ec: 0, em: 'success'}); }; \ No newline at end of file diff --git a/biz/webui/cgi-bin/values/move-up.js b/biz/webui/cgi-bin/values/move-up.js index 4c6e7c707..a2bb265d5 100644 --- a/biz/webui/cgi-bin/values/move-up.js +++ b/biz/webui/cgi-bin/values/move-up.js @@ -1,6 +1,6 @@ var values = require('../../lib/values'); module.exports = function(req, res) { - values.moveUp(req.body.name); - res.json({ec: 0, em: 'success'}); + values.moveUp(req.body.name); + res.json({ec: 0, em: 'success'}); }; \ No newline at end of file diff --git a/biz/webui/cgi-bin/values/remove.js b/biz/webui/cgi-bin/values/remove.js index ce9906065..80d736aed 100644 --- a/biz/webui/cgi-bin/values/remove.js +++ b/biz/webui/cgi-bin/values/remove.js @@ -1,6 +1,6 @@ var values = require('../../lib/values'); module.exports = function(req, res) { - values.remove(req.body.name); - res.json({ec: 0, em: 'success'}); + values.remove(req.body.name); + res.json({ec: 0, em: 'success'}); }; \ No newline at end of file diff --git a/biz/webui/cgi-bin/values/rename.js b/biz/webui/cgi-bin/values/rename.js index f4f1e78b3..89a1dc847 100644 --- a/biz/webui/cgi-bin/values/rename.js +++ b/biz/webui/cgi-bin/values/rename.js @@ -1,6 +1,6 @@ var values = require('../../lib/values'); module.exports = function(req, res) { - values.rename(req.body.name, req.body.newName); - res.json({ec: 0, em: 'success'}); + values.rename(req.body.name, req.body.newName); + res.json({ec: 0, em: 'success'}); }; \ No newline at end of file diff --git a/biz/webui/cgi-bin/values/set-current.js b/biz/webui/cgi-bin/values/set-current.js index 2e378a6e1..eb79f5b20 100644 --- a/biz/webui/cgi-bin/values/set-current.js +++ b/biz/webui/cgi-bin/values/set-current.js @@ -1,6 +1,6 @@ var properties = require('../../lib/properties'); module.exports = function(req, res) { - properties.set('currentValuesFile', req.body.name); - res.json({ec: 0, em: 'success'}); + properties.set('currentValuesFile', req.body.name); + res.json({ec: 0, em: 'success'}); }; diff --git a/biz/webui/cgi-bin/values/set-font-size.js b/biz/webui/cgi-bin/values/set-font-size.js index 353adfbcd..0856fe6ee 100644 --- a/biz/webui/cgi-bin/values/set-font-size.js +++ b/biz/webui/cgi-bin/values/set-font-size.js @@ -1,6 +1,6 @@ var properties = require('../../lib/properties'); module.exports = function(req, res) { - properties.set('valuesFontSize', req.body.fontSize); - res.json({ec: 0, em: 'success'}); + properties.set('valuesFontSize', req.body.fontSize); + res.json({ec: 0, em: 'success'}); }; \ No newline at end of file diff --git a/biz/webui/cgi-bin/values/set-theme.js b/biz/webui/cgi-bin/values/set-theme.js index 1cd3218ff..0496ef99e 100644 --- a/biz/webui/cgi-bin/values/set-theme.js +++ b/biz/webui/cgi-bin/values/set-theme.js @@ -1,6 +1,6 @@ var properties = require('../../lib/properties'); module.exports = function(req, res) { - properties.set('valuesTheme', req.body.theme); - res.json({ec: 0, em: 'success'}); + properties.set('valuesTheme', req.body.theme); + res.json({ec: 0, em: 'success'}); }; \ No newline at end of file diff --git a/biz/webui/cgi-bin/values/show-line-numbers.js b/biz/webui/cgi-bin/values/show-line-numbers.js index 487e54701..f7e8e2620 100644 --- a/biz/webui/cgi-bin/values/show-line-numbers.js +++ b/biz/webui/cgi-bin/values/show-line-numbers.js @@ -1,6 +1,6 @@ var properties = require('../../lib/properties'); module.exports = function(req, res) { - properties.set('valuesShowLineNumbers', req.body.showLineNumbers == 1); - res.json({ec: 0, em: 'success'}); + properties.set('valuesShowLineNumbers', req.body.showLineNumbers == 1); + res.json({ec: 0, em: 'success'}); }; \ No newline at end of file diff --git a/biz/webui/lib/config.js b/biz/webui/lib/config.js index 2801fbc48..9e34e4f00 100644 --- a/biz/webui/lib/config.js +++ b/biz/webui/lib/config.js @@ -1,4 +1,4 @@ module.exports = function setConfig(config) { - module.exports = config; + module.exports = config; }; \ No newline at end of file diff --git a/biz/webui/lib/data.js b/biz/webui/lib/data.js index 48e6d560a..c761e6b26 100644 --- a/biz/webui/lib/data.js +++ b/biz/webui/lib/data.js @@ -1,4 +1,4 @@ module.exports = function init(proxy) { - module.exports = proxy.getData; + module.exports = proxy.getData; }; \ No newline at end of file diff --git a/biz/webui/lib/https-util.js b/biz/webui/lib/https-util.js index c43f37f97..c6435015c 100644 --- a/biz/webui/lib/https-util.js +++ b/biz/webui/lib/https-util.js @@ -1,3 +1,3 @@ module.exports = function init(httpsUtil) { - module.exports = httpsUtil; + module.exports = httpsUtil; }; \ No newline at end of file diff --git a/biz/webui/lib/index.js b/biz/webui/lib/index.js index a7508b4c4..d934ffc0d 100644 --- a/biz/webui/lib/index.js +++ b/biz/webui/lib/index.js @@ -9,16 +9,16 @@ var DONT_CHECK_PATHS = ['/cgi-bin/server-info', '/cgi-bin/show-host-ip-in-res-he var util, username, password, config; function dontCheckPaths(req) { - return DONT_CHECK_PATHS.indexOf(req.path) != -1; + return DONT_CHECK_PATHS.indexOf(req.path) != -1; } app.use(function(req, res, next) { - req.on('error', abort).on('close', abort); - res.on('error', abort); - function abort() { - res.destroy(); + req.on('error', abort).on('close', abort); + res.on('error', abort); + function abort() { + res.destroy(); } - next(); + next(); }); app.use(bodyParser.urlencoded({ extended: true, limit: '1mb'})); @@ -26,91 +26,91 @@ app.use(bodyParser.json()); app.use(function(req, res, next) { - if (checkLogin(req, res)) { - next(); - return; + if (checkLogin(req, res)) { + next(); + return; } - res.setHeader('WWW-Authenticate', ' Basic realm=User Login'); - res.status(401).end('Please enter your username and password.'); + res.setHeader('WWW-Authenticate', ' Basic realm=User Login'); + res.status(401).end('Please enter your username and password.'); }); app.all('/cgi-bin/*', function(req, res) { - try { - if (req.headers.origin) { - res.setHeader('Access-Control-Allow-Origin', req.headers.origin); - res.setHeader('Access-Control-Allow-Credentials', true); + try { + if (req.headers.origin) { + res.setHeader('Access-Control-Allow-Origin', req.headers.origin); + res.setHeader('Access-Control-Allow-Credentials', true); } - require(path.join(__dirname, '..' + req.path))(req, res); + require(path.join(__dirname, '..' + req.path))(req, res); } catch(err) { - res.status(500).send(util.getErrorStack(err)); + res.status(500).send(util.getErrorStack(err)); } }); app.use(express.static(path.join(__dirname, '../htdocs'), {maxAge: 300000})); app.get('*', function(req, res) { - res.sendFile(htdocs.getHtmlFile('index.html')); + res.sendFile(htdocs.getHtmlFile('index.html')); }); function checkLogin(req, res) { - if (!username && !password || dontCheckPaths(req)) { + if (!username && !password || dontCheckPaths(req)) { - return true; + return true; } - var userInfo = auth(req); - if (userInfo && (userInfo.name || userInfo.pass)) { - if (username == userInfo.name && password == userInfo.pass) { - res.setHeader('set-cookie', '_lkey=' + getLoginKey(req) + var userInfo = auth(req); + if (userInfo && (userInfo.name || userInfo.pass)) { + if (username == userInfo.name && password == userInfo.pass) { + res.setHeader('set-cookie', '_lkey=' + getLoginKey(req) + '; max-age=' + 60 * 60 * 24 * 1000 + '; path=/'); - return true; + return true; } } - return checkCookie(req); + return checkCookie(req); } function checkCookie(req) { - var cookies = req.headers.cookie; - if (cookies) { - cookies = cookies.split(/;\s*/g); - for (var i = 0, len = cookies.length; i < len; i++) { - var cookie = cookies[i].split('='); - if (cookie[0] == '_lkey') { - return cookie.slice(1).join('=') == getLoginKey(req); + var cookies = req.headers.cookie; + if (cookies) { + cookies = cookies.split(/;\s*/g); + for (var i = 0, len = cookies.length; i < len; i++) { + var cookie = cookies[i].split('='); + if (cookie[0] == '_lkey') { + return cookie.slice(1).join('=') == getLoginKey(req); } } } - return false; + return false; } function getLoginKey(req) { - return shasum(username + '\n' + password + return shasum(username + '\n' + password + '\n' + util.getClientIp(req, true)); } function shasum(str) { - var shasum = crypto.createHash('sha1'); - shasum.update(str); - return shasum.digest('hex'); + var shasum = crypto.createHash('sha1'); + shasum.update(str); + return shasum.digest('hex'); } module.exports = function(proxy) { - config = proxy.config; - var rulesUtil = proxy.rulesUtil; - username = config.username || ''; - password = config.password || ''; + config = proxy.config; + var rulesUtil = proxy.rulesUtil; + username = config.username || ''; + password = config.password || ''; - require('./proxy')(proxy); - require('./util')(util = proxy.util); - require('./config')(config); - require('./rules-util')(rulesUtil); - require('./rules')(rulesUtil.rules); - require('./properties')(rulesUtil.properties); - require('./values')(rulesUtil.values); - require('./https-util')(proxy.httpsUtil); - require('./data')(proxy); - app.listen(config.uiport); + require('./proxy')(proxy); + require('./util')(util = proxy.util); + require('./config')(config); + require('./rules-util')(rulesUtil); + require('./rules')(rulesUtil.rules); + require('./properties')(rulesUtil.properties); + require('./values')(rulesUtil.values); + require('./https-util')(proxy.httpsUtil); + require('./data')(proxy); + app.listen(config.uiport); }; \ No newline at end of file diff --git a/biz/webui/lib/properties.js b/biz/webui/lib/properties.js index 8cc229abe..0a169a7b4 100644 --- a/biz/webui/lib/properties.js +++ b/biz/webui/lib/properties.js @@ -1,3 +1,3 @@ module.exports = function init(properties) { - module.exports = properties; + module.exports = properties; }; \ No newline at end of file diff --git a/biz/webui/lib/proxy.js b/biz/webui/lib/proxy.js index c2e1d0ef6..81724b499 100644 --- a/biz/webui/lib/proxy.js +++ b/biz/webui/lib/proxy.js @@ -1,3 +1,3 @@ module.exports = function init(proxy) { - module.exports = proxy; + module.exports = proxy; }; \ No newline at end of file diff --git a/biz/webui/lib/rules-util.js b/biz/webui/lib/rules-util.js index f3827d245..437de9bdc 100644 --- a/biz/webui/lib/rules-util.js +++ b/biz/webui/lib/rules-util.js @@ -1,3 +1,3 @@ module.exports = function init(util) { - module.exports = util; + module.exports = util; }; \ No newline at end of file diff --git a/biz/webui/lib/rules.js b/biz/webui/lib/rules.js index a345ac299..e3be664b1 100644 --- a/biz/webui/lib/rules.js +++ b/biz/webui/lib/rules.js @@ -1,3 +1,3 @@ module.exports = function init(rules) { - module.exports = rules; + module.exports = rules; }; \ No newline at end of file diff --git a/biz/webui/lib/util.js b/biz/webui/lib/util.js index 68258ee18..76f540a4b 100644 --- a/biz/webui/lib/util.js +++ b/biz/webui/lib/util.js @@ -1,4 +1,4 @@ module.exports = function setConfig(util) { - module.exports = util; + module.exports = util; }; \ No newline at end of file diff --git a/biz/webui/lib/values.js b/biz/webui/lib/values.js index a03aceb16..aa3dfc455 100644 --- a/biz/webui/lib/values.js +++ b/biz/webui/lib/values.js @@ -1,3 +1,3 @@ module.exports = function init(values) { - module.exports = values; + module.exports = values; }; \ No newline at end of file diff --git a/biz/weinre/app.js b/biz/weinre/app.js index 50a5cc34c..c260bcd75 100644 --- a/biz/weinre/app.js +++ b/biz/weinre/app.js @@ -2,22 +2,22 @@ module.exports = function init(config) { //weinre用到老版本的express,改版本会直接往下面原型对象设置__defineGetter__ //会影响到同一进程的web应用,新版的express处理方式更加合理些 - var noop = function() {}; - var prepareStackTrace = Error.prepareStackTrace; - var req = require('http').IncomingMessage.prototype; - var __defineGetter__ = req.__defineGetter__; - req.__defineGetter__ = noop; - var log = console.log; - console.log = noop; - require('weinre').run({ - boundHost: '-all-', - httpPort: parseInt(config.weinreport, 10), - verbose: false, - debug: false, - readTimeout: 5, - deathTimeout: 15 + var noop = function() {}; + var prepareStackTrace = Error.prepareStackTrace; + var req = require('http').IncomingMessage.prototype; + var __defineGetter__ = req.__defineGetter__; + req.__defineGetter__ = noop; + var log = console.log; + console.log = noop; + require('weinre').run({ + boundHost: '-all-', + httpPort: parseInt(config.weinreport, 10), + verbose: false, + debug: false, + readTimeout: 5, + deathTimeout: 15 }); - req.__defineGetter__ = __defineGetter__; - console.log = log; - Error.prepareStackTrace = prepareStackTrace; + req.__defineGetter__ = __defineGetter__; + console.log = log; + Error.prepareStackTrace = prepareStackTrace; }; \ No newline at end of file diff --git a/lib/config.js b/lib/config.js index bbf533f46..6d0e46304 100644 --- a/lib/config.js +++ b/lib/config.js @@ -24,89 +24,89 @@ config.CLIENT_IP_HEAD = 'x-forwarded-for-' + config.name + '-' + now; config.HTTPS_FLAG = config.whistleSsl + '.'; function getHomeDirname() { - var homedir = (getHomedir() || '').split(/[\/\\]/g); - for (var i = homedir.length - 1; i >= 0; i--) { - if (homedir[i]) { - return homedir[i]; + var homedir = (getHomedir() || '').split(/[\/\\]/g); + for (var i = homedir.length - 1; i >= 0; i--) { + if (homedir[i]) { + return homedir[i]; } } - return ''; + return ''; } function getHomedir() { //默认设置为`~`,防止Linux在开机启动时Node无法获取homedir - return (typeof os.homedir == 'function' ? os.homedir() : + return (typeof os.homedir == 'function' ? os.homedir() : process.env[process.platform == 'win32' ? 'USERPROFILE' : 'HOME']) || '~'; } function getWhistlePath() { - return process.env.WHISTLE_PATH || path.join(getHomedir(), '.WhistleAppData'); + return process.env.WHISTLE_PATH || path.join(getHomedir(), '.WhistleAppData'); } function getDataDir(dirname) { - var dir = path.join(getWhistlePath(), dirname || '.' + config.name); - fse.ensureDirSync(dir); - return dir; + var dir = path.join(getWhistlePath(), dirname || '.' + config.name); + fse.ensureDirSync(dir); + return dir; } exports.getDataDir = getDataDir; function createAgent(config, https) { - return new (https ? httpsAgent : httpAgent)(config) + return new (https ? httpsAgent : httpAgent)(config) .on('free', preventThrowOutError); } function getHttpsAgent(options) { - return getAgent(options, httpsAgents, 'httpsOverHttp'); + return getAgent(options, httpsAgents, 'httpsOverHttp'); } exports.getHttpsAgent = getHttpsAgent; function getHttpAgent(options) { - return getAgent(options, httpAgents, 'httpOverHttp'); + return getAgent(options, httpAgents, 'httpOverHttp'); } exports.getHttpAgent = getHttpAgent; function getAgent(options, cache, type) { - var key = getCacheKey(options); - var agent = cache[key]; - if (!agent) { - options.proxyAuth = options.auth; - options = { - proxy: options, - rejectUnauthorized: false + var key = getCacheKey(options); + var agent = cache[key]; + if (!agent) { + options.proxyAuth = options.auth; + options = { + proxy: options, + rejectUnauthorized: false }; - agent = cache[key] = new tunnel[type || 'httpsOverHttp'](options); - agent.on('free', preventThrowOutError); + agent = cache[key] = new tunnel[type || 'httpsOverHttp'](options); + agent.on('free', preventThrowOutError); } - return agent; + return agent; } function getCacheKey(options) { - return [options.isHttps ? 'https' : 'http', options.host, options.port, options.auth || options.proxyAuth || ''].join(':'); + return [options.isHttps ? 'https' : 'http', options.host, options.port, options.auth || options.proxyAuth || ''].join(':'); } function getAuths(_url) { - var options = typeof _url == 'string' ? url.parse(_url) : _url; - if (!options || !options.auth) { - return [socks.auth.None()]; + var options = typeof _url == 'string' ? url.parse(_url) : _url; + if (!options || !options.auth) { + return [socks.auth.None()]; } - var auths = []; - options.auth.split('|').forEach(function(auth) { - if (auth = auth.trim()) { - var index = auth.indexOf(':'); - auths.push({ - username: index == -1 ? auth : auth.substring(0, index), - password: index == -1 ? '' : auth.substring(index + 1) + var auths = []; + options.auth.split('|').forEach(function(auth) { + if (auth = auth.trim()) { + var index = auth.indexOf(':'); + auths.push({ + username: index == -1 ? auth : auth.substring(0, index), + password: index == -1 ? '' : auth.substring(index + 1) }); } }); - return auths.length ? auths.map(function(auth) { - return socks.auth.UserPassword(auth.username, auth.password); + return auths.length ? auths.map(function(auth) { + return socks.auth.UserPassword(auth.username, auth.password); }) : [socks.auth.None()]; } @@ -114,133 +114,133 @@ function getAuths(_url) { exports.getAuths = getAuths; function connect(options, cb) { - var proxyOptions = { - method: 'CONNECT', - agent: false, - path: options.host + ':' + options.port, - host: options.proxyHost, - port: options.proxyPort, - headers: options.headers || {} + var proxyOptions = { + method: 'CONNECT', + agent: false, + path: options.host + ':' + options.port, + host: options.proxyHost, + port: options.proxyPort, + headers: options.headers || {} }; - proxyOptions.headers.host = proxyOptions.path; - if (options.proxyAuth) { - proxyOptions.headers['proxy-authorization'] = 'Basic ' + + proxyOptions.headers.host = proxyOptions.path; + if (options.proxyAuth) { + proxyOptions.headers['proxy-authorization'] = 'Basic ' + new Buffer(options.proxyAuth + '').toString('base64'); } - var timer = setTimeout(function() { - req.emit('error', new Error('Timeout')); - req.abort(); + var timer = setTimeout(function() { + req.emit('error', new Error('Timeout')); + req.abort(); }, 16000); - var req = http.request(proxyOptions); - req.on('connect', function(res, socket, head) { - clearTimeout(timer); - socket.on('error', noop); - cb(socket); - if (res.statusCode !== 200) { - process.nextTick(function() { - req.emit('error', new Error('Tunneling socket could not be established, statusCode=' + res.statusCode)); + var req = http.request(proxyOptions); + req.on('connect', function(res, socket, head) { + clearTimeout(timer); + socket.on('error', noop); + cb(socket); + if (res.statusCode !== 200) { + process.nextTick(function() { + req.emit('error', new Error('Tunneling socket could not be established, statusCode=' + res.statusCode)); }); } }).end(); - return req; + return req; } exports.connect = connect; function preventThrowOutError(socket) { - socket.removeListener('error', freeSocketErrorListener); - socket.on('error', freeSocketErrorListener); + socket.removeListener('error', freeSocketErrorListener); + socket.on('error', freeSocketErrorListener); } function freeSocketErrorListener() { - var socket = this; - socket.destroy(); - socket.emit('agentRemove'); - socket.removeListener('error', freeSocketErrorListener); + var socket = this; + socket.destroy(); + socket.emit('agentRemove'); + socket.removeListener('error', freeSocketErrorListener); } function resolvePath(file) { - if (!file || !(file = file.trim())) { - return file; + if (!file || !(file = file.trim())) { + return file; } - return /^[\w-]+$/.test(file) ? file : path.resolve(file); + return /^[\w-]+$/.test(file) ? file : path.resolve(file); } exports.extend = function extend(newConf) { - if (newConf) { - variableProperties.forEach(function(name) { - config[name] = newConf[name] || pkgConf[name]; + if (newConf) { + variableProperties.forEach(function(name) { + config[name] = newConf[name] || pkgConf[name]; }); - if (Array.isArray(newConf.ports)) { - config.ports = pkgConf.ports.concat(newConf.ports); + if (Array.isArray(newConf.ports)) { + config.ports = pkgConf.ports.concat(newConf.ports); } - if (typeof newConf.middlewares == 'string') { - config.middlewares = newConf.middlewares.trim().split(/\s*,\s*/g); + if (typeof newConf.middlewares == 'string') { + config.middlewares = newConf.middlewares.trim().split(/\s*,\s*/g); } } - config.middlewares = Array.isArray(config.middlewares) ? config.middlewares.map(resolvePath) : []; - config.WEINRE_HOST = 'weinre.' + config.localUIHost; + config.middlewares = Array.isArray(config.middlewares) ? config.middlewares.map(resolvePath) : []; + config.WEINRE_HOST = 'weinre.' + config.localUIHost; - var port = config.port; - config.ports.forEach(function(name) { - if (!/port$/.test(name) || name == 'port') { - throw new Error('Port name "' + name + '" must be end of "port", but not equals "port", like: ' + name + 'port'); + var port = config.port; + config.ports.forEach(function(name) { + if (!/port$/.test(name) || name == 'port') { + throw new Error('Port name "' + name + '" must be end of "port", but not equals "port", like: ' + name + 'port'); } - config[name] = ++port; + config[name] = ++port; }); - config.sockets = Math.max(parseInt(config.sockets, 10) || 0, 1); - var agentConfig = { - maxSockets: config.sockets, - keepAlive: config.keepAlive, - keepAliveMsecs: config.keepAliveMsecs + config.sockets = Math.max(parseInt(config.sockets, 10) || 0, 1); + var agentConfig = { + maxSockets: config.sockets, + keepAlive: config.keepAlive, + keepAliveMsecs: config.keepAliveMsecs }; - config.httpAgent = config.debug ? false : createAgent(agentConfig); - config.httpsAgent = config.debug ? false : createAgent(agentConfig, true); - config.getSocksAgent = function(options) { - var key = getCacheKey(options); - var agent = socksAgents[key]; - if (!agent) { - var proxyOptions = _extend({}, agentConfig); - proxyOptions.proxyHost = options.host; - proxyOptions.proxyPort = parseInt(options.port, 10) || 1080; - proxyOptions.rejectUnauthorized = false; - proxyOptions.localDNS = false; - proxyOptions.auths = getAuths(options); - agent = socksAgents[key] = options.isHttps ? new socks.HttpsAgent(proxyOptions) : new socks.HttpAgent(proxyOptions); - agent.on('free', preventThrowOutError); - var createSocket = agent.createSocket; - agent.createSocket = function(req, options) { - var client = createSocket.apply(agent, arguments); - client.on('error', function(err) { - req.emit('error', err); + config.httpAgent = config.debug ? false : createAgent(agentConfig); + config.httpsAgent = config.debug ? false : createAgent(agentConfig, true); + config.getSocksAgent = function(options) { + var key = getCacheKey(options); + var agent = socksAgents[key]; + if (!agent) { + var proxyOptions = _extend({}, agentConfig); + proxyOptions.proxyHost = options.host; + proxyOptions.proxyPort = parseInt(options.port, 10) || 1080; + proxyOptions.rejectUnauthorized = false; + proxyOptions.localDNS = false; + proxyOptions.auths = getAuths(options); + agent = socksAgents[key] = options.isHttps ? new socks.HttpsAgent(proxyOptions) : new socks.HttpAgent(proxyOptions); + agent.on('free', preventThrowOutError); + var createSocket = agent.createSocket; + agent.createSocket = function(req, options) { + var client = createSocket.apply(agent, arguments); + client.on('error', function(err) { + req.emit('error', err); }); - return client; + return client; }; } - return agent; + return agent; }; - config.uipath = config.uipath ? resolvePath(config.uipath) : './webui/app'; - config.DATA_DIR = getDataDir(config.dataDirname); - config.storage = config.storage && encodeURIComponent(config.storage); - var customDirs = path.join(config.DATA_DIR, 'custom_dirs'); - var root = config.storage ? path.join(customDirs, config.storage) : config.DATA_DIR; - config.rulesDir = path.join(root, 'rules'); - config.valuesDir = path.join(root, 'values'); - config.propertiesDir = path.join(root, 'properties'); - config.homeDirname = getHomeDirname(); - if (config.storage && newConf.copy) { - var copyDir = typeof newConf.copy == 'string' && encodeURIComponent(newConf.copy); - if (copyDir !== config.storage) { - var dataDir = copyDir ? path.join(customDirs, copyDir) : config.DATA_DIR; - fse.copySync(path.join(dataDir, 'rules'), config.rulesDir); - fse.copySync(path.join(dataDir, 'values'), config.valuesDir); - fse.copySync(path.join(dataDir, 'properties'), config.propertiesDir); + config.uipath = config.uipath ? resolvePath(config.uipath) : './webui/app'; + config.DATA_DIR = getDataDir(config.dataDirname); + config.storage = config.storage && encodeURIComponent(config.storage); + var customDirs = path.join(config.DATA_DIR, 'custom_dirs'); + var root = config.storage ? path.join(customDirs, config.storage) : config.DATA_DIR; + config.rulesDir = path.join(root, 'rules'); + config.valuesDir = path.join(root, 'values'); + config.propertiesDir = path.join(root, 'properties'); + config.homeDirname = getHomeDirname(); + if (config.storage && newConf.copy) { + var copyDir = typeof newConf.copy == 'string' && encodeURIComponent(newConf.copy); + if (copyDir !== config.storage) { + var dataDir = copyDir ? path.join(customDirs, copyDir) : config.DATA_DIR; + fse.copySync(path.join(dataDir, 'rules'), config.rulesDir); + fse.copySync(path.join(dataDir, 'values'), config.valuesDir); + fse.copySync(path.join(dataDir, 'properties'), config.propertiesDir); } } - return config; + return config; }; \ No newline at end of file diff --git a/lib/handlers/error-handler.js b/lib/handlers/error-handler.js index f0b980e83..775e30c68 100644 --- a/lib/handlers/error-handler.js +++ b/lib/handlers/error-handler.js @@ -1,5 +1,5 @@ var util = require('../util'); module.exports = function(err, req, res, next) { - res.response(util.wrapGatewayError(util.getErrorStack(err))); + res.response(util.wrapGatewayError(util.getErrorStack(err))); }; \ No newline at end of file diff --git a/lib/handlers/file-proxy.js b/lib/handlers/file-proxy.js index 29566ae5e..0b759d39b 100644 --- a/lib/handlers/file-proxy.js +++ b/lib/handlers/file-proxy.js @@ -13,192 +13,192 @@ var MAX_HEADERS_SIZE = 256 * 1024; var TPL_RE = /(?:dust|tpl|jsonp):$/; function isTplProtocol(protocol) { - return TPL_RE.test(protocol); + return TPL_RE.test(protocol); } function isRawFileProtocol(protocol) { - return RAW_FILE_RE.test(protocol); + return RAW_FILE_RE.test(protocol); } function readFiles(files, callback) { - var file = files.shift(); - var execCallback = function(err, stat) { - if(!err && stat && stat.isFile()) { - callback(null, file); + var file = files.shift(); + var execCallback = function(err, stat) { + if(!err && stat && stat.isFile()) { + callback(null, file); } else if (files.length) { - readFiles(files, callback); + readFiles(files, callback); } else { - callback(err || new Error('Not found file ' + file), file); + callback(err || new Error('Not found file ' + file), file); } }; - !file || typeof file != 'string' ? execCallback() : fs.stat(file, execCallback); + !file || typeof file != 'string' ? execCallback() : fs.stat(file, execCallback); } function parseRes(str) { - if (!str) { - return { - statusCode: 200, - headers: {} + if (!str) { + return { + statusCode: 200, + headers: {} }; } - var headers = str.split(CRLF_RE); - var statusLine = headers.shift().trim().split(/\s+/g); - return { - statusCode: statusLine[1] || 200, - headers: util.parseHeaders(headers) + var headers = str.split(CRLF_RE); + var statusLine = headers.shift().trim().split(/\s+/g); + return { + statusCode: statusLine[1] || 200, + headers: util.parseHeaders(headers) }; } function getRawResByValue(body) { - var headers; - if (HEADERS_SEP_RE.test(body)) { - var crlfStr = RegExp.$1; - var index = body.indexOf(crlfStr); - headers = body.substring(0, index); - body = body.substring(index + crlfStr.length); + var headers; + if (HEADERS_SEP_RE.test(body)) { + var crlfStr = RegExp.$1; + var index = body.indexOf(crlfStr); + headers = body.substring(0, index); + body = body.substring(index + crlfStr.length); } - var reader = parseRes(headers); - reader.body = body; - return reader; + var reader = parseRes(headers); + reader.body = body; + return reader; } function getRawResByPath(protocol, path, callback) { - var reader = fs.createReadStream(path); - if (isRawFileProtocol(protocol)) { - var buffer; - var response = function(err, crlf) { - reader.removeAllListeners('data'); - reader.removeAllListeners('error'); - reader.removeAllListeners('end'); - var stream = reader; - reader = new PassThrough(); - if (err) { - reader.statusCode = 500; - reader.push(err.stack); - reader.push(null); + var reader = fs.createReadStream(path); + if (isRawFileProtocol(protocol)) { + var buffer; + var response = function(err, crlf) { + reader.removeAllListeners('data'); + reader.removeAllListeners('error'); + reader.removeAllListeners('end'); + var stream = reader; + reader = new PassThrough(); + if (err) { + reader.statusCode = 500; + reader.push(err.stack); + reader.push(null); } else { - if (crlf) { - crlf = new Buffer(crlf); - var index = util.indexOfList(buffer, crlf); - if (index != -1) { - extend(reader, parseRes(buffer.slice(0, index) + '')); - buffer = buffer.slice(index + crlf.length); + if (crlf) { + crlf = new Buffer(crlf); + var index = util.indexOfList(buffer, crlf); + if (index != -1) { + extend(reader, parseRes(buffer.slice(0, index) + '')); + buffer = buffer.slice(index + crlf.length); } } - buffer && reader.push(buffer); - stream.on('error', function(err) { - reader.emit('error', err); + buffer && reader.push(buffer); + stream.on('error', function(err) { + reader.emit('error', err); }); - stream.pipe(reader); + stream.pipe(reader); } - callback(reader); + callback(reader); }; - reader.on('data', function(data) { - buffer = buffer ? Buffer.concat([buffer, data]) : data; - if (HEADERS_SEP_RE.test(buffer + '')) { - response(null, RegExp.$1); + reader.on('data', function(data) { + buffer = buffer ? Buffer.concat([buffer, data]) : data; + if (HEADERS_SEP_RE.test(buffer + '')) { + response(null, RegExp.$1); } else if (buffer.length > MAX_HEADERS_SIZE) { - response(); + response(); } }); - reader.on('error', response); - reader.on('end', response); + reader.on('error', response); + reader.on('end', response); } else { - callback(reader); + callback(reader); } } module.exports = function(req, res, next) { - var options = req.options; - var config = this.config; - var protocol = options && options.protocol; - if (!protoMgr.isFileProxy(protocol)) { - return next(); + var options = req.options; + var config = this.config; + var protocol = options && options.protocol; + if (!protoMgr.isFileProxy(protocol)) { + return next(); } - var defaultType = mime.lookup(req.fullUrl.replace(/[?#].*$/, ''), 'text/html'); - var rule = req.rules.rule; - if (rule.value) { - var body = util.removeProtocol(rule.value, true); - var reader = isRawFileProtocol(protocol) ? getRawResByValue(body) : { - statusCode: 200, - body: body, - headers: { - 'content-type': (rule.key ? mime.lookup(rule.key, defaultType) : defaultType) + '; charset=utf-8' + var defaultType = mime.lookup(req.fullUrl.replace(/[?#].*$/, ''), 'text/html'); + var rule = req.rules.rule; + if (rule.value) { + var body = util.removeProtocol(rule.value, true); + var reader = isRawFileProtocol(protocol) ? getRawResByValue(body) : { + statusCode: 200, + body: body, + headers: { + 'content-type': (rule.key ? mime.lookup(rule.key, defaultType) : defaultType) + '; charset=utf-8' } }; - if (isTplProtocol(protocol)){ - reader.realUrl = rule.matcher; - render(reader); + if (isTplProtocol(protocol)){ + reader.realUrl = rule.matcher; + render(reader); } else { - reader = util.wrapResponse(reader); - reader.realUrl = rule.matcher; - res.response(reader); + reader = util.wrapResponse(reader); + reader.realUrl = rule.matcher; + res.response(reader); } - return; + return; } - readFiles(util.getRuleFiles(rule), function(err, path) { - if (err) { - if (/^x/.test(protocol)) { - extend(options, url.parse(/^xs/.test(protocol) ? req.fullUrl.replace(/^http:/, 'https:') : req.fullUrl)); - next(); + readFiles(util.getRuleFiles(rule), function(err, path) { + if (err) { + if (/^x/.test(protocol)) { + extend(options, url.parse(/^xs/.test(protocol) ? req.fullUrl.replace(/^http:/, 'https:') : req.fullUrl)); + next(); } else { - var notFound = util.wrapResponse({ - statusCode: 404, - body: 'Not found file ' + path + '', - headers: { - 'content-type': 'text/html; charset=utf-8' + var notFound = util.wrapResponse({ + statusCode: 404, + body: 'Not found file ' + path + '', + headers: { + 'content-type': 'text/html; charset=utf-8' } }); - notFound.realUrl = path; - res.response(notFound); + notFound.realUrl = path; + res.response(notFound); } - return; + return; } - var headers = { - 'server': config.name, - 'content-type': mime.lookup(path, defaultType) + '; charset=utf-8' + var headers = { + 'server': config.name, + 'content-type': mime.lookup(path, defaultType) + '; charset=utf-8' }; - if (isTplProtocol(protocol)) { - var reader = { - statusCode: 200, - realUrl: path, - headers: headers + if (isTplProtocol(protocol)) { + var reader = { + statusCode: 200, + realUrl: path, + headers: headers }; - fs.readFile(path, {encoding: 'utf8'}, function(err, data) { - if (err) { - return util.emitError(req, err); + fs.readFile(path, {encoding: 'utf8'}, function(err, data) { + if (err) { + return util.emitError(req, err); } - reader.body = data; - render(reader); + reader.body = data; + render(reader); }); } else { - getRawResByPath(protocol, path, function(reader) { - reader.realUrl = path; - reader.statusCode = reader.statusCode || 200; - reader.headers = reader.headers || headers; - res.response(reader); + getRawResByPath(protocol, path, function(reader) { + reader.realUrl = path; + reader.statusCode = reader.statusCode || 200; + reader.headers = reader.headers || headers; + res.response(reader); }); } }); - function render(reader) { - if (reader.body) { - var data = querystring.parse(util.getQueryString(req.fullUrl)); - if (!util.isEmptyObject(data)) { - reader.body = reader.body.replace(/\{([\w\-$]+)\}/g, function(all, matched) { - return matched in data ? data[matched] : all; + function render(reader) { + if (reader.body) { + var data = querystring.parse(util.getQueryString(req.fullUrl)); + if (!util.isEmptyObject(data)) { + reader.body = reader.body.replace(/\{([\w\-$]+)\}/g, function(all, matched) { + return matched in data ? data[matched] : all; }); } } - var realUrl = reader.realUrl; - reader = util.wrapResponse(reader); - reader.realUrl = realUrl; - res.response(reader); + var realUrl = reader.realUrl; + reader = util.wrapResponse(reader); + reader.realUrl = realUrl; + res.response(reader); } }; \ No newline at end of file diff --git a/lib/handlers/final-handler.js b/lib/handlers/final-handler.js index c4457e37b..fcf7e2fc5 100644 --- a/lib/handlers/final-handler.js +++ b/lib/handlers/final-handler.js @@ -1,4 +1,4 @@ module.exports = function(req, res, next) { - next(new Error('Unrecognized protocol ' + req.options.protocol)); + next(new Error('Unrecognized protocol ' + req.options.protocol)); }; diff --git a/lib/handlers/http-proxy.js b/lib/handlers/http-proxy.js index c0c05ab1e..dc68760a5 100644 --- a/lib/handlers/http-proxy.js +++ b/lib/handlers/http-proxy.js @@ -1,10 +1,10 @@ var protoMgr = require('../rules/protocols'); module.exports = function(req, res, next) { - var protocol = req.options && req.options.protocol; - if (!protoMgr.isProxyProtocol(protocol) && !protoMgr.isWebProtocol(protocol)) { - next(); - return; + var protocol = req.options && req.options.protocol; + if (!protoMgr.isProxyProtocol(protocol) && !protoMgr.isWebProtocol(protocol)) { + next(); + return; } - req.request(req.options); + req.request(req.options); }; \ No newline at end of file diff --git a/lib/handlers/index.js b/lib/handlers/index.js index e3da334d9..6908064a1 100644 --- a/lib/handlers/index.js +++ b/lib/handlers/index.js @@ -4,5 +4,5 @@ module.exports = ['./file-proxy', './plugin-handler', './final-handler', './error-handler'].map(function(mod) { - return require(mod); + return require(mod); }); \ No newline at end of file diff --git a/lib/handlers/plugin-handler.js b/lib/handlers/plugin-handler.js index 6206878c3..b58d03506 100644 --- a/lib/handlers/plugin-handler.js +++ b/lib/handlers/plugin-handler.js @@ -3,42 +3,42 @@ var util = require('../util'); var pluginMgr = require('../plugins'); module.exports = function(req, res, next) { - var protocol = req.options && req.options.protocol; - var plugin = pluginMgr.getPlugin(protocol); - if (!plugin) { - return next(); + var protocol = req.options && req.options.protocol; + var plugin = pluginMgr.getPlugin(protocol); + if (!plugin) { + return next(); } - pluginMgr.loadPlugin(plugin, function(err, ports) { - if (err || !ports.port) { - res.response(util.wrapGatewayError(err || new Error('No plugin.server'))); - return; + pluginMgr.loadPlugin(plugin, function(err, ports) { + if (err || !ports.port) { + res.response(util.wrapGatewayError(err || new Error('No plugin.server'))); + return; } - var options = url.parse(req.fullUrl); - req.headers[pluginMgr.FULL_URL_HEADER] = encodeURIComponent(req.fullUrl); - if (options.protocol == 'https:') { - options.protocol = 'http:'; - req.headers[pluginMgr.SSL_FLAG_HEADER] = 'true'; + var options = url.parse(req.fullUrl); + req.headers[pluginMgr.FULL_URL_HEADER] = encodeURIComponent(req.fullUrl); + if (options.protocol == 'https:') { + options.protocol = 'http:'; + req.headers[pluginMgr.SSL_FLAG_HEADER] = 'true'; } - var localHost = req.rules.host; - if (localHost) { - req.headers[pluginMgr.LOCAL_HOST_HEADER] = encodeURIComponent(util.removeProtocol(localHost.matcher, true)); - if (localHost.port) { - req.headers[pluginMgr.HOST_PORT_HEADER] = localHost.port; + var localHost = req.rules.host; + if (localHost) { + req.headers[pluginMgr.LOCAL_HOST_HEADER] = encodeURIComponent(util.removeProtocol(localHost.matcher, true)); + if (localHost.port) { + req.headers[pluginMgr.HOST_PORT_HEADER] = localHost.port; } } - options.host = '127.0.0.1'; - options.port = ports.port; - options.href = util.changePort(req.fullUrl, ports.port); - options.localDNS = true; - var ruleValue = util.getMatcherValue(req.rules.rule); - if (ruleValue) { - req.headers[pluginMgr.RULE_VALUE_HEADER] = encodeURIComponent(ruleValue); + options.host = '127.0.0.1'; + options.port = ports.port; + options.href = util.changePort(req.fullUrl, ports.port); + options.localDNS = true; + var ruleValue = util.getMatcherValue(req.rules.rule); + if (ruleValue) { + req.headers[pluginMgr.RULE_VALUE_HEADER] = encodeURIComponent(ruleValue); } - options.isPlugin = true; - req.request(options); + options.isPlugin = true; + req.request(options); }); }; \ No newline at end of file diff --git a/lib/https/ca.js b/lib/https/ca.js index 1aed81755..77c923397 100644 --- a/lib/https/ca.js +++ b/lib/https/ca.js @@ -16,14 +16,14 @@ var ROOT_KEY, ROOT_CRT; function getMacAddress() { - var ifaces = os.networkInterfaces(); - for (var i in ifaces) { - var addrList = ifaces[i]; - if (addrList) { - for (var j = 0, len = addrList.length; j< len; j++) { - var addr = addrList[j]; - if (addr && !addr.internal && addr.family == 'IPv4') { - return addr.mac || addr.address; + var ifaces = os.networkInterfaces(); + for (var i in ifaces) { + var addrList = ifaces[i]; + if (addrList) { + for (var j = 0, len = addrList.length; j< len; j++) { + var addr = addrList[j]; + if (addr && !addr.internal && addr.family == 'IPv4') { + return addr.mac || addr.address; } } } @@ -31,144 +31,144 @@ function getMacAddress() { } function createCertificate(hostname) { - var cert = cachePairs[hostname]; - if (cert) { - return cert; + var cert = cachePairs[hostname]; + if (cert) { + return cert; } - cert = createCert(pki.setRsaPublicKey(ROOT_KEY.n, ROOT_KEY.e), + cert = createCert(pki.setRsaPublicKey(ROOT_KEY.n, ROOT_KEY.e), crypto.createHash('sha1') .update(hostname, 'binary') .digest('hex')); - cert.setSubject([{ - name: 'commonName', - value: hostname + cert.setSubject([{ + name: 'commonName', + value: hostname }]); - cert.setIssuer(ROOT_CRT.subject.attributes); - cert.sign(ROOT_KEY, forge.md.sha256.create()); - cert = cachePairs[hostname] = { - key: pki.privateKeyToPem(ROOT_KEY), - cert: pki.certificateToPem(cert) + cert.setIssuer(ROOT_CRT.subject.attributes); + cert.sign(ROOT_KEY, forge.md.sha256.create()); + cert = cachePairs[hostname] = { + key: pki.privateKeyToPem(ROOT_KEY), + cert: pki.certificateToPem(cert) }; - return cert; + return cert; } function createRootCA() { - if (ROOT_KEY && ROOT_CRT) { - return; + if (ROOT_KEY && ROOT_CRT) { + return; } - try { - ROOT_KEY = fs.readFileSync(ROOT_KEY_FILE); - ROOT_CRT = fs.readFileSync(ROOT_CRT_FILE); + try { + ROOT_KEY = fs.readFileSync(ROOT_KEY_FILE); + ROOT_CRT = fs.readFileSync(ROOT_CRT_FILE); } catch (e) { - ROOT_KEY = ROOT_CRT = null; + ROOT_KEY = ROOT_CRT = null; } - if (ROOT_KEY && ROOT_CRT && ROOT_KEY.length && ROOT_CRT.length) { - ROOT_KEY = pki.privateKeyFromPem(ROOT_KEY); - ROOT_CRT = pki.certificateFromPem(ROOT_CRT); + if (ROOT_KEY && ROOT_CRT && ROOT_KEY.length && ROOT_CRT.length) { + ROOT_KEY = pki.privateKeyFromPem(ROOT_KEY); + ROOT_CRT = pki.certificateFromPem(ROOT_CRT); } else { - var cert = createCACert(); - ROOT_CRT = cert.cert; - ROOT_KEY = cert.key; - fs.writeFileSync(ROOT_KEY_FILE, pki.privateKeyToPem(ROOT_KEY).toString()); - fs.writeFileSync(ROOT_CRT_FILE, pki.certificateToPem(ROOT_CRT).toString()); + var cert = createCACert(); + ROOT_CRT = cert.cert; + ROOT_KEY = cert.key; + fs.writeFileSync(ROOT_KEY_FILE, pki.privateKeyToPem(ROOT_KEY).toString()); + fs.writeFileSync(ROOT_CRT_FILE, pki.certificateToPem(ROOT_CRT).toString()); } - exports.DEFAULT_CERT_CTX = createSecureContext({ - key: ROOT_KEY, - cert: ROOT_CRT + exports.DEFAULT_CERT_CTX = createSecureContext({ + key: ROOT_KEY, + cert: ROOT_CRT }); } function createCACert() { - var keys = pki.rsa.generateKeyPair(1024); - var cert = createCert(keys.publicKey); - var name = []; - if (config.homeDirname) { - try { + var keys = pki.rsa.generateKeyPair(1024); + var cert = createCert(keys.publicKey); + var name = []; + if (config.homeDirname) { + try { //避免特殊字符导致根证书无法安装 - name.push(encodeURIComponent(config.homeDirname.slice(0, 20))); + name.push(encodeURIComponent(config.homeDirname.slice(0, 20))); } catch(e) {} } - if (MAC_ADDR) { - name.push(MAC_ADDR); + if (MAC_ADDR) { + name.push(MAC_ADDR); } - name = name.join('@'); - name = 'WHISTLE' + (name ? '(' + name + ')' : ''); - var attrs = [ { - name : 'commonName', - value : name + name = name.join('@'); + name = 'WHISTLE' + (name ? '(' + name + ')' : ''); + var attrs = [ { + name : 'commonName', + value : name }, { - name : 'countryName', - value : 'CN' + name : 'countryName', + value : 'CN' }, { - shortName : 'ST', - value : 'ZJ' + shortName : 'ST', + value : 'ZJ' }, { - name : 'localityName', - value : 'HZ' + name : 'localityName', + value : 'HZ' }, { - name : 'organizationName', - value : name + name : 'organizationName', + value : name }, { - shortName : 'OU', - value : 'WPROXY' + shortName : 'OU', + value : 'WPROXY' } ]; - cert.setSubject(attrs); - cert.setIssuer(attrs); - cert.setExtensions([ { - name : 'basicConstraints', - cA : true + cert.setSubject(attrs); + cert.setIssuer(attrs); + cert.setExtensions([ { + name : 'basicConstraints', + cA : true }, { - name : 'keyUsage', - keyCertSign : true, - digitalSignature : true, - nonRepudiation : true, - keyEncipherment : true, - dataEncipherment : true + name : 'keyUsage', + keyCertSign : true, + digitalSignature : true, + nonRepudiation : true, + keyEncipherment : true, + dataEncipherment : true }, { - name : 'extKeyUsage', - serverAuth : true, - clientAuth : true, - codeSigning : true, - emailProtection : true, - timeStamping : true + name : 'extKeyUsage', + serverAuth : true, + clientAuth : true, + codeSigning : true, + emailProtection : true, + timeStamping : true }, { - name : 'nsCertType', - client : true, - server : true, - email : true, - objsign : true, - sslCA : true, - emailCA : true, - objCA : true + name : 'nsCertType', + client : true, + server : true, + email : true, + objsign : true, + sslCA : true, + emailCA : true, + objCA : true } ]); - cert.sign(keys.privateKey, forge.md.sha256.create()); + cert.sign(keys.privateKey, forge.md.sha256.create()); - return { - key: keys.privateKey, - cert: cert + return { + key: keys.privateKey, + cert: cert }; } function createCert(publicKey, serialNumber) { - var cert = pki.createCertificate(); - cert.publicKey = publicKey; - cert.serialNumber = serialNumber || '01'; - cert.validity.notBefore = new Date(); - cert.validity.notAfter = new Date(); - cert.validity.notAfter + var cert = pki.createCertificate(); + cert.publicKey = publicKey; + cert.serialNumber = serialNumber || '01'; + cert.validity.notBefore = new Date(); + cert.validity.notAfter = new Date(); + cert.validity.notAfter .setFullYear(cert.validity.notBefore.getFullYear() + 10); - return cert; + return cert; } function getRootCAFile() { - return ROOT_CRT_FILE; + return ROOT_CRT_FILE; } createRootCA();//启动生成ca diff --git a/lib/https/index.js b/lib/https/index.js index bf88393a2..88c5877b5 100644 --- a/lib/https/index.js +++ b/lib/https/index.js @@ -16,41 +16,41 @@ var index = 0; var proxy; function handleWebsocket(socket, clientIp, callback) { - var wss = clientIp !== false; - var reqEmitter = new EventEmitter(); - var headers = socket.headers; - var fullUrl = socket.fullUrl = (wss ? 'wss:' : 'ws:') + '//' + headers.host + socket.url; - var _rules = socket.rules = rules.resolveRules(fullUrl); - var filter = socket.filter = rules.resolveFilter(fullUrl); - var now = Date.now(); - var reqData = { - ip: util.removeIPV6Prefix(clientIp || socket.remoteAddress), - method: util.toUpperCase(socket.method) || 'GET', - httpVersion: socket.httpVersion || '1.1', - headers: headers + var wss = clientIp !== false; + var reqEmitter = new EventEmitter(); + var headers = socket.headers; + var fullUrl = socket.fullUrl = (wss ? 'wss:' : 'ws:') + '//' + headers.host + socket.url; + var _rules = socket.rules = rules.resolveRules(fullUrl); + var filter = socket.filter = rules.resolveFilter(fullUrl); + var now = Date.now(); + var reqData = { + ip: util.removeIPV6Prefix(clientIp || socket.remoteAddress), + method: util.toUpperCase(socket.method) || 'GET', + httpVersion: socket.httpVersion || '1.1', + headers: headers }; - var resData = {}; - var data = reqEmitter.data = { - url: fullUrl, - startTime: now, - rules: _rules, - req: reqData, - res: resData + var resData = {}; + var data = reqEmitter.data = { + url: fullUrl, + startTime: now, + rules: _rules, + req: reqData, + res: resData }; - socket.clientIp = reqData.ip; - socket.reqId = data.reqId = ++index; + socket.clientIp = reqData.ip; + socket.reqId = data.reqId = ++index; - var reqSocket, options, plugin, pluginRules, matchedUrl, done; - var pluginHomePage = plugin = pluginMgr.getPluginByHomePage(fullUrl); - var timeout = util.setTimeout(function() { - destroy(new Error('Timeout')); + var reqSocket, options, plugin, pluginRules, matchedUrl, done; + var pluginHomePage = plugin = pluginMgr.getPluginByHomePage(fullUrl); + var timeout = util.setTimeout(function() { + destroy(new Error('Timeout')); }); - if (pluginHomePage) { - return connect(); + if (pluginHomePage) { + return connect(); } - plugin = pluginMgr.resolvePluginRule(socket); + plugin = pluginMgr.resolvePluginRule(socket); pluginMgr.getRules(socket, function(rulesMgr) { if (pluginRules = rulesMgr) { util.handlePluginRules(socket, rulesMgr); @@ -97,10 +97,10 @@ function handleWebsocket(socket, clientIp, callback) { var onConnect = function(proxySocket) { if (wss) { proxySocket = tls.connect({ - rejectUnauthorized: false, - socket: proxySocket, - servername: dstOptions.hostname - }).on('error', execCallback); + rejectUnauthorized: false, + socket: proxySocket, + servername: dstOptions.hostname + }).on('error', execCallback); } reqSocket = proxySocket; @@ -127,115 +127,115 @@ function handleWebsocket(socket, clientIp, callback) { }); }); - function connect() { - options = url.parse(fullUrl); - !pluginHomePage && !filter.hide && proxy.emit('request', reqEmitter); + function connect() { + options = url.parse(fullUrl); + !pluginHomePage && !filter.hide && proxy.emit('request', reqEmitter); - if (plugin) { - pluginMgr.loadPlugin(plugin, function(err, ports) { - if (err) { - return execCallback(err); + if (plugin) { + pluginMgr.loadPlugin(plugin, function(err, ports) { + if (err) { + return execCallback(err); } - if (pluginHomePage && !ports.uiPort) { - return execCallback(new Error('Not implemented')); + if (pluginHomePage && !ports.uiPort) { + return execCallback(new Error('Not implemented')); } - var headers = socket.headers; - headers[pluginMgr.FULL_URL_HEADER] = encodeURIComponent(fullUrl); - if (options.protocol == 'wss:') { - options.protocol = 'ws:'; - headers[pluginMgr.SSL_FLAG_HEADER] = 'true'; + var headers = socket.headers; + headers[pluginMgr.FULL_URL_HEADER] = encodeURIComponent(fullUrl); + if (options.protocol == 'wss:') { + options.protocol = 'ws:'; + headers[pluginMgr.SSL_FLAG_HEADER] = 'true'; } - var ruleValue = _rules.rule && util.removeProtocol(_rules.rule.matcher, true); - if (ruleValue) { - headers[pluginMgr.RULE_VALUE_HEADER] = encodeURIComponent(ruleValue); + var ruleValue = _rules.rule && util.removeProtocol(_rules.rule.matcher, true); + if (ruleValue) { + headers[pluginMgr.RULE_VALUE_HEADER] = encodeURIComponent(ruleValue); } - if (socket.reqId) { - headers[pluginMgr.REQ_ID_HEADER] = socket.reqId; - } - if (socket.clientIP) { - headers[pluginMgr.CLIENT_IP_HEADER] = socket.clientIP; + if (socket.reqId) { + headers[pluginMgr.REQ_ID_HEADER] = socket.reqId; +} + if (socket.clientIP) { + headers[pluginMgr.CLIENT_IP_HEADER] = socket.clientIP; } - options.port = pluginHomePage ? ports.uiPort : ports.port; - if (!pluginHomePage) { - data.realUrl = util.changePort(fullUrl, options.port); + options.port = pluginHomePage ? ports.uiPort : ports.port; + if (!pluginHomePage) { + data.realUrl = util.changePort(fullUrl, options.port); } - if (!options.port) { - return execCallback(new Error(pluginHomePage ? 'Not implemented' : 'No plugin.server')); - } + if (!options.port) { + return execCallback(new Error(pluginHomePage ? 'Not implemented' : 'No plugin.server')); +} - var localHost = _rules.host; - if (localHost) { - headers[pluginMgr.LOCAL_HOST_HEADER] = encodeURIComponent(util.removeProtocol(localHost.matcher, true)); - if (localHost.port) { - headers[pluginMgr.HOST_PORT_HEADER] = localHost.port; + var localHost = _rules.host; + if (localHost) { + headers[pluginMgr.LOCAL_HOST_HEADER] = encodeURIComponent(util.removeProtocol(localHost.matcher, true)); + if (localHost.port) { + headers[pluginMgr.HOST_PORT_HEADER] = localHost.port; } } - _connect(); + _connect(); }); } else { - _connect(); + _connect(); } } - function _connect() { - resolveHost(fullUrl, function(ip, port) { - var isWss = options.protocol == 'wss:'; - resData.ip = port ? ip + ':' + port : ip; - reqSocket = (isWss ? tls : net).connect({ - rejectUnauthorized: false, - host: ip, - port: port || options.port || (isWss ? 443 : 80) + function _connect() { + resolveHost(fullUrl, function(ip, port) { + var isWss = options.protocol == 'wss:'; + resData.ip = port ? ip + ':' + port : ip; + reqSocket = (isWss ? tls : net).connect({ + rejectUnauthorized: false, + host: ip, + port: port || options.port || (isWss ? 443 : 80) }, pipeData); - abortIfUnavailable(reqSocket); + abortIfUnavailable(reqSocket); }); } - function pipeData() { - clearTimeout(timeout); - var headers = socket.headers; - var origin; - if (matchedUrl) { - headers.host = options.host; - origin = headers.origin; - headers.origin = (options.protocol == 'wss:' ? 'https://' : 'http://') + options.host; + function pipeData() { + clearTimeout(timeout); + var headers = socket.headers; + var origin; + if (matchedUrl) { + headers.host = options.host; + origin = headers.origin; + headers.origin = (options.protocol == 'wss:' ? 'https://' : 'http://') + options.host; } - if (_rules.hostname) { - headers.host = util.getMatcherValue(_rules.hostname); + if (_rules.hostname) { + headers.host = util.getMatcherValue(_rules.hostname); } - reqSocket.write(socket.getBuffer((plugin || matchedUrl || _rules.hostname) ? headers : null)); - socket.pipe(reqSocket); - util.parseReq(reqSocket, function(err, res) { - if (err) { - return execCallback(err); + reqSocket.write(socket.getBuffer((plugin || matchedUrl || _rules.hostname) ? headers : null)); + socket.pipe(reqSocket); + util.parseReq(reqSocket, function(err, res) { + if (err) { + return execCallback(err); } - headers = res.headers; - if (matchedUrl) { - headers['access-control-allow-origin'] = origin; + headers = res.headers; + if (matchedUrl) { + headers['access-control-allow-origin'] = origin; } - socket.write(res.getBuffer(matchedUrl ? headers : null)); - res.pipe(socket); - resData.headers = headers; - resData.statusCode = res.statusCode; - reqEmitter.emit('response', data); - execCallback(null, reqSocket); + socket.write(res.getBuffer(matchedUrl ? headers : null)); + res.pipe(socket); + resData.headers = headers; + resData.statusCode = res.statusCode; + reqEmitter.emit('response', data); + execCallback(null, reqSocket); }, true); } - function resolveHost(url, callback) { - data.status = 'requestEnd'; - pluginMgr.postStatus(socket.pluginMgr, data); - if (plugin) { + function resolveHost(url, callback) { + data.status = 'requestEnd'; + pluginMgr.postStatus(socket.pluginMgr, data); + if (plugin) { return callback(LOCALHOST); } - rules.resolveHost(url, function(err, ip, port, host) { + rules.resolveHost(url, function(err, ip, port, host) { if (err) { return execCallback(err); } @@ -249,93 +249,93 @@ function handleWebsocket(socket, clientIp, callback) { reqEmitter.emit('send', data); callback(ip, port); }, pluginRules); - } +} - function abortIfUnavailable(socket) { - return socket.on('error', destroy) + function abortIfUnavailable(socket) { + return socket.on('error', destroy) .on('close', destroy); } - function destroy(err) { - socket.destroy(); - reqSocket && reqSocket.destroy(); - execCallback(err); - err && logger.error(fullUrl + '\n' + err.stack); + function destroy(err) { + socket.destroy(); + reqSocket && reqSocket.destroy(); + execCallback(err); + err && logger.error(fullUrl + '\n' + err.stack); } - function execCallback(err, _socket) { - if (done) { - return; + function execCallback(err, _socket) { + if (done) { + return; } - done = true; - clearTimeout(timeout); - data.responseTime = data.endTime = Date.now(); - resData.ip = resData.ip || LOCALHOST; - var status; - if (!err && !_socket) { - err = new Error('Aborted'); - data.reqError = true; - resData.statusCode ='aborted'; - reqData.body = util.getErrorStack(err); - reqEmitter.emit('abort', data); - status = 'aborted'; + done = true; + clearTimeout(timeout); + data.responseTime = data.endTime = Date.now(); + resData.ip = resData.ip || LOCALHOST; + var status; + if (!err && !_socket) { + err = new Error('Aborted'); + data.reqError = true; + resData.statusCode ='aborted'; + reqData.body = util.getErrorStack(err); + reqEmitter.emit('abort', data); + status = 'aborted'; } else if (err) { - data.resError = true; - resData.statusCode = resData.statusCode || 502; - resData.body = util.getErrorStack(err); - util.emitError(reqEmitter, data); - status = 'error'; + data.resError = true; + resData.statusCode = resData.statusCode || 502; + resData.body = util.getErrorStack(err); + util.emitError(reqEmitter, data); + status = 'error'; } else { - reqEmitter.emit('end', data); - status = 'responseEnd'; + reqEmitter.emit('end', data); + status = 'responseEnd'; } - callback(err, _socket); - data.status = status; - pluginMgr.postStatus(socket.pluginMgr, data); + callback(err, _socket); + data.status = status; + pluginMgr.postStatus(socket.pluginMgr, data); } } function handleTlsSocket(socket, hostname) { - var reqSocket; - function destroy(err) { - socket.destroy(); - reqSocket && reqSocket.destroy(); - err && logger.error(hostname + '\n' + err.stack); + var reqSocket; + function destroy(err) { + socket.destroy(); + reqSocket && reqSocket.destroy(); + err && logger.error(hostname + '\n' + err.stack); } - function abortIfUnavailable(socket) { - return socket.on('error', destroy) + function abortIfUnavailable(socket) { + return socket.on('error', destroy) .on('close', destroy); } - abortIfUnavailable(socket); - util.parseReq(socket, function(err, socket) { - if (err) { - return destroy(err); + abortIfUnavailable(socket); + util.parseReq(socket, function(err, socket) { + if (err) { + return destroy(err); } //wss - var clientIp = ports[socket.remotePort]; - var headers = socket.headers; - if (headers.upgrade && headers.upgrade.toLowerCase() == 'websocket') { - handleWebsocket(socket, clientIp, function(err, req) { - if (err) { - return destroy(err); + var clientIp = ports[socket.remotePort]; + var headers = socket.headers; + if (headers.upgrade && headers.upgrade.toLowerCase() == 'websocket') { + handleWebsocket(socket, clientIp, function(err, req) { + if (err) { + return destroy(err); } - reqSocket = req; - abortIfUnavailable(reqSocket); + reqSocket = req; + abortIfUnavailable(reqSocket); }); } else { //https - socket.pause(); - reqSocket = net.connect(config.port, LOCALHOST, function() { - headers[config.HTTPS_FIELD] = 1; - headers[config.CLIENT_IP_HEAD] = clientIp; - reqSocket.write(socket.getBuffer(headers)); - socket.resume(); - socket.pipe(reqSocket).pipe(socket); + socket.pause(); + reqSocket = net.connect(config.port, LOCALHOST, function() { + headers[config.HTTPS_FIELD] = 1; + headers[config.CLIENT_IP_HEAD] = clientIp; + reqSocket.write(socket.getBuffer(headers)); + socket.resume(); + socket.pipe(reqSocket).pipe(socket); }); - abortIfUnavailable(reqSocket); + abortIfUnavailable(reqSocket); } }, true); @@ -343,54 +343,54 @@ function handleTlsSocket(socket, hostname) { } module.exports = function dispatch(socket, hostname, _proxy) { - proxy = _proxy; + proxy = _proxy; - var reqSocket; - function destroy(err) { - socket.destroy(); - reqSocket && reqSocket.destroy(); - err && logger.error(hostname + '\n' + err.stack); + var reqSocket; + function destroy(err) { + socket.destroy(); + reqSocket && reqSocket.destroy(); + err && logger.error(hostname + '\n' + err.stack); } - function abortIfUnavailable(socket) { - return socket.on('error', destroy) + function abortIfUnavailable(socket) { + return socket.on('error', destroy) .on('close', destroy); } - abortIfUnavailable(socket); - socket.on('data', request); - socket.on('end', request); + abortIfUnavailable(socket); + socket.on('data', request); + socket.on('end', request); - function request(chunk) { - socket.removeListener('data', request); - socket.removeListener('end', request); - if (!chunk) {//没有数据 - return destroy(); + function request(chunk) { + socket.removeListener('data', request); + socket.removeListener('end', request); + if (!chunk) {//没有数据 + return destroy(); } - if (/upgrade\s*:\s*websocket/i.test(chunk.toString())) { //ws - util.parseReq(socket, function(err, socket) { - if (err) { - return destroy(err); + if (/upgrade\s*:\s*websocket/i.test(chunk.toString())) { //ws + util.parseReq(socket, function(err, socket) { + if (err) { + return destroy(err); } - handleWebsocket(socket, false, function(err, req) { - if (err) { - return destroy(err); + handleWebsocket(socket, false, function(err, req) { + if (err) { + return destroy(err); } - abortIfUnavailable(reqSocket = req); + abortIfUnavailable(reqSocket = req); }); }, chunk, true); } else { - serverAgent.createServer(hostname, function(socket) { - handleTlsSocket(socket, hostname); + serverAgent.createServer(hostname, function(socket) { + handleTlsSocket(socket, hostname); }, function(port) { - reqSocket = net.connect(port, LOCALHOST, function() { - ports[reqSocket.localPort] = socket.remoteAddress; - reqSocket.write(chunk); - reqSocket.pipe(socket).pipe(reqSocket); + reqSocket = net.connect(port, LOCALHOST, function() { + ports[reqSocket.localPort] = socket.remoteAddress; + reqSocket.write(chunk); + reqSocket.pipe(socket).pipe(reqSocket); }); - abortIfUnavailable(reqSocket); + abortIfUnavailable(reqSocket); }); } } diff --git a/lib/https/server-agent.js b/lib/https/server-agent.js index 05e349541..861c773cc 100644 --- a/lib/https/server-agent.js +++ b/lib/https/server-agent.js @@ -8,94 +8,94 @@ var TIMEOUT = 6000; var DELAY = 600; function ServerAgent() { - this._cache = {}; - this._serverCount = 0; + this._cache = {}; + this._serverCount = 0; } var proto = ServerAgent.prototype; proto.createServer = function createServer(hostname, secureConnectionListener, callback) { - var self = this; - var cache = self._cache; + var self = this; + var cache = self._cache; - var promise = cache[hostname]; - var defer; + var promise = cache[hostname]; + var defer; - if (!promise) { - defer = Q.defer(); - cache[hostname] = promise = defer.promise; + if (!promise) { + defer = Q.defer(); + cache[hostname] = promise = defer.promise; } - promise.done(callback); + promise.done(callback); - if (!defer) { - return ; + if (!defer) { + return ; } - self.freeServer(); - getServer(ca.createCertificate(hostname), secureConnectionListener, + self.freeServer(); + getServer(ca.createCertificate(hostname), secureConnectionListener, function(port, server) { - var removeServer = function() { - self.removeServer(hostname); + var removeServer = function() { + self.removeServer(hostname); }; - server.on('error', removeServer); - setTimeout(function() { - promise.server = server; - var timeout = setTimeout(removeServer, TIMEOUT); - server.once('secureConnection', function() { - clearTimeout(timeout); + server.on('error', removeServer); + setTimeout(function() { + promise.server = server; + var timeout = setTimeout(removeServer, TIMEOUT); + server.once('secureConnection', function() { + clearTimeout(timeout); }); - defer.resolve(port); + defer.resolve(port); }, DELAY); }); - self._serverCount++; + self._serverCount++; - return self; + return self; }; proto.removeServer = function removeServer(hostname) { - var self = this; - var cache = self._cache; - var promise = cache[hostname]; - if (!promise) { - return; + var self = this; + var cache = self._cache; + var promise = cache[hostname]; + if (!promise) { + return; } - delete cache[hostname]; - --self._serverCount; - setTimeout(function() { - try { - promise.server.close(); + delete cache[hostname]; + --self._serverCount; + setTimeout(function() { + try { + promise.server.close(); } catch(e) {} //重复关闭会导致异常 }, TIMEOUT); }; proto.freeServer = function() { - var self = this; - if (self._serverCount < MAX_SERVERS) { - return; + var self = this; + if (self._serverCount < MAX_SERVERS) { + return; } - var cache = self._cache; - for (var i in cache) { - destroy(i); + var cache = self._cache; + for (var i in cache) { + destroy(i); } - function destroy(hostname) { - var promise = cache[hostname]; - if (promise._pending) { - return; + function destroy(hostname) { + var promise = cache[hostname]; + if (promise._pending) { + return; } - promise._pending = true; - promise.done(function(port) { - var server = promise.server; - server.getConnections(function(err, count) { - promise._pending = false; - if (!err && !count && self._serverCount > MAX_SERVERS) { - delete cache[hostname]; - --self._serverCount; - setTimeout(function() { - try { - server.close(); + promise._pending = true; + promise.done(function(port) { + var server = promise.server; + server.getConnections(function(err, count) { + promise._pending = false; + if (!err && !count && self._serverCount > MAX_SERVERS) { + delete cache[hostname]; + --self._serverCount; + setTimeout(function() { + try { + server.close(); } catch(e) {} //重复关闭会导致异常 }, DELAY); } @@ -105,15 +105,15 @@ proto.freeServer = function() { }; proto.destroy = function destroy() { - var cache = this._cache; - this._cache = {}; - this._serverCount = 0; - for (var i in cache) { - var promise = cache[i]; - promise.done(function() { - setTimeout(function() { - try { - promise.server.close(); + var cache = this._cache; + this._cache = {}; + this._serverCount = 0; + for (var i in cache) { + var promise = cache[i]; + promise.done(function() { + setTimeout(function() { + try { + promise.server.close(); } catch(e) {} //重复关闭会导致异常 }, DELAY); }); @@ -121,20 +121,20 @@ proto.destroy = function destroy() { }; function getServer(options, secureConnectionListener, callback) { - if (curPort > MAX_PORT) { - curPort = 40000; + if (curPort > MAX_PORT) { + curPort = 40000; } - var server = tls.createServer(options, secureConnectionListener); - var next = function() { - getServer(options, secureConnectionListener, callback); + var server = tls.createServer(options, secureConnectionListener); + var next = function() { + getServer(options, secureConnectionListener, callback); }; - server.on('error', next); + server.on('error', next); - var port = curPort++; - server.listen(port, function() { - server.removeListener('error', next); - callback(port, server); + var port = curPort++; + server.listen(port, function() { + server.removeListener('error', next); + callback(port, server); }); } diff --git a/lib/index.js b/lib/index.js index 79c83aa85..c1d2edf0e 100644 --- a/lib/index.js +++ b/lib/index.js @@ -25,281 +25,281 @@ var index = 0; function tunnelProxy(server, proxy) { //see: https://github.com/joyent/node/issues/9272 - if (typeof tls.checkServerIdentity == 'function') { - var checkServerIdentity = tls.checkServerIdentity; - tls.checkServerIdentity = function() { - try { - return checkServerIdentity.apply(this, arguments); + if (typeof tls.checkServerIdentity == 'function') { + var checkServerIdentity = tls.checkServerIdentity; + tls.checkServerIdentity = function() { + try { + return checkServerIdentity.apply(this, arguments); } catch(err) { - logger.error(err); - return err; + logger.error(err); + return err; } }; } - process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = '0'; - server.on('connect', function(req, reqSocket, head) {//ws, wss, https proxy - var tunnelUrl = req.fullUrl = util.setProtocol(/^[^:\/]+:\d+$/.test(req.url) ? req.url : req.headers.host, true); - var options = parseUrl(); - var tunnelUrl = req.fullUrl = 'tunnel://' + options.host; - var resSocket, proxySocket, responsed; - req.isTunnel = true; - var hostname = options.hostname; - var _rules = req.rules = rules.resolveRules(tunnelUrl); - var filter = rules.resolveFilter(tunnelUrl); - var disable = rules.resolveDisable(tunnelUrl); - var plugin = pluginMgr.getPluginByRuleUrl(util.rule.getUrl(_rules.rule)); - var rulesMgr = plugin && plugin.rulesMgr; - util.handlePluginRules(req, rulesMgr); - if (rulesMgr && !filter.rule) { - extend(_rules, rulesMgr.resolveRules(req.fullUrl)); + process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = '0'; + server.on('connect', function(req, reqSocket, head) {//ws, wss, https proxy + var tunnelUrl = req.fullUrl = util.setProtocol(/^[^:\/]+:\d+$/.test(req.url) ? req.url : req.headers.host, true); + var options = parseUrl(); + var tunnelUrl = req.fullUrl = 'tunnel://' + options.host; + var resSocket, proxySocket, responsed; + req.isTunnel = true; + var hostname = options.hostname; + var _rules = req.rules = rules.resolveRules(tunnelUrl); + var filter = rules.resolveFilter(tunnelUrl); + var disable = rules.resolveDisable(tunnelUrl); + var plugin = pluginMgr.getPluginByRuleUrl(util.rule.getUrl(_rules.rule)); + var rulesMgr = plugin && plugin.rulesMgr; + util.handlePluginRules(req, rulesMgr); + if (rulesMgr && !filter.rule) { + extend(_rules, rulesMgr.resolveRules(req.fullUrl)); } - var useTunnelPolicy = req.headers[WHISTLE_POLICY_HEADER] == 'tunnel'; - if (!useTunnelPolicy && (LOCAL_URL_RE.test(hostname) || ((filter.https || filter.tunnel + var useTunnelPolicy = req.headers[WHISTLE_POLICY_HEADER] == 'tunnel'; + if (!useTunnelPolicy && (LOCAL_URL_RE.test(hostname) || ((filter.https || filter.tunnel || rulesUtil.properties.get('interceptHttpsConnects')) && !filter.intercept && !disable.intercept))) { - dispatch(reqSocket, hostname, proxy); - sendEstablished(); - return; + dispatch(reqSocket, hostname, proxy); + sendEstablished(); + return; } - var reqEmitter = new EventEmitter(); - var headers = req.headers; - var reqData = { - ip: util.getClientIp(req) || LOCALHOST, - method: util.toUpperCase(req.method) || 'CONNECT', - httpVersion: req.httpVersion || '1.1', - headers: headers + var reqEmitter = new EventEmitter(); + var headers = req.headers; + var reqData = { + ip: util.getClientIp(req) || LOCALHOST, + method: util.toUpperCase(req.method) || 'CONNECT', + httpVersion: req.httpVersion || '1.1', + headers: headers }; - var resData = {headers: {}}; - var data = reqEmitter.data = { - url: options.host, - startTime: Date.now(), - rules: _rules, - req: reqData, - res: resData, - isHttps: true + var resData = {headers: {}}; + var data = reqEmitter.data = { + url: options.host, + startTime: Date.now(), + rules: _rules, + req: reqData, + res: resData, + isHttps: true }; - req.clientIp = reqData.ip; - abortIfUnavailable(reqSocket); - if (!rulesUtil.properties.get('hideHttpsConnects') && !filter.hide) { - proxy.emit('request', reqEmitter); + req.clientIp = reqData.ip; + abortIfUnavailable(reqSocket); + if (!rulesUtil.properties.get('hideHttpsConnects') && !filter.hide) { + proxy.emit('request', reqEmitter); } - if (disable.tunnel) { - return reqSocket.destroy(); + if (disable.tunnel) { + return reqSocket.destroy(); } - req.reqId = ++index; - plugin = pluginMgr.resolvePluginRule(req); - pluginMgr.getTunnelRules(req, function(_rulesMgr) { - if (_rulesMgr) { - rulesMgr = _rulesMgr; - var pluginRules = rulesMgr.resolveRules(tunnelUrl); - var _disable = rulesMgr.resolveDisable(tunnelUrl); - if (pluginRules.rule) { - _rules.rule = pluginRules.rule; - plugin = pluginMgr.getPluginByRuleUrl(util.rule.getUrl(_rules.rule)); + req.reqId = ++index; + plugin = pluginMgr.resolvePluginRule(req); + pluginMgr.getTunnelRules(req, function(_rulesMgr) { + if (_rulesMgr) { + rulesMgr = _rulesMgr; + var pluginRules = rulesMgr.resolveRules(tunnelUrl); + var _disable = rulesMgr.resolveDisable(tunnelUrl); + if (pluginRules.rule) { + _rules.rule = pluginRules.rule; + plugin = pluginMgr.getPluginByRuleUrl(util.rule.getUrl(_rules.rule)); } - if (!disable.tunnel && _disable.tunnel) { - _rules.disable = pluginRules.disable; - return reqSocket.destroy(); + if (!disable.tunnel && _disable.tunnel) { + _rules.disable = pluginRules.disable; + return reqSocket.destroy(); } - if (pluginRules.host) { - _rules.host = pluginRules.host; - } - var _filter = rulesMgr.resolveFilter(tunnelUrl); - if ((!filter.rule && _filter.rule) || (!filter.pac && _filter.pac)) { - _rules.filter = pluginRules.filter; - filter.rule = true; + if (pluginRules.host) { + _rules.host = pluginRules.host; +} + var _filter = rulesMgr.resolveFilter(tunnelUrl); + if ((!filter.rule && _filter.rule) || (!filter.pac && _filter.pac)) { + _rules.filter = pluginRules.filter; + filter.rule = true; } - if (!_filter.pac && !filter.pac && pluginRules.pac) { - _rules.rule = pluginRules.pac; - } + if (!_filter.pac && !filter.pac && pluginRules.pac) { + _rules.rule = pluginRules.pac; +} } - rules.findProxyFromPac(req, function() { - var tunnelPort; - var proxyUrl = util.rule.getProxy(_rules.rule); - if (filter.rule) { - delete _rules.rule; - plugin = null; + rules.findProxyFromPac(req, function() { + var tunnelPort; + var proxyUrl = util.rule.getProxy(_rules.rule); + if (filter.rule) { + delete _rules.rule; + plugin = null; } else if(!proxyUrl && plugin) { - tunnelPort = plugin.ports && plugin.ports.tunnelPort; - if (!tunnelPort) { - return emitError(new Error('No plugin.tunnelServer')); + tunnelPort = plugin.ports && plugin.ports.tunnelPort; + if (!tunnelPort) { + return emitError(new Error('No plugin.tunnelServer')); } - proxyUrl = 'proxy://127.0.0.1:' + tunnelPort; + proxyUrl = 'proxy://127.0.0.1:' + tunnelPort; } - if (!tunnelPort) { - delete headers[pluginMgr.CLIENT_IP_HEADER]; - delete headers[pluginMgr.RULE_VALUE_HEADER]; - delete headers[pluginMgr.REQ_ID_HEADER]; - delete headers[pluginMgr.CUR_RULE_HEADER]; - delete headers[pluginMgr.LOCAL_HOST_HEADER]; - delete headers[pluginMgr.HOST_PORT_HEADER]; + if (!tunnelPort) { + delete headers[pluginMgr.CLIENT_IP_HEADER]; + delete headers[pluginMgr.RULE_VALUE_HEADER]; + delete headers[pluginMgr.REQ_ID_HEADER]; + delete headers[pluginMgr.CUR_RULE_HEADER]; + delete headers[pluginMgr.LOCAL_HOST_HEADER]; + delete headers[pluginMgr.HOST_PORT_HEADER]; } - if (proxyUrl) { - var isSocks = /^socks:\/\//.test(proxyUrl); - data.realUrl = proxyUrl; - var _url = 'https:' + util.removeProtocol(proxyUrl); - data.proxy = true; - resolveHost(_url, function(ip) { - options = parseUrl(_url, isSocks ? 1080 : 8888); - if (options.port == config.port && util.isLocalAddress(ip)) { - return emitError(new Error('Can not proxy to itself')); + if (proxyUrl) { + var isSocks = /^socks:\/\//.test(proxyUrl); + data.realUrl = proxyUrl; + var _url = 'https:' + util.removeProtocol(proxyUrl); + data.proxy = true; + resolveHost(_url, function(ip) { + options = parseUrl(_url, isSocks ? 1080 : 8888); + if (options.port == config.port && util.isLocalAddress(ip)) { + return emitError(new Error('Can not proxy to itself')); } - var opts = url.parse(tunnelUrl); - headers.host = opts.hostname + ':' + (opts.port || 443); - var onConnect = function(_proxySocket) { - proxySocket = _proxySocket; - abortIfUnavailable(proxySocket); - reqSocket.pipe(proxySocket).pipe(reqSocket); - sendEstablished(); + var opts = url.parse(tunnelUrl); + headers.host = opts.hostname + ':' + (opts.port || 443); + var onConnect = function(_proxySocket) { + proxySocket = _proxySocket; + abortIfUnavailable(proxySocket); + reqSocket.pipe(proxySocket).pipe(reqSocket); + sendEstablished(); }; - var dstOptions = url.parse(tunnelUrl); - dstOptions.proxyHost = ip; - dstOptions.proxyPort = parseInt(options.port, 10); - dstOptions.port = dstOptions.port || 443; - dstOptions.host = dstOptions.hostname; - dstOptions.headers = headers; - if (isSocks) { - dstOptions.proxyPort = options.port || 1080; - dstOptions.localDNS = false; - dstOptions.auths = config.getAuths(options); - socks.connect(dstOptions, onConnect).on('error', emitError); + var dstOptions = url.parse(tunnelUrl); + dstOptions.proxyHost = ip; + dstOptions.proxyPort = parseInt(options.port, 10); + dstOptions.port = dstOptions.port || 443; + dstOptions.host = dstOptions.hostname; + dstOptions.headers = headers; + if (isSocks) { + dstOptions.proxyPort = options.port || 1080; + dstOptions.localDNS = false; + dstOptions.auths = config.getAuths(options); + socks.connect(dstOptions, onConnect).on('error', emitError); } else { - dstOptions.proxyPort = options.port || 80; - dstOptions.proxyAuth = options.auth; - config.connect(dstOptions, onConnect).on('error', emitError); + dstOptions.proxyPort = options.port || 80; + dstOptions.proxyAuth = options.auth; + config.connect(dstOptions, onConnect).on('error', emitError); } }); } else { - tunnel(); + tunnel(); } }); }); - function tunnel() { - resolveHost(tunnelUrl, function(ip, port) { - resData.ip = port ? ip + ':' + port : ip; - resSocket = net.connect(port || options.port, ip, function() { - resSocket.pipe(reqSocket).pipe(resSocket); - sendEstablished(); + function tunnel() { + resolveHost(tunnelUrl, function(ip, port) { + resData.ip = port ? ip + ':' + port : ip; + resSocket = net.connect(port || options.port, ip, function() { + resSocket.pipe(reqSocket).pipe(resSocket); + sendEstablished(); }); - abortIfUnavailable(resSocket); + abortIfUnavailable(resSocket); }); } - function parseUrl(_url, port) { - _url = _url || tunnelUrl; - options = req.options = url.parse(_url); - options.port = options.port || port || 443; - return options; + function parseUrl(_url, port) { + _url = _url || tunnelUrl; + options = req.options = url.parse(_url); + options.port = options.port || port || 443; + return options; } - function resolveHost(url, callback) { - rules.resolveHost(url, function(err, ip, port, host) { - if (host) { - _rules.host = host; + function resolveHost(url, callback) { + rules.resolveHost(url, function(err, ip, port, host) { + if (host) { + _rules.host = host; } - data.requestTime = data.dnsTime = Date.now(); - resData.ip = ip || LOCALHOST; - reqEmitter.emit('send', data); - err ? emitError(err) : callback(ip, port); + data.requestTime = data.dnsTime = Date.now(); + resData.ip = ip || LOCALHOST; + reqEmitter.emit('send', data); + err ? emitError(err) : callback(ip, port); }, rulesMgr); } - function abortIfUnavailable(socket) { - socket.on('error', emitError).on('close', emitError); + function abortIfUnavailable(socket) { + socket.on('error', emitError).on('close', emitError); } - function sendEstablished() { - reqSocket.write('HTTP/1.1 200 Connection Established\r\nProxy-Agent: ' + config.name + '\r\n\r\n'); - responsed = true; - if (reqEmitter) { - data.responseTime = data.endTime = Date.now(); - resData.statusCode = 200; - reqEmitter.emit('response', data); - reqEmitter.emit('end', data); + function sendEstablished() { + reqSocket.write('HTTP/1.1 200 Connection Established\r\nProxy-Agent: ' + config.name + '\r\n\r\n'); + responsed = true; + if (reqEmitter) { + data.responseTime = data.endTime = Date.now(); + resData.statusCode = 200; + reqEmitter.emit('response', data); + reqEmitter.emit('end', data); } - return reqSocket; + return reqSocket; } - function emitError(err) { - if (responsed) { - return; + function emitError(err) { + if (responsed) { + return; } - responsed = true; - resSocket && resSocket.destroy(); - proxySocket && proxySocket.destroy(); - reqSocket.destroy(); - data.responseTime = data.endTime = Date.now(); + responsed = true; + resSocket && resSocket.destroy(); + proxySocket && proxySocket.destroy(); + reqSocket.destroy(); + data.responseTime = data.endTime = Date.now(); - if (!resData.ip) { - resData.ip = LOCALHOST; + if (!resData.ip) { + resData.ip = LOCALHOST; } - if (err) { - err = new Error('Aborted'); - data.reqError = true; - resData.statusCode ='aborted'; - reqData.body = util.getErrorStack(err); - reqEmitter.emit('abort', data); + if (err) { + err = new Error('Aborted'); + data.reqError = true; + resData.statusCode ='aborted'; + reqData.body = util.getErrorStack(err); + reqEmitter.emit('abort', data); } else { - data.resError = true; - resData.statusCode = resData.statusCode || 502; - resData.body = util.getErrorStack(err); - util.emitError(reqEmitter, data); + data.resError = true; + resData.statusCode = resData.statusCode || 502; + resData.body = util.getErrorStack(err); + util.emitError(reqEmitter, data); } } - }); +}); - return server; + return server; } function proxy(callback) { - var app = express(); - var server = app.listen(config.port, callback); - var proxyEvents = new EventEmitter(); - var middlewares = ['./init', + var app = express(); + var server = app.listen(config.port, callback); + var proxyEvents = new EventEmitter(); + var middlewares = ['./init', '../biz'] .concat(require('./inspectors')) .concat(config.middlewares) .concat(require('./handlers')); - proxyEvents.config = config; - app.logger = logger; - middlewares.forEach(function(mw) { - mw && app.use((typeof mw == 'string' ? require(mw) : mw).bind(proxyEvents)); + proxyEvents.config = config; + app.logger = logger; + middlewares.forEach(function(mw) { + mw && app.use((typeof mw == 'string' ? require(mw) : mw).bind(proxyEvents)); }); - exportInterfaces(proxyEvents); - tunnelProxy(server, proxyEvents); - initDataServer(proxyEvents); - initLogServer(proxyEvents); - require('../biz/init')(proxyEvents); - config.debug && rules.disableDnsCache(); - return proxyEvents; + exportInterfaces(proxyEvents); + tunnelProxy(server, proxyEvents); + initDataServer(proxyEvents); + initLogServer(proxyEvents); + require('../biz/init')(proxyEvents); + config.debug && rules.disableDnsCache(); + return proxyEvents; } function exportInterfaces(obj) { - obj.rules = rules; - obj.util = util; - obj.rulesUtil = rulesUtil; - obj.httpsUtil = httpsUtil; - obj.pluginMgr = pluginMgr; - obj.logger = logger; - return obj; + obj.rules = rules; + obj.util = util; + obj.rulesUtil = rulesUtil; + obj.httpsUtil = httpsUtil; + obj.pluginMgr = pluginMgr; + obj.logger = logger; + return obj; } process.on('uncaughtException', function(err){ - var stack = util.getErrorStack(err); - fs.writeFileSync(path.join(process.cwd(), config.name + '.log'), '\r\n' + stack + '\r\n', {flag: 'a'}); - console.error(stack); - process.exit(1); + var stack = util.getErrorStack(err); + fs.writeFileSync(path.join(process.cwd(), config.name + '.log'), '\r\n' + stack + '\r\n', {flag: 'a'}); + console.error(stack); + process.exit(1); }); module.exports = exportInterfaces(proxy); \ No newline at end of file diff --git a/lib/init.js b/lib/init.js index e9a241745..c8274f437 100644 --- a/lib/init.js +++ b/lib/init.js @@ -3,123 +3,123 @@ var util = require('./util'); var config = require('./config'); function addErrorEvents(req, res) { - var clientReq; - req.on('dest', function(_req) { - clientReq = _req.on('error', util.noop); + var clientReq; + req.on('dest', function(_req) { + clientReq = _req.on('error', util.noop); }).on('error', abort) .on('close', abort); - res.on('src', function(_res) { - _res.on('error', abort); + res.on('src', function(_res) { + _res.on('error', abort); }).on('error', abort); - function abort(err) { - if (clientReq) { - if (clientReq.abort) { - clientReq.abort(); + function abort(err) { + if (clientReq) { + if (clientReq.abort) { + clientReq.abort(); } else if (clientReq.destroy) { - clientReq.destroy(); + clientReq.destroy(); } } - res.destroy(); + res.destroy(); } } function addTransforms(req, res) { - var reqTextPipeStream, resZipPipeStream, resIconvPipeStream, svrRes; + var reqTextPipeStream, resZipPipeStream, resIconvPipeStream, svrRes; - req.addTextTransform = function(transform) { - if (!reqTextPipeStream) { - reqTextPipeStream = util.getPipeIconvStream(req.headers, true); - delete req.headers['content-length']; - req.add(reqTextPipeStream); + req.addTextTransform = function(transform) { + if (!reqTextPipeStream) { + reqTextPipeStream = util.getPipeIconvStream(req.headers, true); + delete req.headers['content-length']; + req.add(reqTextPipeStream); } - reqTextPipeStream.add(transform); - return req; + reqTextPipeStream.add(transform); + return req; }; - function initZipTransform() { - if (!resZipPipeStream) { - resZipPipeStream = new PipeStream(); - removeContentLength(); - res.add(function(src, next) { - var pipeZipStream = util.getPipeZipStream(res.headers); - pipeZipStream.addHead(resZipPipeStream); - if (resIconvPipeStream) { - var pipeIconvStream = util.getPipeIconvStream(res.headers); - pipeIconvStream.add(resIconvPipeStream); - pipeZipStream.add(pipeIconvStream); + function initZipTransform() { + if (!resZipPipeStream) { + resZipPipeStream = new PipeStream(); + removeContentLength(); + res.add(function(src, next) { + var pipeZipStream = util.getPipeZipStream(res.headers); + pipeZipStream.addHead(resZipPipeStream); + if (resIconvPipeStream) { + var pipeIconvStream = util.getPipeIconvStream(res.headers); + pipeIconvStream.add(resIconvPipeStream); + pipeZipStream.add(pipeIconvStream); } - next(src.pipe(pipeZipStream)); + next(src.pipe(pipeZipStream)); }); } - return resZipPipeStream; + return resZipPipeStream; } - res.addZipTransform = function(transform, head, tail) { - initZipTransform()[head ? 'addHead' : (tail ? 'addTail' : 'add')](transform); - return res; + res.addZipTransform = function(transform, head, tail) { + initZipTransform()[head ? 'addHead' : (tail ? 'addTail' : 'add')](transform); + return res; }; - res.addTextTransform = function(transform, head, tail) { - if (!resIconvPipeStream) { - initZipTransform(); - resIconvPipeStream = new PipeStream(); + res.addTextTransform = function(transform, head, tail) { + if (!resIconvPipeStream) { + initZipTransform(); + resIconvPipeStream = new PipeStream(); } - resIconvPipeStream[head ? 'addHead' : (tail ? 'addTail' : 'add')](transform); - return res; + resIconvPipeStream[head ? 'addHead' : (tail ? 'addTail' : 'add')](transform); + return res; }; - res.on('src', function(_res) { - svrRes = _res; - removeContentLength(); + res.on('src', function(_res) { + svrRes = _res; + removeContentLength(); }); - function removeContentLength() { - if (svrRes && (resZipPipeStream || resIconvPipeStream)) { - delete svrRes.headers['content-length']; + function removeContentLength() { + if (svrRes && (resZipPipeStream || resIconvPipeStream)) { + delete svrRes.headers['content-length']; } } } module.exports = function(req, res, next) { - PipeStream.wrapSrc(req); - PipeStream.wrapDest(res); - addTransforms(req, res); - addErrorEvents(req, res); - var socket = req.socket || {}; - socket[config.CLIENT_IP_HEAD] = req.clientIp + PipeStream.wrapSrc(req); + PipeStream.wrapDest(res); + addTransforms(req, res); + addErrorEvents(req, res); + var socket = req.socket || {}; + socket[config.CLIENT_IP_HEAD] = req.clientIp = socket[config.CLIENT_IP_HEAD] || util.getClientIp(req) || '127.0.0.1'; - delete req.headers[config.CLIENT_IP_HEAD]; - if (req.headers[config.HTTPS_FIELD] || req.socket.isHttps) {//防止socket长连接导致新请求的头部无法加util.HTTPS_FIELD - req.socket.isHttps = true; - req.isHttps = true; - delete req.headers[config.HTTPS_FIELD]; + delete req.headers[config.CLIENT_IP_HEAD]; + if (req.headers[config.HTTPS_FIELD] || req.socket.isHttps) {//防止socket长连接导致新请求的头部无法加util.HTTPS_FIELD + req.socket.isHttps = true; + req.isHttps = true; + delete req.headers[config.HTTPS_FIELD]; } - var responsed; - res.response = function(_res) { - if (responsed) { - return; + var responsed; + res.response = function(_res) { + if (responsed) { + return; } - responsed = true; - if (_res.realUrl) { - req.realUrl = res.realUrl = _res.realUrl; + responsed = true; + if (_res.realUrl) { + req.realUrl = res.realUrl = _res.realUrl; } - res.headers = _res.headers; - res.trailers = _res.trailers; - res.statusCode = _res.statusCode = util.getStatusCode(_res.statusCode); + res.headers = _res.headers; + res.trailers = _res.trailers; + res.statusCode = _res.statusCode = util.getStatusCode(_res.statusCode); - util.drain(req, function() { - if (util.getStatusCode(_res.statusCode)) { - res.writeHead(_res.statusCode, _res.headers); - res.src(_res); - _res.trailers && res.addTrailers(_res.trailers); + util.drain(req, function() { + if (util.getStatusCode(_res.statusCode)) { + res.writeHead(_res.statusCode, _res.headers); + res.src(_res); + _res.trailers && res.addTrailers(_res.trailers); } else { - util.sendStatusCodeError(res, _res); + util.sendStatusCodeError(res, _res); } }); }; - next(); + next(); }; \ No newline at end of file diff --git a/lib/inspectors/data.js b/lib/inspectors/data.js index ed1212719..8cf90b26f 100644 --- a/lib/inspectors/data.js +++ b/lib/inspectors/data.js @@ -13,270 +13,270 @@ var pluginMgr = require('../plugins'); var index = 0; function passThrough(chunk, encoding, callback) { - callback(null, chunk); + callback(null, chunk); } function unzipBody(encoding, body, callback) { - var unzip; - switch (body && util.toLowerCase(encoding)) { + var unzip; + switch (body && util.toLowerCase(encoding)) { case 'gzip': - unzip = zlib.gunzip.bind(zlib); - break; + unzip = zlib.gunzip.bind(zlib); + break; case 'deflate': - unzip = zlib.inflate.bind(zlib); - break; + unzip = zlib.inflate.bind(zlib); + break; } - unzip ? unzip(body, function(err, data) { - err ? zlib.inflateRaw(body, callback) : callback(null, data); + unzip ? unzip(body, function(err, data) { + err ? zlib.inflateRaw(body, callback) : callback(null, data); }) : callback(null, body); } function emitDataEvents(req, res, proxy) { - var now = Date.now(); - var dataId = req.dataId = now + '-' + ++index; - var exportsFile = util.getMatcherValue(req.rules.exports); - var plugin = req.pluginMgr; - var statusPort = plugin && plugin.ports && plugin.ports.statusPort; - var showHttpData = !req.filter.hide && EventEmitter.listenerCount(proxy, 'request') || statusPort; - if (!exportsFile && !showHttpData && !statusPort) { - return; + var now = Date.now(); + var dataId = req.dataId = now + '-' + ++index; + var exportsFile = util.getMatcherValue(req.rules.exports); + var plugin = req.pluginMgr; + var statusPort = plugin && plugin.ports && plugin.ports.statusPort; + var showHttpData = !req.filter.hide && EventEmitter.listenerCount(proxy, 'request') || statusPort; + if (!exportsFile && !showHttpData && !statusPort) { + return; } - var _res = {}; - var reqEmitter = new EventEmitter(); - var request = new Transform(); - var response = new Transform(); - var reqData = { - method: util.toUpperCase(req.method) || 'GET', - httpVersion: req.httpVersion || '1.1', - ip: req.clientIp, - isWhistleHttps: req.isWhistleHttps, - headers: req.headers, - trailers: req.trailers + var _res = {}; + var reqEmitter = new EventEmitter(); + var request = new Transform(); + var response = new Transform(); + var reqData = { + method: util.toUpperCase(req.method) || 'GET', + httpVersion: req.httpVersion || '1.1', + ip: req.clientIp, + isWhistleHttps: req.isWhistleHttps, + headers: req.headers, + trailers: req.trailers }; - var resData = {}; - var data = request.data = { - startTime: now, - id: dataId, - url: req.fullUrl, - req: reqData, - res: resData, - rules: req.rules, - reqId: req.reqId + var resData = {}; + var data = request.data = { + startTime: now, + id: dataId, + url: req.fullUrl, + req: reqData, + res: resData, + rules: req.rules, + reqId: req.reqId }; - req.once('dest', function() { - setReqStatus(); - reqEmitter.emit('send', data); + req.once('dest', function() { + setReqStatus(); + reqEmitter.emit('send', data); }); - res.once('src', function(res) { - _res = res; - if (data.endTime) { - return; + res.once('src', function(res) { + _res = res; + if (data.endTime) { + return; } - receiveResBody(); - setResStatus(); - reqEmitter.emit('response', data); + receiveResBody(); + setResStatus(); + reqEmitter.emit('response', data); }); - req.once('close', handleError); - req.once('error', handleError); - res.once('error', handleError); - req.append(request); - res.append(response); + req.once('close', handleError); + req.once('error', handleError); + res.once('error', handleError); + req.append(request); + res.append(response); - reqEmitter.data = data; - proxy.emit('request', reqEmitter); + reqEmitter.data = data; + proxy.emit('request', reqEmitter); - var reqBody = false; - var reqSize = 0; + var reqBody = false; + var reqSize = 0; - if (util.hasRequestBody(req)) { - reqBody = showHttpData ? null : ''; + if (util.hasRequestBody(req)) { + reqBody = showHttpData ? null : ''; } - request._transform = function(chunk, encoding, callback) { + request._transform = function(chunk, encoding, callback) { - if (chunk) { - if (reqBody || reqBody === null) { - reqBody = reqBody ? Buffer.concat([reqBody, chunk]) : chunk; - if (reqBody.length > MAX_REQ_SIZE) { - reqBody = false; + if (chunk) { + if (reqBody || reqBody === null) { + reqBody = reqBody ? Buffer.concat([reqBody, chunk]) : chunk; + if (reqBody.length > MAX_REQ_SIZE) { + reqBody = false; } } - reqSize += chunk.length; + reqSize += chunk.length; } else { - data.requestTime = Date.now(); - reqData.size = reqSize; - reqData.body = util.decodeBuffer(reqBody); - data.status = 'requestEnd'; - pluginMgr.postStatus(plugin, data); + data.requestTime = Date.now(); + reqData.size = reqSize; + reqData.body = util.decodeBuffer(reqBody); + data.status = 'requestEnd'; + pluginMgr.postStatus(plugin, data); } - callback(null, chunk); + callback(null, chunk); }; - function receiveResBody() { - var resBody = false; - var resSize = 0; - var contentType = util.getContentType(_res.headers); - if (!_res.headers['content-type'] || (contentType && contentType != 'IMG' && util.hasBody(_res))) { - resBody = showHttpData ? null : ''; + function receiveResBody() { + var resBody = false; + var resSize = 0; + var contentType = util.getContentType(_res.headers); + if (!_res.headers['content-type'] || (contentType && contentType != 'IMG' && util.hasBody(_res))) { + resBody = showHttpData ? null : ''; } - response._transform = function(chunk, encoding, callback) { - if (chunk) { - if (resBody || resBody === null) { - resBody = resBody ? Buffer.concat([resBody, chunk]) : chunk; - if (resBody.length > MAX_RES_SIZE) { - resBody = false; + response._transform = function(chunk, encoding, callback) { + if (chunk) { + if (resBody || resBody === null) { + resBody = resBody ? Buffer.concat([resBody, chunk]) : chunk; + if (resBody.length > MAX_RES_SIZE) { + resBody = false; } } - resSize += chunk.length; - callback(null, chunk); + resSize += chunk.length; + callback(null, chunk); } else { - unzipBody(util.toLowerCase(_res.headers['content-encoding']), resBody, + unzipBody(util.toLowerCase(_res.headers['content-encoding']), resBody, function(err, body) { - resData.body = err ? util.getErrorStack(err) : util.decodeBuffer(body); - data.endTime = Date.now(); - resData.size = resSize; - reqEmitter.emit('end', data); - callback(null, chunk); - writeExportsFile(); - data.status = 'responseEnd'; - pluginMgr.postStatus(plugin, data); + resData.body = err ? util.getErrorStack(err) : util.decodeBuffer(body); + data.endTime = Date.now(); + resData.size = resSize; + reqEmitter.emit('end', data); + callback(null, chunk); + writeExportsFile(); + data.status = 'responseEnd'; + pluginMgr.postStatus(plugin, data); }); } }; } - function handleError(err) { - if ((!err || !err._resError) && (data.endTime || (data.responseTime && !err))) {//connection: close的时候,还要数据缓存 - return; + function handleError(err) { + if ((!err || !err._resError) && (data.endTime || (data.responseTime && !err))) {//connection: close的时候,还要数据缓存 + return; } - request._transform = passThrough; - response._transform = passThrough; - data.endTime = Date.now(); - if (err) { - data.resError = true; - resData.body = util.getErrorStack(err); - util.emitError(reqEmitter, data); - setResStatus(502); - data.status = 'error'; - pluginMgr.postStatus(plugin, data); + request._transform = passThrough; + response._transform = passThrough; + data.endTime = Date.now(); + if (err) { + data.resError = true; + resData.body = util.getErrorStack(err); + util.emitError(reqEmitter, data); + setResStatus(502); + data.status = 'error'; + pluginMgr.postStatus(plugin, data); } else { - data.reqError = true; - reqData.body = 'aborted'; - reqEmitter.emit('abort', data); - setResStatus('aborted'); - data.status = 'aborted'; - pluginMgr.postStatus(plugin, data); + data.reqError = true; + reqData.body = 'aborted'; + reqEmitter.emit('abort', data); + setResStatus('aborted'); + data.status = 'aborted'; + pluginMgr.postStatus(plugin, data); } - writeExportsFile(); + writeExportsFile(); } - function setReqStatus(defaultHost) { - data.dnsTime = (req.dnsTime || 0) + now; - data.realUrl = req.realUrl; - resData.ip = req.hostIp || defaultHost; + function setReqStatus(defaultHost) { + data.dnsTime = (req.dnsTime || 0) + now; + data.realUrl = req.realUrl; + resData.ip = req.hostIp || defaultHost; } - function setResStatus(defaultCode) { - setReqStatus(LOCALHOST); - resData.statusCode = _res.statusCode || defaultCode || 502; - resData.statusMessage = _res.statusMessage; - if (!data.requestTime) { - data.requestTime = Date.now(); + function setResStatus(defaultCode) { + setReqStatus(LOCALHOST); + resData.statusCode = _res.statusCode || defaultCode || 502; + resData.statusMessage = _res.statusMessage; + if (!data.requestTime) { + data.requestTime = Date.now(); } - data.responseTime = Date.now(); - resData.headers = _res.headers; - resData.trailers = _res.trailers; + data.responseTime = Date.now(); + resData.headers = _res.headers; + resData.trailers = _res.trailers; } - function writeExportsFile() { - if (!exportsFile) { - return; + function writeExportsFile() { + if (!exportsFile) { + return; } - exportsFile = util.join(req.rules.exports.root, exportsFile); - fse.ensureFile(exportsFile, function(err) { - if (err) { - return; + exportsFile = util.join(req.rules.exports.root, exportsFile); + fse.ensureFile(exportsFile, function(err) { + if (err) { + return; } - fs.writeFile(exportsFile, '\r\n' + JSON.stringify({ - reqId: req.reqId, - startTime: data.startTime, - dnsTime: data.dnsTime, - requestTime: data.requestTime, - responseTime: data.responseTime, - endTime: data.endTime, - url: data.url, - realUrl: data.url == data.realUrl ? undefined : data.realUrl, - method: reqData.method, - httpVersion: reqData.httpVersion, - clientIp: reqData.ip, - reqError: data.reqError, - reqSize: reqData.size, - reqHeaders: reqData.headers, - reqTrailers: reqData.trailers, - statusCode: resData.statusCode, - hostIp: resData.ip, - resError: data.resError, - resSize: resData.size, - resHeaders: resData.headers, - resTrailers: resData.trailers, - rules: req.rules + fs.writeFile(exportsFile, '\r\n' + JSON.stringify({ + reqId: req.reqId, + startTime: data.startTime, + dnsTime: data.dnsTime, + requestTime: data.requestTime, + responseTime: data.responseTime, + endTime: data.endTime, + url: data.url, + realUrl: data.url == data.realUrl ? undefined : data.realUrl, + method: reqData.method, + httpVersion: reqData.httpVersion, + clientIp: reqData.ip, + reqError: data.reqError, + reqSize: reqData.size, + reqHeaders: reqData.headers, + reqTrailers: reqData.trailers, + statusCode: resData.statusCode, + hostIp: resData.ip, + resError: data.resError, + resSize: resData.size, + resHeaders: resData.headers, + resTrailers: resData.trailers, + rules: req.rules }), {flag: 'a'}, util.noop); }); } } function addTimeout(req, res, timeout, custom) { - if (!(timeout > 0) || req.disable.timeout) { - return; + if (!(timeout > 0) || req.disable.timeout) { + return; } - if (!custom && util.isMultipart(req)) { - timeout *= 2; + if (!custom && util.isMultipart(req)) { + timeout *= 2; } - var timeoutId, responsed; - var preReq = new Transform(); - var endReq = new Transform(); - var preRes = new Transform(); - var endRes = new Transform(); + var timeoutId, responsed; + var preReq = new Transform(); + var endReq = new Transform(); + var preRes = new Transform(); + var endRes = new Transform(); - preReq._transform = preRes._transform = function(chunk, encoding, callback) { - timeoutId && clearTimeout(timeoutId); - timeoutId = null; - callback(null, chunk); + preReq._transform = preRes._transform = function(chunk, encoding, callback) { + timeoutId && clearTimeout(timeoutId); + timeoutId = null; + callback(null, chunk); }; - endReq._transform = endRes._transform = function(chunk, encoding, callback) { - timeoutId && clearTimeout(timeoutId); - if (!responsed || chunk) { - timeoutId = setTimeout(emitTimeoutError, timeout); + endReq._transform = endRes._transform = function(chunk, encoding, callback) { + timeoutId && clearTimeout(timeoutId); + if (!responsed || chunk) { + timeoutId = setTimeout(emitTimeoutError, timeout); } - if (!chunk) { - responsed = true; + if (!chunk) { + responsed = true; } - callback(null, chunk); + callback(null, chunk); }; - function emitTimeoutError() { - util.emitError(responsed ? res : req, new Error('Timeout')); + function emitTimeoutError() { + util.emitError(responsed ? res : req, new Error('Timeout')); } - req.prepend(preReq).append(endReq); - res.prepend(preRes).append(endRes); + req.prepend(preReq).append(endReq); + res.prepend(preRes).append(endRes); } module.exports = function(req, res, next) { - emitDataEvents(req, res, this); - addTimeout(req, res, req.timeout || this.config.timeout, req.timeout); - next(); + emitDataEvents(req, res, this); + addTimeout(req, res, req.timeout || this.config.timeout, req.timeout); + next(); }; diff --git a/lib/inspectors/head.js b/lib/inspectors/head.js index 65bdf29b8..885e3a8d8 100644 --- a/lib/inspectors/head.js +++ b/lib/inspectors/head.js @@ -5,28 +5,28 @@ var util = require('../util'); * @deprecated */ module.exports = function(req, res, next) { - util.parseRuleJson(req.rules.head, function (data) { - if (data) { - var reqRule = req.rules.head.req = {}; - if (data.req) { - reqRule.headers = data.req; + util.parseRuleJson(req.rules.head, function (data) { + if (data) { + var reqRule = req.rules.head.req = {}; + if (data.req) { + reqRule.headers = data.req; } - var resRule = req.rules.head.res = {}; - if (data.statusCode) { - resRule.statusCode = data.statusCode; + var resRule = req.rules.head.res = {}; + if (data.statusCode) { + resRule.statusCode = data.statusCode; } - if (data.body) { - resRule.body = data.body; + if (data.body) { + resRule.body = data.body; } - if (data.res) { - resRule.headers = data.res; + if (data.res) { + resRule.headers = data.res; } } - next(); + next(); }); }; \ No newline at end of file diff --git a/lib/inspectors/https.js b/lib/inspectors/https.js index 0ff1991d5..44241eba9 100644 --- a/lib/inspectors/https.js +++ b/lib/inspectors/https.js @@ -7,59 +7,59 @@ var HTTPS_RE = /https:(\/\/|\\\/\\\/)/ig; var RESET_COOKIE_RE = /secure;?|domain=([^;]*);?/ig; function getTransform() { - var transform = new Transform(); - var rest = ''; - transform._transform = function(chunk, encoding, callback) { - if (chunk != null) { - rest = chunk = (rest + chunk).replace(HTTPS_RE, 'http:$1' + HTTPS_FLAG); - var len = chunk.length - 7; - if (len > 0) { - rest = chunk.substring(len); - chunk = chunk.substring(0, len); + var transform = new Transform(); + var rest = ''; + transform._transform = function(chunk, encoding, callback) { + if (chunk != null) { + rest = chunk = (rest + chunk).replace(HTTPS_RE, 'http:$1' + HTTPS_FLAG); + var len = chunk.length - 7; + if (len > 0) { + rest = chunk.substring(len); + chunk = chunk.substring(0, len); } else { - chunk = null; + chunk = null; } } else { - chunk = rest || null; + chunk = rest || null; } - callback(null, chunk); + callback(null, chunk); }; - return transform; + return transform; } module.exports = function(req, res, next) { - if (!req.isHttps) { - var host = req.headers.host; - var isHttps = host && host.indexOf(HTTPS_FLAG) == 0 && host.indexOf('.', HTTPS_FLAG_LEN) != -1; - if (isHttps) { - host = req.headers.host = host.substring(HTTPS_FLAG_LEN); - req.isHttps = req.isWhistleHttps = true; - var referer = req.headers.referer; - if (referer) { - req.headers.referer = referer.replace('http://' + HTTPS_FLAG, 'https://'); + if (!req.isHttps) { + var host = req.headers.host; + var isHttps = host && host.indexOf(HTTPS_FLAG) == 0 && host.indexOf('.', HTTPS_FLAG_LEN) != -1; + if (isHttps) { + host = req.headers.host = host.substring(HTTPS_FLAG_LEN); + req.isHttps = req.isWhistleHttps = true; + var referer = req.headers.referer; + if (referer) { + req.headers.referer = referer.replace('http://' + HTTPS_FLAG, 'https://'); } - res.on('src', function(_res) { - var headers = _res.headers; - if (/^https:\/\//i.test(headers.location)) { - headers.location = 'http:' + HTTPS_FLAG + util.removeProtocol(headers.location, true); + res.on('src', function(_res) { + var headers = _res.headers; + if (/^https:\/\//i.test(headers.location)) { + headers.location = 'http:' + HTTPS_FLAG + util.removeProtocol(headers.location, true); } - var cookies = headers['set-cookie']; - if (Array.isArray(cookies)) { - host = host.split(':')[0].split('.'); - host = '.' + host.slice(host.length - 2).join('.'); - headers['set-cookie'] = cookies.map(function(cookie) { - return cookie.replace(RESET_COOKIE_RE, '') + '; DOMAIN=' + host + ';'; + var cookies = headers['set-cookie']; + if (Array.isArray(cookies)) { + host = host.split(':')[0].split('.'); + host = '.' + host.slice(host.length - 2).join('.'); + headers['set-cookie'] = cookies.map(function(cookie) { + return cookie.replace(RESET_COOKIE_RE, '') + '; DOMAIN=' + host + ';'; }); } - if (util.supportHtmlTransform(_res)) { - res.addTextTransform(getTransform(), true); + if (util.supportHtmlTransform(_res)) { + res.addTextTransform(getTransform(), true); } }); } } - next(); + next(); }; \ No newline at end of file diff --git a/lib/inspectors/index.js b/lib/inspectors/index.js index 5ee1a378d..52c57bc2d 100644 --- a/lib/inspectors/index.js +++ b/lib/inspectors/index.js @@ -6,5 +6,5 @@ module.exports = ['./https', './req', './data', './res'].map(function(mod) { - return require(mod); - }); \ No newline at end of file + return require(mod); +}); \ No newline at end of file diff --git a/lib/inspectors/log.js b/lib/inspectors/log.js index 232c68793..86391b38d 100644 --- a/lib/inspectors/log.js +++ b/lib/inspectors/log.js @@ -9,63 +9,63 @@ var logHtmlScript, logHttpsHtmlScript, logHttpsScript; function wrapScript(script, isHtml) { - return isHtml ? '\r\n\r\n' : '\r\n' + script + '\r\n'; + return isHtml ? '\r\n\r\n' : '\r\n' + script + '\r\n'; } module.exports = function(req, res, next) { - if (req.rules.log) { - if (!logHtmlScript) { - var logCgi = '//' + this.config.localUIHost + '/cgi-bin/log/set'; - logHttpsScript = logScript.replace('$LOG_CGI', 'https:' + logCgi); - logScript = logScript.replace('$LOG_CGI', 'http:' + logCgi); - logHttpsHtmlScript = '\r\n\r\n'; - logHtmlScript = '\r\n\r\n'; + if (req.rules.log) { + if (!logHtmlScript) { + var logCgi = '//' + this.config.localUIHost + '/cgi-bin/log/set'; + logHttpsScript = logScript.replace('$LOG_CGI', 'https:' + logCgi); + logScript = logScript.replace('$LOG_CGI', 'http:' + logCgi); + logHttpsHtmlScript = '\r\n\r\n'; + logHtmlScript = '\r\n\r\n'; } - util.disableReqCache(req.headers); - res.on('src', function(_res) { - var topScript, isHtml; - if (util.supportHtmlTransform(_res)) { - isHtml = true; - topScript = req.isHttps ? logHttpsHtmlScript : logHtmlScript; + util.disableReqCache(req.headers); + res.on('src', function(_res) { + var topScript, isHtml; + if (util.supportHtmlTransform(_res)) { + isHtml = true; + topScript = req.isHttps ? logHttpsHtmlScript : logHtmlScript; } else if (util.getContentType(_res.headers) == 'JS') { - topScript = req.isHttps ? logHttpsScript : logScript; + topScript = req.isHttps ? logHttpsScript : logScript; } - if (topScript) { - delete _res.headers['content-security-policy']; - delete _res.headers['content-security-policy-report-only']; - if (!isHtml) { - _res.headers['access-control-allow-origin'] = '*'; + if (topScript) { + delete _res.headers['content-security-policy']; + delete _res.headers['content-security-policy-report-only']; + if (!isHtml) { + _res.headers['access-control-allow-origin'] = '*'; } - topScript = new Buffer(topScript); - var userScript; - var transform = new Transform(); - var added; - transform._transform = function(chunk, encoding, callback) { - if (!added) { - added = true; - util.getRuleValue(req.rules.log, function(script) { - var buf = [topScript]; - if (userScript = script || null) { - userScript = new Buffer(wrapScript(userScript, isHtml)); - if (isHtml || !chunk) { - buf.push(userScript); - userScript = null; + topScript = new Buffer(topScript); + var userScript; + var transform = new Transform(); + var added; + transform._transform = function(chunk, encoding, callback) { + if (!added) { + added = true; + util.getRuleValue(req.rules.log, function(script) { + var buf = [topScript]; + if (userScript = script || null) { + userScript = new Buffer(wrapScript(userScript, isHtml)); + if (isHtml || !chunk) { + buf.push(userScript); + userScript = null; } } - chunk && buf.push(chunk); - callback(null, Buffer.concat(buf)); + chunk && buf.push(chunk); + callback(null, Buffer.concat(buf)); }); } else { - callback(null, chunk || userScript); + callback(null, chunk || userScript); } }; - res.addZipTransform(transform, false, true); + res.addZipTransform(transform, false, true); } }); } - next(); + next(); }; \ No newline at end of file diff --git a/lib/inspectors/req.js b/lib/inspectors/req.js index 52829ce26..298a4e944 100644 --- a/lib/inspectors/req.js +++ b/lib/inspectors/req.js @@ -11,14 +11,14 @@ var FileWriterTransform = util.FileWriterTransform; var MultiPartParser = util.MultiPartParser; var MAX_REQ_SIZE = 256 * 1024; var REQ_TYPE = { - urlencoded: 'application/x-www-form-urlencoded', - form: 'application/x-www-form-urlencoded', - json: 'application/json', - xml: 'text/xml', - text: 'text/plain', - upload: 'multipart/form-data', - multipart: 'multipart/form-data', - defaultType: 'application/octet-stream' + urlencoded: 'application/x-www-form-urlencoded', + form: 'application/x-www-form-urlencoded', + json: 'application/json', + xml: 'text/xml', + text: 'text/plain', + upload: 'multipart/form-data', + multipart: 'multipart/form-data', + defaultType: 'application/octet-stream' }; /** @@ -28,416 +28,416 @@ var REQ_TYPE = { * @param data */ function handleReq(req, data) { - req.method = data.method || req.method; - req.timeout = parseInt(data.timeout, 10); - extend(req.headers, data.headers); - if (typeof data.charset == 'string') { - var type = req.headers['content-type']; - var charset = '; charset=' + data.charset; - if (typeof type == 'string') { - req.headers['content-type'] = type.split(';')[0] + charset; + req.method = data.method || req.method; + req.timeout = parseInt(data.timeout, 10); + extend(req.headers, data.headers); + if (typeof data.charset == 'string') { + var type = req.headers['content-type']; + var charset = '; charset=' + data.charset; + if (typeof type == 'string') { + req.headers['content-type'] = type.split(';')[0] + charset; } else { - req.headers['content-type'] = charset; + req.headers['content-type'] = charset; } } else { - delete data.charset; + delete data.charset; } - var method = req.method = typeof req.method != 'string' ? 'GET' : req.method.toUpperCase(); - if (!util.hasRequestBody(method)) { - delete data.top; - delete data.bottom; - delete data.body; + var method = req.method = typeof req.method != 'string' ? 'GET' : req.method.toUpperCase(); + if (!util.hasRequestBody(method)) { + delete data.top; + delete data.bottom; + delete data.body; } else if (data.top || data.bottom || data.body) { - delete req.headers['content-length']; + delete req.headers['content-length']; } - !util.isEmptyObject(data) && req.add(new WhistleTransform(data)); + !util.isEmptyObject(data) && req.add(new WhistleTransform(data)); } function handleCors(data, cors) { - if (!cors) { - return; + if (!cors) { + return; } - if (cors.origin !== undefined) { - util.setHeader(data, 'origin', cors.origin); + if (cors.origin !== undefined) { + util.setHeader(data, 'origin', cors.origin); } - if (cors.method !== undefined) { - util.setHeader(data, 'access-control-request-method', cors.method); + if (cors.method !== undefined) { + util.setHeader(data, 'access-control-request-method', cors.method); } - if (cors.headers !== undefined) { - util.setHeader(data, 'access-control-request-headers', cors.headers); + if (cors.headers !== undefined) { + util.setHeader(data, 'access-control-request-headers', cors.headers); } } function handleAuth(data, auth) { - if (!auth) { - return; + if (!auth) { + return; } - var basic = []; - auth.username != null && basic.push(auth.username); - auth.password != null && basic.push(auth.password); - if (basic = basic.join(':')) { - util.setHeader(data, 'authorization', 'Basic ' + new Buffer(basic).toString('base64')); + var basic = []; + auth.username != null && basic.push(auth.username); + auth.password != null && basic.push(auth.password); + if (basic = basic.join(':')) { + util.setHeader(data, 'authorization', 'Basic ' + new Buffer(basic).toString('base64')); } } function handleCookies(data, cookies, curCookies) { - var list = cookies && Object.keys(cookies); - if (list && list.length) { - var result = {}; - if (curCookies && typeof curCookies == 'string') { - curCookies.split(/;\s*/g) + var list = cookies && Object.keys(cookies); + if (list && list.length) { + var result = {}; + if (curCookies && typeof curCookies == 'string') { + curCookies.split(/;\s*/g) .forEach(function(cookie) { - var index = cookie.indexOf('='); - if (index == -1) { - result[cookie] = null; + var index = cookie.indexOf('='); + if (index == -1) { + result[cookie] = null; } else { - result[cookie.substring(0, index)] = cookie.substring(index + 1); + result[cookie.substring(0, index)] = cookie.substring(index + 1); } }); } - list.forEach(function(name) { - var value = cookies[name]; - value = value && typeof value == 'object' ? value.value : value; - result[util.encodeURIComponent(name)] = value ? util.encodeURIComponent(value) : value; + list.forEach(function(name) { + var value = cookies[name]; + value = value && typeof value == 'object' ? value.value : value; + result[util.encodeURIComponent(name)] = value ? util.encodeURIComponent(value) : value; }); - cookies = Object.keys(result).map(function(name) { - var value = result[name]; - return name + (value == null ? '' : '=' + value); + cookies = Object.keys(result).map(function(name) { + var value = result[name]; + return name + (value == null ? '' : '=' + value); }).join('; '); - util.setHeader(data, 'cookie', cookies); + util.setHeader(data, 'cookie', cookies); } } function handleParams(req, params) { - var _params = params; - if (!(params = params && qs.stringify(params))) { - return; + var _params = params; + if (!(params = params && qs.stringify(params))) { + return; } - if (util.isUrlEncoded(req)) { - delete req.headers['content-length']; - var transform = new Transform(); - var buffer, interrupt; - transform._transform = function(chunk, encoding, callback) { - if (chunk) { - if (!interrupt) { - buffer = buffer ? Buffer.concat([buffer, chunk]) : chunk; - chunk = null; - if (buffer.length > MAX_REQ_SIZE) { - interrupt = true; - chunk = buffer; - buffer = null; + if (util.isUrlEncoded(req)) { + delete req.headers['content-length']; + var transform = new Transform(); + var buffer, interrupt; + transform._transform = function(chunk, encoding, callback) { + if (chunk) { + if (!interrupt) { + buffer = buffer ? Buffer.concat([buffer, chunk]) : chunk; + chunk = null; + if (buffer.length > MAX_REQ_SIZE) { + interrupt = true; + chunk = buffer; + buffer = null; } } } else if (buffer) { - var body = buffer + ''; - var isGBK = body.indexOf('�') == -1; - if (isGBK) { - body = iconv.decode(buffer, 'GB18030'); - body = util.replaceQueryString(body, params); - chunk = iconv.encode(body, 'GB18030'); + var body = buffer + ''; + var isGBK = body.indexOf('�') == -1; + if (isGBK) { + body = iconv.decode(buffer, 'GB18030'); + body = util.replaceQueryString(body, params); + chunk = iconv.encode(body, 'GB18030'); } else { - chunk = new Buffer(body); + chunk = new Buffer(body); } - buffer = null; + buffer = null; } else { - chunk = new Buffer(params); + chunk = new Buffer(params); } - callback(null, chunk); + callback(null, chunk); }; - req.add(transform); + req.add(transform); } else if (util.isMultipart(req) && /boundary=(?:"([^"]+)"|([^;]+))/i.test(req.headers['content-type'])) { - delete req.headers['content-length']; - var boundaryStr = '--' + (RegExp.$1 || RegExp.$2); - var startBoundary = new Buffer(boundaryStr + '\r\n'); - var boundary = new Buffer('\r\n' + boundaryStr); - var sepBoundary = new Buffer('\r\n' + boundaryStr + '\r\n'); - var endBoudary = new Buffer('\r\n' + boundaryStr + '--'); - var length = startBoundary.length; - var sepLength = sepBoundary.length; - var transform = new Transform(); + delete req.headers['content-length']; + var boundaryStr = '--' + (RegExp.$1 || RegExp.$2); + var startBoundary = new Buffer(boundaryStr + '\r\n'); + var boundary = new Buffer('\r\n' + boundaryStr); + var sepBoundary = new Buffer('\r\n' + boundaryStr + '\r\n'); + var endBoudary = new Buffer('\r\n' + boundaryStr + '--'); + var length = startBoundary.length; + var sepLength = sepBoundary.length; + var transform = new Transform(); - transform.parse = function(chunk) { - var index, result, sep, data; - while((index = util.indexOfList(chunk, boundary)) != -1 + transform.parse = function(chunk) { + var index, result, sep, data; + while((index = util.indexOfList(chunk, boundary)) != -1 && ((sep = util.startWithList(chunk, sepBoundary, index)) || util.startWithList(chunk, endBoudary, index))) { - data = this.parser.transform(chunk.slice(0, index)); - result = result && data ? Buffer.concat([result, data]) : (result || data); - if (!sep) { - data = util.toMultiparts(_params, boundaryStr); - result = result ? Buffer.concat([result, data]) : data; + data = this.parser.transform(chunk.slice(0, index)); + result = result && data ? Buffer.concat([result, data]) : (result || data); + if (!sep) { + data = util.toMultiparts(_params, boundaryStr); + result = result ? Buffer.concat([result, data]) : data; } - sep = sep ? sepBoundary : endBoudary; - result = result ? Buffer.concat([result, sep]) : sep; - chunk = chunk.slice(index + sepLength); - this.parser = new MultiPartParser(_params); + sep = sep ? sepBoundary : endBoudary; + result = result ? Buffer.concat([result, sep]) : sep; + chunk = chunk.slice(index + sepLength); + this.parser = new MultiPartParser(_params); } - var len = chunk.length; - if (len >= sepLength) { - var lastIndex = len - sepLength + 1; - data = this.parser.transform(chunk.slice(0, lastIndex)); - chunk = chunk.slice(lastIndex); - result = result && data ? Buffer.concat([result, data]) : (result || data); + var len = chunk.length; + if (len >= sepLength) { + var lastIndex = len - sepLength + 1; + data = this.parser.transform(chunk.slice(0, lastIndex)); + chunk = chunk.slice(lastIndex); + result = result && data ? Buffer.concat([result, data]) : (result || data); } - this.buffer = chunk; + this.buffer = chunk; - return result; + return result; }; - transform._transform = function(chunk, encoding, callback) { - if (this.badMultipart) { - return callback(null, chunk); + transform._transform = function(chunk, encoding, callback) { + if (this.badMultipart) { + return callback(null, chunk); } - var end; - if (chunk) { - chunk = this.buffer ? Buffer.concat([this.buffer, chunk]) : chunk; + var end; + if (chunk) { + chunk = this.buffer ? Buffer.concat([this.buffer, chunk]) : chunk; } else { - end = true; - chunk = this.buffer; + end = true; + chunk = this.buffer; } - if (chunk) { - this.buffer = null; - if (!this.parser) { - if (util.startWithList(chunk, startBoundary)) { - this.parser = new MultiPartParser(_params); - chunk = this.parse(chunk.slice(length)); - chunk = chunk ? Buffer.concat([startBoundary, chunk]) : startBoundary; + if (chunk) { + this.buffer = null; + if (!this.parser) { + if (util.startWithList(chunk, startBoundary)) { + this.parser = new MultiPartParser(_params); + chunk = this.parse(chunk.slice(length)); + chunk = chunk ? Buffer.concat([startBoundary, chunk]) : startBoundary; } else if(end || chunk.length >= length) { - this.badMultipart = true; + this.badMultipart = true; } else { - this.buffer = chunk; - chunk = null; + this.buffer = chunk; + chunk = null; } } else { - chunk = this.parse(chunk); + chunk = this.parse(chunk); } } - if (end && this.buffer) { - chunk = chunk ? Buffer.concat([chunk, this.buffer]) : this.buffer; + if (end && this.buffer) { + chunk = chunk ? Buffer.concat([chunk, this.buffer]) : this.buffer; } - callback(null, chunk); + callback(null, chunk); }; - req.add(transform); + req.add(transform); } else if (/^https?:/.test(req.options.href)) { - req.options =url.parse(util.replaceUrlQueryString(req.options.href, params)); + req.options =url.parse(util.replaceUrlQueryString(req.options.href, params)); } } function handleUrlReplace(req, params) { - if (!params || !/^https?:/.test(req.options.href)) { - return; + if (!params || !/^https?:/.test(req.options.href)) { + return; } - var path = req.options.href; - var index = path.indexOf('://'); - if (index == -1) { - return; + var path = req.options.href; + var index = path.indexOf('://'); + if (index == -1) { + return; } - index = path.indexOf('/', index + 3) + 1; - if (index <= 0) { - return; + index = path.indexOf('/', index + 3) + 1; + if (index <= 0) { + return; } - var root = path.substring(0, index); - path = path.substring(index); + var root = path.substring(0, index); + path = path.substring(index); - Object.keys(params).forEach(function(pattern) { - var value = params[pattern]; - value = value == null ? '' : value + ''; - if (util.isOriginalRegExp(pattern) && (pattern = util.toOriginalRegExp(pattern))) { - path = path.replace(pattern, value); + Object.keys(params).forEach(function(pattern) { + var value = params[pattern]; + value = value == null ? '' : value + ''; + if (util.isOriginalRegExp(pattern) && (pattern = util.toOriginalRegExp(pattern))) { + path = path.replace(pattern, value); } else if (pattern) { - path = path.split(pattern).join(value); + path = path.split(pattern).join(value); } }); - req.options = url.parse(root + path); + req.options = url.parse(root + path); } function removeDisableProps(req) { - var disable = req.disable; - var headers = req.headers; + var disable = req.disable; + var headers = req.headers; - if (disable.ua) { - delete headers['user-agent']; + if (disable.ua) { + delete headers['user-agent']; } - if (disable.cookie || disable.cookies || + if (disable.cookie || disable.cookies || disable.reqCookie || disable.reqCookies) { - delete headers.cookie; + delete headers.cookie; } - if (disable.referer) { - delete headers.referer; + if (disable.referer) { + delete headers.referer; } - if (disable.ajax) { - delete headers['x-requested-with']; + if (disable.ajax) { + delete headers['x-requested-with']; } - if (disable.cache) { - util.disableReqCache(headers); + if (disable.cache) { + util.disableReqCache(headers); } } function handleReplace(req, replacement) { - if (!util.hasRequestBody(req) || !replacement) { - return; + if (!util.hasRequestBody(req) || !replacement) { + return; } - var type = req.headers['content-type']; - type = util.isUrlEncoded(req) ? 'FORM' : util.getContentType(type); - if (!type || type == 'IMG') { - return; + var type = req.headers['content-type']; + type = util.isUrlEncoded(req) ? 'FORM' : util.getContentType(type); + if (!type || type == 'IMG') { + return; } - Object.keys(replacement).forEach(function(pattern) { - var value = replacement[pattern]; - if (util.isOriginalRegExp(pattern) && (pattern = util.toOriginalRegExp(pattern))) { - req.addTextTransform(new ReplacePatternTransform(pattern, value)); + Object.keys(replacement).forEach(function(pattern) { + var value = replacement[pattern]; + if (util.isOriginalRegExp(pattern) && (pattern = util.toOriginalRegExp(pattern))) { + req.addTextTransform(new ReplacePatternTransform(pattern, value)); } else if (pattern) { - req.addTextTransform(new ReplaceStringTransform(pattern, value)); + req.addTextTransform(new ReplaceStringTransform(pattern, value)); } }); } module.exports = function(req, res, next) { - var reqRules = req.rules; - var authObj; - if (reqRules.auth) { - authObj = util.getMatcherValue(reqRules.auth); - if (/[\\\/]/.test(authObj)) { - authObj = null; + var reqRules = req.rules; + var authObj; + if (reqRules.auth) { + authObj = util.getMatcherValue(reqRules.auth); + if (/[\\\/]/.test(authObj)) { + authObj = null; } else { - var index = authObj.indexOf(':'); - authObj = { - username: index == -1 ? authObj : authObj.substring(0, index), - password: index == -1 ? null : authObj.substring(index + 1) + var index = authObj.indexOf(':'); + authObj = { + username: index == -1 ? authObj : authObj.substring(0, index), + password: index == -1 ? null : authObj.substring(index + 1) }; } } - util.parseRuleJson([reqRules.req, reqRules.reqHeaders, reqRules.reqCookies, + util.parseRuleJson([reqRules.req, reqRules.reqHeaders, reqRules.reqCookies, authObj ? null : reqRules.auth, reqRules.params, reqRules.reqCors, reqRules.reqReplace, reqRules.urlReplace], function(data, headers, cookies, auth, params, cors, replacement, urlReplace) { - if (reqRules.head && reqRules.head.req) { - data = extend(reqRules.head.req, data); + if (reqRules.head && reqRules.head.req) { + data = extend(reqRules.head.req, data); } - data = data || {}; - if (headers) { - data.headers = extend(data.headers || {}, headers); + data = data || {}; + if (headers) { + data.headers = extend(data.headers || {}, headers); } - if (data.headers) { - data.headers = util.lowerCaseify(data.headers); + if (data.headers) { + data.headers = util.lowerCaseify(data.headers); } - if (reqRules.method) { - var method = util.getMatcherValue(reqRules.method); - data.method = method; + if (reqRules.method) { + var method = util.getMatcherValue(reqRules.method); + data.method = method; } - if (reqRules.reqType) { - var newType = util.getMatcherValue(reqRules.reqType).split(';'); - var type = newType[0]; - newType[0] = (!type || type.indexOf('/') != -1) ? type : (REQ_TYPE[type] || REQ_TYPE.defaultType); - type = newType.join(';'); - if (type.indexOf(';') == -1) { - var origType = req.headers['content-type']; - if (typeof origType == 'string' && origType.indexOf(';') != -1) { - origType = origType.split(';'); - origType[0] = type; - type = origType.join(';'); + if (reqRules.reqType) { + var newType = util.getMatcherValue(reqRules.reqType).split(';'); + var type = newType[0]; + newType[0] = (!type || type.indexOf('/') != -1) ? type : (REQ_TYPE[type] || REQ_TYPE.defaultType); + type = newType.join(';'); + if (type.indexOf(';') == -1) { + var origType = req.headers['content-type']; + if (typeof origType == 'string' && origType.indexOf(';') != -1) { + origType = origType.split(';'); + origType[0] = type; + type = origType.join(';'); } } - util.setHeader(data, 'content-type', type); + util.setHeader(data, 'content-type', type); } - if (reqRules.reqCharset) { - data.charset = util.getMatcherValue(reqRules.reqCharset); + if (reqRules.reqCharset) { + data.charset = util.getMatcherValue(reqRules.reqCharset); } - if (reqRules.referer) { - var referer = util.getMatcherValue(reqRules.referer); - util.setHeader(data, 'referer', referer); + if (reqRules.referer) { + var referer = util.getMatcherValue(reqRules.referer); + util.setHeader(data, 'referer', referer); } - if (reqRules.accept) { - var accept = util.getMatcherValue(reqRules.accept); - util.setHeader(data, 'accept', accept); + if (reqRules.accept) { + var accept = util.getMatcherValue(reqRules.accept); + util.setHeader(data, 'accept', accept); } - if (reqRules.ua) { - var ua = util.getMatcherValue(reqRules.ua); - util.setHeader(data, 'user-agent', ua); + if (reqRules.ua) { + var ua = util.getMatcherValue(reqRules.ua); + util.setHeader(data, 'user-agent', ua); } - if (reqRules.etag) { - var etag = util.getMatcherValue(reqRules.etag); - util.setHeader(data, 'etag', etag); + if (reqRules.etag) { + var etag = util.getMatcherValue(reqRules.etag); + util.setHeader(data, 'etag', etag); } - var reqDelay = util.getMatcherValue(reqRules.reqDelay); - reqDelay = reqDelay && parseInt(reqDelay, 10); - if (reqDelay > 0) { - data.delay = reqDelay; + var reqDelay = util.getMatcherValue(reqRules.reqDelay); + reqDelay = reqDelay && parseInt(reqDelay, 10); + if (reqDelay > 0) { + data.delay = reqDelay; } - var reqSpeed = util.getMatcherValue(reqRules.reqSpeed); - reqSpeed = reqSpeed && parseFloat(reqSpeed); - if (reqSpeed > 0) { - data.speed = reqSpeed; + var reqSpeed = util.getMatcherValue(reqRules.reqSpeed); + reqSpeed = reqSpeed && parseFloat(reqSpeed); + if (reqSpeed > 0) { + data.speed = reqSpeed; } - handleCookies(data, cookies, req.headers.cookie); - handleAuth(data, auth || authObj); - handleCors(data, cors); + handleCookies(data, cookies, req.headers.cookie); + handleAuth(data, auth || authObj); + handleCors(data, cors); - util.readInjectFiles(data, function(data) { - util.getRuleValue([reqRules.reqBody, reqRules.reqPrepend, reqRules.reqAppend], + util.readInjectFiles(data, function(data) { + util.getRuleValue([reqRules.reqBody, reqRules.reqPrepend, reqRules.reqAppend], function(reqBody, reqPrepend, reqAppend) { - if (reqBody) { - data.body = reqBody; + if (reqBody) { + data.body = reqBody; } - if (reqPrepend) { - data.top = reqPrepend; + if (reqPrepend) { + data.top = reqPrepend; } - if (reqAppend) { - data.bottom = reqAppend; + if (reqAppend) { + data.bottom = reqAppend; } - handleReq(req, data); - handleParams(req, params); - handleUrlReplace(req, urlReplace); - util.removeUnsupportsHeaders(req.headers); - removeDisableProps(req); - handleReplace(req, replacement); + handleReq(req, data); + handleParams(req, params); + handleUrlReplace(req, urlReplace); + util.removeUnsupportsHeaders(req.headers); + removeDisableProps(req); + handleReplace(req, replacement); - util.getFileWriters([util.hasRequestBody(req) ? util.getRuleFile(reqRules.reqWrite) : null, util.getRuleFile(reqRules.reqWriteRaw)], function(writer, rawWriter) { - if (writer) { - req.add(new FileWriterTransform(writer, req, false, false, true)); + util.getFileWriters([util.hasRequestBody(req) ? util.getRuleFile(reqRules.reqWrite) : null, util.getRuleFile(reqRules.reqWriteRaw)], function(writer, rawWriter) { + if (writer) { + req.add(new FileWriterTransform(writer, req, false, false, true)); } - if (rawWriter) { - req.add(new FileWriterTransform(rawWriter, req, true, false, true)); + if (rawWriter) { + req.add(new FileWriterTransform(rawWriter, req, true, false, true)); } - next(); + next(); }); }, !util.hasRequestBody(req.method)); diff --git a/lib/inspectors/res.js b/lib/inspectors/res.js index 4642340ca..8143f2636 100644 --- a/lib/inspectors/res.js +++ b/lib/inspectors/res.js @@ -48,292 +48,292 @@ function getDeleteProperties(deleteRule) { } function handleCookies(data, cookies) { - var list = cookies && Object.keys(cookies); - var curCookies = data.headers && data.headers['set-cookie']; - if (!Array.isArray(curCookies)) { - curCookies = curCookies ? [curCookies + ''] : []; + var list = cookies && Object.keys(cookies); + var curCookies = data.headers && data.headers['set-cookie']; + if (!Array.isArray(curCookies)) { + curCookies = curCookies ? [curCookies + ''] : []; } - if (list && list.length) { - var result = {}; - curCookies.forEach(function(cookie) { - var index = cookie.indexOf('='); - if (index == -1) { - result[cookie] = null; + if (list && list.length) { + var result = {}; + curCookies.forEach(function(cookie) { + var index = cookie.indexOf('='); + if (index == -1) { + result[cookie] = null; } else { - result[cookie.substring(0, index)] = cookie.substring(index + 1); + result[cookie.substring(0, index)] = cookie.substring(index + 1); } }); - list.forEach(function(name) { - var cookie = cookies[name]; - name = util.encodeURIComponent(name); - if (!cookie || typeof cookie != 'object') { - result[name] = cookie ? util.encodeURIComponent(cookie) : cookie; + list.forEach(function(name) { + var cookie = cookies[name]; + name = util.encodeURIComponent(name); + if (!cookie || typeof cookie != 'object') { + result[name] = cookie ? util.encodeURIComponent(cookie) : cookie; } else { - var attrs = []; - var value = cookie.value; - attrs.push(value ? util.encodeURIComponent(value) : (value == null ? '' : value)); - var maxAge = cookie.maxAge && parseInt(cookie.maxAge, 10); - if (!Number.isNaN(maxAge)) { - attrs.push('Expires=' + new Date(Date.now() + maxAge * 1000).toGMTString()); - attrs.push('Max-Age=' + maxAge); + var attrs = []; + var value = cookie.value; + attrs.push(value ? util.encodeURIComponent(value) : (value == null ? '' : value)); + var maxAge = cookie.maxAge && parseInt(cookie.maxAge, 10); + if (!Number.isNaN(maxAge)) { + attrs.push('Expires=' + new Date(Date.now() + maxAge * 1000).toGMTString()); + attrs.push('Max-Age=' + maxAge); } - cookie.secure && attrs.push('Secure'); - cookie.path && attrs.push('Path=' + cookie.path); - cookie.domain && attrs.push('Domain=' + cookie.domain); - cookie.httpOnly && attrs.push('HttpOnly'); - result[name] = attrs.join('; '); + cookie.secure && attrs.push('Secure'); + cookie.path && attrs.push('Path=' + cookie.path); + cookie.domain && attrs.push('Domain=' + cookie.domain); + cookie.httpOnly && attrs.push('HttpOnly'); + result[name] = attrs.join('; '); } }); - cookies = Object.keys(result).map(function(name) { - var value = result[name]; - return name + (value == null ? '' : '=' + value); + cookies = Object.keys(result).map(function(name) { + var value = result[name]; + return name + (value == null ? '' : '=' + value); }); - util.setHeader(data, 'set-cookie', cookies); + util.setHeader(data, 'set-cookie', cookies); } } function handleCors(data, cors) { - if (!cors) { - return; + if (!cors) { + return; } - if (cors.origin !== undefined) { - util.setHeader(data, 'access-control-allow-origin', cors.origin); + if (cors.origin !== undefined) { + util.setHeader(data, 'access-control-allow-origin', cors.origin); } - if (cors.methods !== undefined) { - util.setHeader(data, 'access-control-allow-methods', cors.methods); + if (cors.methods !== undefined) { + util.setHeader(data, 'access-control-allow-methods', cors.methods); } - if (cors.headers !== undefined) { - util.setHeader(data, 'access-control-expose-headers', cors.headers); + if (cors.headers !== undefined) { + util.setHeader(data, 'access-control-expose-headers', cors.headers); } - if (cors.credentials !== undefined) { - util.setHeader(data, 'access-control-allow-credentials', cors.credentials); + if (cors.credentials !== undefined) { + util.setHeader(data, 'access-control-allow-credentials', cors.credentials); } - if (cors.maxAge !== undefined) { - util.setHeader(data, 'access-control-max-age', cors.maxAge); + if (cors.maxAge !== undefined) { + util.setHeader(data, 'access-control-max-age', cors.maxAge); } } function setCookies(headers, data) { - var newCookies = data.headers['set-cookie']; - if (newCookies) { - var cookies = headers['set-cookie']; - if (Array.isArray(cookies)) { - var newNameMap = {}; - newCookies.forEach(function(cookie) { - var index = cookie.indexOf('='); - var name = index == -1 ? name : cookie.substring(0, index); - newNameMap[name] = 1; + var newCookies = data.headers['set-cookie']; + if (newCookies) { + var cookies = headers['set-cookie']; + if (Array.isArray(cookies)) { + var newNameMap = {}; + newCookies.forEach(function(cookie) { + var index = cookie.indexOf('='); + var name = index == -1 ? name : cookie.substring(0, index); + newNameMap[name] = 1; }); - cookies.forEach(function(cookie) { - var index = cookie.indexOf('='); - var name = index == -1 ? name : cookie.substring(0, index); - if (!newNameMap[name]) { - newCookies.push(cookie); + cookies.forEach(function(cookie) { + var index = cookie.indexOf('='); + var name = index == -1 ? name : cookie.substring(0, index); + if (!newNameMap[name]) { + newCookies.push(cookie); } }); } - headers['set-cookie'] = newCookies; - delete data.headers['set-cookie']; + headers['set-cookie'] = newCookies; + delete data.headers['set-cookie']; } } function removeDisableProps(req, headers) { - var disable = req.disable; + var disable = req.disable; - if (disable.cookie || disable.cookies || + if (disable.cookie || disable.cookies || disable.resCookie || disable.resCookies) { - delete headers['set-cookie']; + delete headers['set-cookie']; } - if (disable.cache) { - headers['cache-control'] = 'no-cache'; - headers.expires = new Date(Date.now() -60000000).toGMTString(); - headers.pragma = 'no-cache'; + if (disable.cache) { + headers['cache-control'] = 'no-cache'; + headers.expires = new Date(Date.now() -60000000).toGMTString(); + headers.pragma = 'no-cache'; } - disable.csp && util.disableCSP(headers); + disable.csp && util.disableCSP(headers); } function handleReplace(res, replacement) { - if (!replacement) { - return; + if (!replacement) { + return; } - var type = util.getContentType(res.headers); - if (!type || type == 'IMG') { - return; + var type = util.getContentType(res.headers); + if (!type || type == 'IMG') { + return; } - Object.keys(replacement).forEach(function(pattern) { - var value = replacement[pattern]; - if (util.isOriginalRegExp(pattern) && (pattern = util.toOriginalRegExp(pattern))) { - res.addTextTransform(new ReplacePatternTransform(pattern, value)); + Object.keys(replacement).forEach(function(pattern) { + var value = replacement[pattern]; + if (util.isOriginalRegExp(pattern) && (pattern = util.toOriginalRegExp(pattern))) { + res.addTextTransform(new ReplacePatternTransform(pattern, value)); } else if (pattern) { - res.addTextTransform(new ReplaceStringTransform(pattern, value)); + res.addTextTransform(new ReplaceStringTransform(pattern, value)); } }); } function getWriterFile(file, statusCode) { - if (!file || statusCode == 200) { - return file; + if (!file || statusCode == 200) { + return file; } - return file + '.' + statusCode; + return file + '.' + statusCode; } module.exports = function(req, res, next) { - var config = this.config; - var responsed, timer; - var resRules = req.rules; - var deleteHeaders = getDeleteProperties(resRules['delete']); + var config = this.config; + var responsed, timer; + var resRules = req.rules; + var deleteHeaders = getDeleteProperties(resRules['delete']); - req.request = function(options) { - options = options || req.options; - req.realUrl = res.realUrl = options.href; + req.request = function(options) { + options = options || req.options; + req.realUrl = res.realUrl = options.href; - var now = Date.now(); - var proxyUrl; - if (protoMgr.isProxyProtocol(options.protocol)) { - proxyUrl = util.rule.getMatcher(resRules.rule); - options = url.parse(req.fullUrl); + var now = Date.now(); + var proxyUrl; + if (protoMgr.isProxyProtocol(options.protocol)) { + proxyUrl = util.rule.getMatcher(resRules.rule); + options = url.parse(req.fullUrl); } - rules.resolveHost(options.localDNS && net.isIP(options.host) ? options.host : + rules.resolveHost(options.localDNS && net.isIP(options.host) ? options.host : (proxyUrl && util.replaceProtocol(proxyUrl, util.getProtocol(req.fullUrl)) || options.href), function(err, ip, port, host) { - req.dnsTime = Date.now() - now; - req.hostIp = ip; + req.dnsTime = Date.now() - now; + req.hostIp = ip; - if (host) { - resRules.host = host; + if (host) { + resRules.host = host; } - if (err) { - res.response(util.wrapGatewayError('DNS Lookup Failed\r\n' + util.getErrorStack(err))); - return; + if (err) { + res.response(util.wrapGatewayError('DNS Lookup Failed\r\n' + util.getErrorStack(err))); + return; } - var isHttps = options.protocol == 'https:'; - var headers = req.headers; - if (proxyUrl) { - var proxyOptions = url.parse(proxyUrl); - proxyOptions.host = ip; - var isSocks = proxyOptions.protocol == 'socks:'; - if (isHttps || isSocks) { - if ((proxyOptions.port || (isHttps ? 1080 : 80)) == config.port && util.isLocalAddress(ip)) { - res.response(util.wrapResponse({ - statusCode: 302, - headers: { - location: 'http://' + config.localUIHost + (options.path || '') + var isHttps = options.protocol == 'https:'; + var headers = req.headers; + if (proxyUrl) { + var proxyOptions = url.parse(proxyUrl); + proxyOptions.host = ip; + var isSocks = proxyOptions.protocol == 'socks:'; + if (isHttps || isSocks) { + if ((proxyOptions.port || (isHttps ? 1080 : 80)) == config.port && util.isLocalAddress(ip)) { + res.response(util.wrapResponse({ + statusCode: 302, + headers: { + location: 'http://' + config.localUIHost + (options.path || '') } })); } else { - var opts = { - isSocks: isSocks, - host: ip, - port: proxyOptions.port, - isHttps: isHttps, - url: req.fullUrl, - auth: proxyOptions.auth, - headers: { - host: headers.host, - 'proxy-connection': 'keep-alive', - 'user-agent': headers['user-agent'] + var opts = { + isSocks: isSocks, + host: ip, + port: proxyOptions.port, + isHttps: isHttps, + url: req.fullUrl, + auth: proxyOptions.auth, + headers: { + host: headers.host, + 'proxy-connection': 'keep-alive', + 'user-agent': headers['user-agent'] } }; - options.agent = isSocks ? config.getSocksAgent(opts) : config.getHttpsAgent(opts); - request(options); + options.agent = isSocks ? config.getSocksAgent(opts) : config.getHttpsAgent(opts); + request(options); } - return; + return; } - options.port = proxyOptions.port || config.port; //http proxy - if (proxyOptions.auth) { - headers['proxy-authorization'] = 'Basic ' + + options.port = proxyOptions.port || config.port; //http proxy + if (proxyOptions.auth) { + headers['proxy-authorization'] = 'Basic ' + new Buffer(proxyOptions.auth + '').toString('base64'); } } - req.hostIp = port ? ip + ':' + port : ip; - port = port || options.port; - options.host = ip;//设置ip - if ((port || (isHttps ? 443 : 80)) == config.port && util.isLocalAddress(options.host)) { - res.response(util.wrapResponse({ - statusCode: 302, - headers: { - location: 'http://' + config.localUIHost + (options.path || '') + req.hostIp = port ? ip + ':' + port : ip; + port = port || options.port; + options.host = ip;//设置ip + if ((port || (isHttps ? 443 : 80)) == config.port && util.isLocalAddress(options.host)) { + res.response(util.wrapResponse({ + statusCode: 302, + headers: { + location: 'http://' + config.localUIHost + (options.path || '') } })); } else { - options.agent = req.disable.keepAlive ? false : (isHttps ? config.httpsAgent : config.httpAgent); - request(options, port); + options.agent = req.disable.keepAlive ? false : (isHttps ? config.httpsAgent : config.httpAgent); + request(options, port); } - function request(options, port) { - options.headers = headers; - options.method = req.method; - options.rejectUnauthorized = false; - if (!proxyUrl && !options.isPlugin) { - headers.host = options.hostname + (options.port ? ':' + options.port : ''); - } else if (proxyUrl && port) { - options.path = options.href; - } + function request(options, port) { + options.headers = headers; + options.method = req.method; + options.rejectUnauthorized = false; + if (!proxyUrl && !options.isPlugin) { + headers.host = options.hostname + (options.port ? ':' + options.port : ''); +} else if (proxyUrl && port) { + options.path = options.href; +} //tencent的服务器不识别小写的host - if (resRules.hostname) { - headers.Host = headers.host = util.getMatcherValue(resRules.hostname); + if (resRules.hostname) { + headers.Host = headers.host = util.getMatcherValue(resRules.hostname); } else { - headers.Host = headers.host; + headers.Host = headers.host; } - delete options.hostname; //防止自动dns - options.port = port || options.port; - var _request = function() { - try { - var client = (isHttps ? https : http).request(options, res.response); - clearTimeout(timer); - if (!timer && !util.hasRequestBody(req)) { - client.once('finish', function() { - timer = setTimeout(function() { - if (responsed) { - return; + delete options.hostname; //防止自动dns + options.port = port || options.port; + var _request = function() { + try { + var client = (isHttps ? https : http).request(options, res.response); + clearTimeout(timer); + if (!timer && !util.hasRequestBody(req)) { + client.once('finish', function() { + timer = setTimeout(function() { + if (responsed) { + return; } - client.abort(); + client.abort(); }, config.responseTimeout); }); } - return req.pipe(client); + return req.pipe(client); } catch(e) { - res.response(util.wrapGatewayError(util.getErrorStack(e))); + res.response(util.wrapGatewayError(util.getErrorStack(e))); } - return req; + return req; }; - if (deleteHeaders) { - Object.keys(deleteHeaders.reqHeaders).forEach(function(prop) { - delete req.headers[prop]; + if (deleteHeaders) { + Object.keys(deleteHeaders.reqHeaders).forEach(function(prop) { + delete req.headers[prop]; }); } - _request().on('error', function(err) { - if (responsed) { - return; + _request().on('error', function(err) { + if (responsed) { + return; } - if (util.hasRequestBody(req)) { - res.response(util.wrapGatewayError(util.getErrorStack(err))); + if (util.hasRequestBody(req)) { + res.response(util.wrapGatewayError(util.getErrorStack(err))); } else { - _request().on('error', function(err) { - if (!responsed) { - _request().on('error', function(err) { - res.response(util.wrapGatewayError(util.getErrorStack(err))); + _request().on('error', function(err) { + if (!responsed) { + _request().on('error', function(err) { + res.response(util.wrapGatewayError(util.getErrorStack(err))); }); } }); @@ -344,253 +344,253 @@ module.exports = function(req, res, next) { }, req.pluginRules); }; - res.response = function(_res) { - if (responsed) { - return; + res.response = function(_res) { + if (responsed) { + return; } - clearTimeout(timer); - responsed = true; - if (_res.realUrl) { - req.realUrl = res.realUrl = _res.realUrl; + clearTimeout(timer); + responsed = true; + if (_res.realUrl) { + req.realUrl = res.realUrl = _res.realUrl; } - res.headers = _res.headers; - res.trailers = _res.trailers; + res.headers = _res.headers; + res.trailers = _res.trailers; - pluginMgr.getResRules(req, _res, function(resRulesMgr) { - if (resRulesMgr) { - var _resRules = resRulesMgr.resolveRules(req.fullUrl); - protoMgr.resProtocols.forEach(function(protocol) { - var rule = _resRules[protocol]; - if (rule) { - resRules[protocol] = rule; + pluginMgr.getResRules(req, _res, function(resRulesMgr) { + if (resRulesMgr) { + var _resRules = resRulesMgr.resolveRules(req.fullUrl); + protoMgr.resProtocols.forEach(function(protocol) { + var rule = _resRules[protocol]; + if (rule) { + resRules[protocol] = rule; } }); - util.handlePluginRules(req, resRulesMgr, true); + util.handlePluginRules(req, resRulesMgr, true); } - res.statusCode = _res.statusCode = util.getMatcherValue(resRules.replaceStatus) || _res.statusCode; - if (req.disable['301'] && _res.statusCode == 301) { - res.statusCode = _res.statusCode = 302; + res.statusCode = _res.statusCode = util.getMatcherValue(resRules.replaceStatus) || _res.statusCode; + if (req.disable['301'] && _res.statusCode == 301) { + res.statusCode = _res.statusCode = 302; } - var cors = resRules.resCors; - var resCors = util.getMatcherValue(cors); - if (resCors == 'use-credentials') { - cors = null; - resCors = 'enable'; + var cors = resRules.resCors; + var resCors = util.getMatcherValue(cors); + if (resCors == 'use-credentials') { + cors = null; + resCors = 'enable'; } else if (resCors == '*' || resCors == 'enable') { - cors = null; + cors = null; } else { - resCors = null; + resCors = null; } - util.parseRuleJson([resRules.res, resRules.resHeaders, resRules.resCookies, cors, resRules.resReplace], + util.parseRuleJson([resRules.res, resRules.resHeaders, resRules.resCookies, cors, resRules.resReplace], function(data, headers, cookies, cors, replacement) { - if (resRules.head && resRules.head.res) { - data = extend(resRules.head.res, data); + if (resRules.head && resRules.head.res) { + data = extend(resRules.head.res, data); } - data = data || {}; + data = data || {}; - if (headers) { - data.headers = extend(data.headers || {}, headers); + if (headers) { + data.headers = extend(data.headers || {}, headers); } - if (data.headers) { - data.headers = util.lowerCaseify(data.headers); + if (data.headers) { + data.headers = util.lowerCaseify(data.headers); } - handleCookies(data, cookies); + handleCookies(data, cookies); - if (resCors == '*') { - util.setHeader(data, 'access-control-allow-origin', '*'); + if (resCors == '*') { + util.setHeader(data, 'access-control-allow-origin', '*'); } else if (resCors == 'enable') { - var origin = req.headers.origin; - util.setHeaders(data, { - 'access-control-allow-credentials': !!origin, - 'access-control-allow-origin': origin || '*' + var origin = req.headers.origin; + util.setHeaders(data, { + 'access-control-allow-credentials': !!origin, + 'access-control-allow-origin': origin || '*' }); } else { - handleCors(data, cors); + handleCors(data, cors); } - var cache = util.getMatcherValue(resRules.cache); - var maxAge = parseInt(cache, 10); - var noCache = /^(?:no|no-cache|no-store)$/i.test(cache) || maxAge < 0; - if (maxAge > 0 || noCache) { - util.setHeaders(data, { - 'cache-control': noCache ? (/^no-store$/i.test(cache) ? 'no-store' : 'no-cache') : 'max-age=' + maxAge, - 'expires': new Date(Date.now() + (noCache ? -60000000 : maxAge)).toGMTString(), - 'pragma': noCache ? 'no-cache' : '' + var cache = util.getMatcherValue(resRules.cache); + var maxAge = parseInt(cache, 10); + var noCache = /^(?:no|no-cache|no-store)$/i.test(cache) || maxAge < 0; + if (maxAge > 0 || noCache) { + util.setHeaders(data, { + 'cache-control': noCache ? (/^no-store$/i.test(cache) ? 'no-store' : 'no-cache') : 'max-age=' + maxAge, + 'expires': new Date(Date.now() + (noCache ? -60000000 : maxAge)).toGMTString(), + 'pragma': noCache ? 'no-cache' : '' }); } - if (resRules.attachment) { - var attachment = util.getMatcherValue(resRules.attachment) || util.getFilename(req.fullUrl); - util.setHeader(data, 'content-disposition', 'attachment; filename="' + attachment + '"'); - util.disableReqCache(req.headers); + if (resRules.attachment) { + var attachment = util.getMatcherValue(resRules.attachment) || util.getFilename(req.fullUrl); + util.setHeader(data, 'content-disposition', 'attachment; filename="' + attachment + '"'); + util.disableReqCache(req.headers); } - if (resRules.location) { - util.setHeader(data, 'location', util.getMatcherValue(resRules.location)); + if (resRules.location) { + util.setHeader(data, 'location', util.getMatcherValue(resRules.location)); } - if (resRules.resType) { - var newType = util.getMatcherValue(resRules.resType).split(';'); - var type = newType[0]; - newType[0] = (!type || type.indexOf('/') != -1) ? type : mime.lookup(type, type); - util.setHeader(data, 'content-type', newType.join(';')); + if (resRules.resType) { + var newType = util.getMatcherValue(resRules.resType).split(';'); + var type = newType[0]; + newType[0] = (!type || type.indexOf('/') != -1) ? type : mime.lookup(type, type); + util.setHeader(data, 'content-type', newType.join(';')); } - if (resRules.resCharset) { - data.charset = util.getMatcherValue(resRules.resCharset); + if (resRules.resCharset) { + data.charset = util.getMatcherValue(resRules.resCharset); } - var resDelay = util.getMatcherValue(resRules.resDelay); - resDelay = resDelay && parseInt(resDelay, 10); - if (resDelay > 0) { - data.delay = resDelay; + var resDelay = util.getMatcherValue(resRules.resDelay); + resDelay = resDelay && parseInt(resDelay, 10); + if (resDelay > 0) { + data.delay = resDelay; } - var resSpeed = util.getMatcherValue(resRules.resSpeed); - resSpeed = resSpeed && parseFloat(resSpeed); - if (resSpeed > 0) { - data.speed = resSpeed; + var resSpeed = util.getMatcherValue(resRules.resSpeed); + resSpeed = resSpeed && parseFloat(resSpeed); + if (resSpeed > 0) { + data.speed = resSpeed; } - util.readInjectFiles(data, function(data) { - util.getRuleValue([resRules.resBody, resRules.resPrepend, resRules.resAppend, resRules.html, resRules.js, resRules.css], + util.readInjectFiles(data, function(data) { + util.getRuleValue([resRules.resBody, resRules.resPrepend, resRules.resAppend, resRules.html, resRules.js, resRules.css], function(resBody, resPrepend, resAppend, html, js, css) { - if (resBody) { - data.body = resBody; + if (resBody) { + data.body = resBody; } - if (resPrepend) { - data.top = resPrepend; + if (resPrepend) { + data.top = resPrepend; } - if (resAppend) { - data.bottom = util.toBuffer(resAppend); + if (resAppend) { + data.bottom = util.toBuffer(resAppend); } - var headers = _res.headers; - if (data.headers) { - setCookies(headers, data); - var type = data.headers['content-type']; - if (typeof type == 'string') { - if (type.indexOf(';') == -1) { - var origType = headers['content-type']; - if (typeof origType == 'string' && origType.indexOf(';') != -1) { - origType = origType.split(';'); - origType[0] = type; - data.headers['content-type'] = origType.join(';'); + var headers = _res.headers; + if (data.headers) { + setCookies(headers, data); + var type = data.headers['content-type']; + if (typeof type == 'string') { + if (type.indexOf(';') == -1) { + var origType = headers['content-type']; + if (typeof origType == 'string' && origType.indexOf(';') != -1) { + origType = origType.split(';'); + origType[0] = type; + data.headers['content-type'] = origType.join(';'); } } } else { - delete data.headers['content-type']; + delete data.headers['content-type']; } - extend(headers, data.headers); + extend(headers, data.headers); } - if (typeof data.charset == 'string') { - var type = headers['content-type']; - var charset = '; charset=' + data.charset; - if (typeof type == 'string') { - headers['content-type'] = type.split(';')[0] + charset; + if (typeof data.charset == 'string') { + var type = headers['content-type']; + var charset = '; charset=' + data.charset; + if (typeof type == 'string') { + headers['content-type'] = type.split(';')[0] + charset; } else { - headers['content-type'] = charset; + headers['content-type'] = charset; } } else { - delete data.charset; + delete data.charset; } - if (!headers.pragma) { - delete headers.pragma; + if (!headers.pragma) { + delete headers.pragma; } - if (headers.location) { + if (headers.location) { //nodejs的url只支持ascii,对非ascii的字符要encodeURIComponent,否则传到浏览器是乱码 - headers.location = util.encodeNonAsciiChar(headers.location); + headers.location = util.encodeNonAsciiChar(headers.location); } - var speedTransform = data.speed || data.delay ? new SpeedTransform(data) : null; - delete data.headers; - delete data.speed; - delete data.delay; + var speedTransform = data.speed || data.delay ? new SpeedTransform(data) : null; + delete data.headers; + delete data.speed; + delete data.delay; - var type = util.getContentType(headers); - var bottom; - switch(type) { + var type = util.getContentType(headers); + var bottom; + switch(type) { case 'HTML': - if (css) { - bottom = Buffer.concat([STYLE_START, util.toBuffer(css), STYLE_END]); + if (css) { + bottom = Buffer.concat([STYLE_START, util.toBuffer(css), STYLE_END]); } - if (html) { - html = util.toBuffer(html); - bottom = bottom ? Buffer.concat([bottom, html]) : html; + if (html) { + html = util.toBuffer(html); + bottom = bottom ? Buffer.concat([bottom, html]) : html; } - if (js) { - js = Buffer.concat([SCRIPT_START, util.toBuffer(js), SCRIPT_END]); - bottom = bottom ? Buffer.concat([bottom, js]) : js; + if (js) { + js = Buffer.concat([SCRIPT_START, util.toBuffer(js), SCRIPT_END]); + bottom = bottom ? Buffer.concat([bottom, js]) : js; } - break; + break; case 'JS': - bottom = js; - break; + bottom = js; + break; case 'CSS': - bottom = css; - break; + bottom = css; + break; } - if (bottom) { - bottom = util.toBuffer(bottom); - data.bottom = data.bottom ? Buffer.concat([data.bottom, bottom]) : bottom; + if (bottom) { + bottom = util.toBuffer(bottom); + data.bottom = data.bottom ? Buffer.concat([data.bottom, bottom]) : bottom; } - if (!util.isEmptyObject(data)) { - res.addZipTransform(new WhistleTransform(data)); + if (!util.isEmptyObject(data)) { + res.addZipTransform(new WhistleTransform(data)); } - if (util.hasBody(_res)) { - handleReplace(res, replacement); + if (util.hasBody(_res)) { + handleReplace(res, replacement); } //一定放在最后,确保能过滤到动态注入的内容 - if (speedTransform) { - res.add(speedTransform); + if (speedTransform) { + res.add(speedTransform); } - util.drain(req, function() { - util.getFileWriters([util.hasBody(_res) ? getWriterFile(util.getRuleFile(resRules.resWrite), _res.statusCode) : null, + util.drain(req, function() { + util.getFileWriters([util.hasBody(_res) ? getWriterFile(util.getRuleFile(resRules.resWrite), _res.statusCode) : null, getWriterFile(util.getRuleFile(resRules.resWriteRaw), _res.statusCode)], function(writer, rawWriter) { - res.on('src', function(_res) { - if (writer) { - res.addZipTransform(new FileWriterTransform(writer, _res)); + res.on('src', function(_res) { + if (writer) { + res.addZipTransform(new FileWriterTransform(writer, _res)); } - if (rawWriter) { - res.addZipTransform(new FileWriterTransform(rawWriter, _res, true, req)); + if (rawWriter) { + res.addZipTransform(new FileWriterTransform(rawWriter, _res, true, req)); } }); - res.src(_res); - removeDisableProps(req, _res.headers); - if (properties.get('showHostIpInResHeaders')) { - _res.headers['x-host-ip'] = req.hostIp || LOCALHOST; + res.src(_res); + removeDisableProps(req, _res.headers); + if (properties.get('showHostIpInResHeaders')) { + _res.headers['x-host-ip'] = req.hostIp || LOCALHOST; } - if (deleteHeaders) { - Object.keys(deleteHeaders.resHeaders).forEach(function(prop) { - delete _res.headers[prop]; + if (deleteHeaders) { + Object.keys(deleteHeaders.resHeaders).forEach(function(prop) { + delete _res.headers[prop]; }); } - try { - res.writeHead(_res.statusCode, _res.headers); - _res.trailers && res.addTrailers(_res.trailers); + try { + res.writeHead(_res.statusCode, _res.headers); + _res.trailers && res.addTrailers(_res.trailers); } catch(e) { - e._resError = true; - util.emitError(res, e); + e._resError = true; + util.emitError(res, e); } }); }); @@ -601,26 +601,26 @@ module.exports = function(req, res, next) { }); }; - var statusCode = util.getMatcherValue(resRules.statusCode); - var resHeaders = {}; - if (!statusCode && resRules.redirect) { - statusCode = 302; - resHeaders.location = util.getMatcherValue(resRules.redirect); + var statusCode = util.getMatcherValue(resRules.statusCode); + var resHeaders = {}; + if (!statusCode && resRules.redirect) { + statusCode = 302; + resHeaders.location = util.getMatcherValue(resRules.redirect); } - if (statusCode) { - req.hostIp = LOCALHOST; - res.response(util.wrapResponse({ - statusCode: statusCode, - headers: resHeaders + if (statusCode) { + req.hostIp = LOCALHOST; + res.response(util.wrapResponse({ + statusCode: statusCode, + headers: resHeaders })); - return; + return; } - if (resRules.attachment || resRules.resReplace || resRules.resBody || resRules.resPrepend || resRules.resAppend + if (resRules.attachment || resRules.resReplace || resRules.resBody || resRules.resPrepend || resRules.resAppend || resRules.html || resRules.js || resRules.css || resRules.resWrite || resRules.resWriteRaw) { - util.disableReqCache(req.headers); + util.disableReqCache(req.headers); } - next(); + next(); }; \ No newline at end of file diff --git a/lib/inspectors/rules.js b/lib/inspectors/rules.js index 0f426f1aa..5b20a135b 100644 --- a/lib/inspectors/rules.js +++ b/lib/inspectors/rules.js @@ -11,84 +11,84 @@ var index = 0; function resolveRules(req, callback, rules) { - if (!rules) { - return callback(); + if (!rules) { + return callback(); } - var fullUrl = req.fullUrl = util.getFullUrl(req); - req.rules = rules.resolveRules(fullUrl); - util.parseRuleJson(req.rules.urlParams, function(urlParams) { - if (urlParams) { - req.url = util.replaceUrlQueryString(req.url, urlParams); - fullUrl = req.fullUrl = util.getFullUrl(req); - req.rules = rules.resolveRules(fullUrl); + var fullUrl = req.fullUrl = util.getFullUrl(req); + req.rules = rules.resolveRules(fullUrl); + util.parseRuleJson(req.rules.urlParams, function(urlParams) { + if (urlParams) { + req.url = util.replaceUrlQueryString(req.url, urlParams); + fullUrl = req.fullUrl = util.getFullUrl(req); + req.rules = rules.resolveRules(fullUrl); } - util.getRuleValue(req.rules.dispatch, function(dispatchScript) { - if (typeof dispatchScript == 'string' && (dispatchScript = dispatchScript.trim())) { - var qMarkIndex = fullUrl.indexOf('?'); - var params = {}; - var query; - if (qMarkIndex != -1 && (query = fullUrl.substring(qMarkIndex + 1))) { - params = qs.parse(query); + util.getRuleValue(req.rules.dispatch, function(dispatchScript) { + if (typeof dispatchScript == 'string' && (dispatchScript = dispatchScript.trim())) { + var qMarkIndex = fullUrl.indexOf('?'); + var params = {}; + var query; + if (qMarkIndex != -1 && (query = fullUrl.substring(qMarkIndex + 1))) { + params = qs.parse(query); } - var ip = req.clientIp; - var context = { - url: fullUrl, - method: util.toUpperCase(req.method) || 'GET', - httpVersion: req.httpVersion || '1.1', - isLocalAddress: function(_ip) { - return util.isLocalAddress(_ip || ip); + var ip = req.clientIp; + var context = { + url: fullUrl, + method: util.toUpperCase(req.method) || 'GET', + httpVersion: req.httpVersion || '1.1', + isLocalAddress: function(_ip) { + return util.isLocalAddress(_ip || ip); }, - ip: ip, - isWhistleHttps: req.isWhistleHttps, - headers: util.clone(req.headers), - params: params + ip: ip, + isWhistleHttps: req.isWhistleHttps, + headers: util.clone(req.headers), + params: params }; - if (util.execScriptSync(dispatchScript, context)) { - var _url = util.replaceUrlQueryString(req.url, context.params); - if (_url != req.url) { - req.url = _url; - fullUrl = req.fullUrl = util.getFullUrl(req); - req.rules = rules.resolveRules(fullUrl); + if (util.execScriptSync(dispatchScript, context)) { + var _url = util.replaceUrlQueryString(req.url, context.params); + if (_url != req.url) { + req.url = _url; + fullUrl = req.fullUrl = util.getFullUrl(req); + req.rules = rules.resolveRules(fullUrl); } } } - callback(); + callback(); }); }); } module.exports = function(req, res, next) { - req.reqId = ++index; - resolveRules(req, function() { - req.filter = rules.resolveFilter(req.fullUrl); - req.disable = rules.resolveDisable(req.fullUrl); - var _rules = req.rules; - pluginMgr.resolvePluginRule(req); - pluginMgr.getRules(req, function(pluginRules) { - req.pluginRules = pluginRules; - resolveRules(req, function() { - if (pluginRules) { - req.rules = extend(_rules, req.rules); - util.handlePluginRules(req, pluginRules); + req.reqId = ++index; + resolveRules(req, function() { + req.filter = rules.resolveFilter(req.fullUrl); + req.disable = rules.resolveDisable(req.fullUrl); + var _rules = req.rules; + pluginMgr.resolvePluginRule(req); + pluginMgr.getRules(req, function(pluginRules) { + req.pluginRules = pluginRules; + resolveRules(req, function() { + if (pluginRules) { + req.rules = extend(_rules, req.rules); + util.handlePluginRules(req, pluginRules); } - var exportsFile = util.getMatcherValue(req.rules.exportsUrl); - if (exportsFile) { - exportsFile = util.join(req.rules.exportsUrl.root, exportsFile); - fse.ensureFile(exportsFile, function(err) { - if (err) { - return; + var exportsFile = util.getMatcherValue(req.rules.exportsUrl); + if (exportsFile) { + exportsFile = util.join(req.rules.exportsUrl.root, exportsFile); + fse.ensureFile(exportsFile, function(err) { + if (err) { + return; } - fs.writeFile(exportsFile, '\r\n' + req.fullUrl, {flag: 'a'}, util.noop); + fs.writeFile(exportsFile, '\r\n' + req.fullUrl, {flag: 'a'}, util.noop); }); } - rules.findProxyFromPac(req, function() { - req.options = url.parse(util.rule.getUrl(req.rules.rule) || req.fullUrl); - next(); + rules.findProxyFromPac(req, function() { + req.options = url.parse(util.rule.getUrl(req.rules.rule) || req.fullUrl); + next(); }); }, pluginRules); }); diff --git a/lib/inspectors/weinre.js b/lib/inspectors/weinre.js index 18bd31285..a31c26127 100644 --- a/lib/inspectors/weinre.js +++ b/lib/inspectors/weinre.js @@ -2,28 +2,28 @@ var Transform = require('pipestream').Transform; var util = require('../util'); module.exports = function(req, res, next) { - if (req.rules.weinre) { - var localUIHost = this.config.localUIHost; - util.disableReqCache(req.headers); - res.on('src', function(_res) { - if (!util.supportHtmlTransform(_res)) { - return; + if (req.rules.weinre) { + var localUIHost = this.config.localUIHost; + util.disableReqCache(req.headers); + res.on('src', function(_res) { + if (!util.supportHtmlTransform(_res)) { + return; } - util.disableCSP(_res.headers); - var name = util.getPath(util.rule.getMatcher(req.rules.weinre)); - var transform = new Transform(); - transform._transform = function(chunk, encoding, callback) { - if (!chunk) { - chunk = new Buffer('\r\n\r\n'); } - callback(null, chunk); + callback(null, chunk); }; - res.addZipTransform(transform, false, true); + res.addZipTransform(transform, false, true); }); } - next(); + next(); }; \ No newline at end of file diff --git a/lib/plugins/get-plugins-sync.js b/lib/plugins/get-plugins-sync.js index 06cd6481d..e074e3286 100644 --- a/lib/plugins/get-plugins-sync.js +++ b/lib/plugins/get-plugins-sync.js @@ -8,71 +8,71 @@ var mp = require('./module-paths'); var paths = mp.getPaths(); function readPluginMoudlesSync(dir, plugins) { - plugins = plugins || {}; - try { - var list = fs.readdirSync(dir).filter(function(name) { - if (util.isWhistleModule(name)) { - return true; + plugins = plugins || {}; + try { + var list = fs.readdirSync(dir).filter(function(name) { + if (util.isWhistleModule(name)) { + return true; } - if (util.isOrgModule(name)) { - try { - var _dir = path.join(dir, name); - fs.readdirSync(_dir).forEach(function(name) { - if (!plugins[name] && util.isWhistleModule(name)) { - plugins[name] = path.join(_dir, name); + if (util.isOrgModule(name)) { + try { + var _dir = path.join(dir, name); + fs.readdirSync(_dir).forEach(function(name) { + if (!plugins[name] && util.isWhistleModule(name)) { + plugins[name] = path.join(_dir, name); } }); } catch(e) {} } - return false; + return false; }); - list.forEach(function(name) { - if (!plugins[name]) { - plugins[name] = path.join(dir, name); + list.forEach(function(name) { + if (!plugins[name]) { + plugins[name] = path.join(dir, name); } }); } catch(e) {} - return plugins; + return plugins; } module.exports = function() { - var plugins = {}; - paths.forEach(function(dir) { - readPluginMoudlesSync(dir, plugins); + var plugins = {}; + paths.forEach(function(dir) { + readPluginMoudlesSync(dir, plugins); }); - var _plugins = {}; - Object.keys(plugins).forEach(function(name) { - var simpleName = name.split('.')[1]; - if (protocols.contains(simpleName)) { - return; + var _plugins = {}; + Object.keys(plugins).forEach(function(name) { + var simpleName = name.split('.')[1]; + if (protocols.contains(simpleName)) { + return; } - var dir = plugins[name]; - try { - var pkgPath = path.join(dir, 'package.json'); - var pkg = fse.readJsonSync(pkgPath); - if (pkg && pkg.version) { - var stats = fs.statSync(pkgPath); - var plugin = { - moduleName: pkg.name, - path: dir, - pkgPath: pkgPath, - mtime: stats.mtime.getTime(), - version: pkg.version, - description: pkg.description, - homepage: util.getHomePageFromPackage(pkg), - rules: comUtil.trim(comUtil.readFileSync(path.join(dir, 'rules.txt'))), - _rules: comUtil.trim(comUtil.readFileSync(path.join(dir, '_rules.txt'))) + var dir = plugins[name]; + try { + var pkgPath = path.join(dir, 'package.json'); + var pkg = fse.readJsonSync(pkgPath); + if (pkg && pkg.version) { + var stats = fs.statSync(pkgPath); + var plugin = { + moduleName: pkg.name, + path: dir, + pkgPath: pkgPath, + mtime: stats.mtime.getTime(), + version: pkg.version, + description: pkg.description, + homepage: util.getHomePageFromPackage(pkg), + rules: comUtil.trim(comUtil.readFileSync(path.join(dir, 'rules.txt'))), + _rules: comUtil.trim(comUtil.readFileSync(path.join(dir, '_rules.txt'))) }; - _plugins[simpleName + ':'] = plugin; + _plugins[simpleName + ':'] = plugin; } } catch(e) {} }); - return _plugins; + return _plugins; }; diff --git a/lib/plugins/get-plugins.js b/lib/plugins/get-plugins.js index 09199ff82..836f13585 100644 --- a/lib/plugins/get-plugins.js +++ b/lib/plugins/get-plugins.js @@ -6,92 +6,92 @@ var mp = require('./module-paths'); var paths = mp.getPaths(); function readPluginMoudles(dir, callback, plugins) { - fs.readdir(dir, function(err, list) { - plugins = plugins || {}; - if (err) { - return callback(plugins); + fs.readdir(dir, function(err, list) { + plugins = plugins || {}; + if (err) { + return callback(plugins); } - var count = 0; - var callbackHandler = function() { - list.forEach(function(name) { - if (!plugins[name]) { - plugins[name] = path.join(dir, name); + var count = 0; + var callbackHandler = function() { + list.forEach(function(name) { + if (!plugins[name]) { + plugins[name] = path.join(dir, name); } }); - callback(plugins); + callback(plugins); }; - list = list.filter(function(name) { - if (util.isWhistleModule(name)) { - return true; + list = list.filter(function(name) { + if (util.isWhistleModule(name)) { + return true; } - if (util.isOrgModule(name)) { - try { - var _dir = path.join(dir, name); - ++count; - fs.readdir(_dir, function(err, list) { - if (!err) { - list.forEach(function(name) { - if (!plugins[name] && util.isWhistleModule(name)) { - plugins[name] = path.join(_dir, name); + if (util.isOrgModule(name)) { + try { + var _dir = path.join(dir, name); + ++count; + fs.readdir(_dir, function(err, list) { + if (!err) { + list.forEach(function(name) { + if (!plugins[name] && util.isWhistleModule(name)) { + plugins[name] = path.join(_dir, name); } }); } - if (--count <= 0) { - callbackHandler(); + if (--count <= 0) { + callbackHandler(); } }); } catch(e) {} } - return false; + return false; }); - if (!count) { - callbackHandler(); + if (!count) { + callbackHandler(); } }); } module.exports = function(callback) { - var plugins = {}; - var result = {}; - var count = paths.length; - if (!count) { - return callback(result); + var plugins = {}; + var result = {}; + var count = paths.length; + if (!count) { + return callback(result); } - var callbackHandler = function() { - if (--count <= 0) { - callback(result); + var callbackHandler = function() { + if (--count <= 0) { + callback(result); } }; - paths.forEach(function(dir) { - readPluginMoudles(dir, function() { - var list = Object.keys(plugins).filter(function(name) { - return !protocols.contains(name.split('.')[1]); + paths.forEach(function(dir) { + readPluginMoudles(dir, function() { + var list = Object.keys(plugins).filter(function(name) { + return !protocols.contains(name.split('.')[1]); }); - var len = list.length; - list.forEach(function(name) { - var dir = plugins[name]; - var pkgPath = path.join(dir, 'package.json'); - fs.stat(pkgPath, function(err, stats) { - if (stats && stats.mtime) { - result[name.split('.')[1] + ':'] = { - path: dir, - pkgPath: pkgPath, - mtime: stats.mtime.getTime() + var len = list.length; + list.forEach(function(name) { + var dir = plugins[name]; + var pkgPath = path.join(dir, 'package.json'); + fs.stat(pkgPath, function(err, stats) { + if (stats && stats.mtime) { + result[name.split('.')[1] + ':'] = { + path: dir, + pkgPath: pkgPath, + mtime: stats.mtime.getTime() }; } - if (--len <= 0) { - callbackHandler(); + if (--len <= 0) { + callbackHandler(); } }); }); - if (!len) { - callbackHandler(); + if (!len) { + callbackHandler(); } }, plugins); }); diff --git a/lib/plugins/index.js b/lib/plugins/index.js index 4c9e10ae3..79240f60b 100644 --- a/lib/plugins/index.js +++ b/lib/plugins/index.js @@ -38,153 +38,153 @@ var LOCALHOST = '127.0.0.1'; var conf = {}; Object.keys(config).forEach(function(name) { - var value = config[name]; - if (typeof value == 'string' || typeof value == 'number') { - conf[name] = value; + var value = config[name]; + if (typeof value == 'string' || typeof value == 'number') { + conf[name] = value; } }); pluginMgr.on('updateRules', function() { - rulesMgr.clearAppend(); - Object.keys(plugins).sort(function(a, b) { - var p1 = plugins[a]; - var p2 = plugins[b]; - return (p1.mtime > p2.mtime) ? 1 : -1; + rulesMgr.clearAppend(); + Object.keys(plugins).sort(function(a, b) { + var p1 = plugins[a]; + var p2 = plugins[b]; + return (p1.mtime > p2.mtime) ? 1 : -1; }).forEach(function(name) { - if (pluginIsDisabled(name.slice(0, -1))) { - return; + if (pluginIsDisabled(name.slice(0, -1))) { + return; } - var plugin = plugins[name]; - if (plugin._rules && !plugin.rulesMgr) { - plugin.rulesMgr = new RulesMgr(); - plugin.rulesMgr.parse(plugin._rules, plugin.path); + var plugin = plugins[name]; + if (plugin._rules && !plugin.rulesMgr) { + plugin.rulesMgr = new RulesMgr(); + plugin.rulesMgr.parse(plugin._rules, plugin.path); } - plugin.rules && rulesMgr.append(plugin.rules, plugin.path); + plugin.rules && rulesMgr.append(plugin.rules, plugin.path); }); }); pluginMgr.emit('updateRules'); pluginMgr.updateRules = function() { - pluginMgr.emit('updateRules'); + pluginMgr.emit('updateRules'); }; pluginMgr.on('update', function(result) { - Object.keys(result).forEach(function(name) { - pluginMgr.stopPlugin(result[name]); + Object.keys(result).forEach(function(name) { + pluginMgr.stopPlugin(result[name]); }); }); pluginMgr.on('uninstall', function(result) { - Object.keys(result).forEach(function(name) { - pluginMgr.stopPlugin(result[name]); + Object.keys(result).forEach(function(name) { + pluginMgr.stopPlugin(result[name]); }); }); function showVerbose(oldData, newData) { - if (!config.debugMode) { - return; + if (!config.debugMode) { + return; } - var uninstallData, installData, updateData; - Object.keys(oldData).forEach(function(name) { - var oldItem = oldData[name]; - var newItem = newData[name]; - if (!newItem) { - uninstallData = uninstallData || {}; - uninstallData[name] = oldItem; + var uninstallData, installData, updateData; + Object.keys(oldData).forEach(function(name) { + var oldItem = oldData[name]; + var newItem = newData[name]; + if (!newItem) { + uninstallData = uninstallData || {}; + uninstallData[name] = oldItem; } else if (newItem.path != oldItem.path || newItem.mtime != oldItem.mtime) { - updateData = updateData || {}; - updateData[name] = newItem; + updateData = updateData || {}; + updateData[name] = newItem; } }); - Object.keys(newData).forEach(function(name) { - if (!oldData[name]) { - installData = installData || {}; - installData[name] = newData[name]; + Object.keys(newData).forEach(function(name) { + if (!oldData[name]) { + installData = installData || {}; + installData[name] = newData[name]; } }); - if (uninstallData || installData || updateData) { - console.log('\n***********[%s] %s has changed***********', comUtil.formatDate(), 'plugins'); + if (uninstallData || installData || updateData) { + console.log('\n***********[%s] %s has changed***********', comUtil.formatDate(), 'plugins'); } - uninstallData && Object.keys(uninstallData).forEach(function(name) { - console.log(colors.red('[' + comUtil.formatDate(new Date(uninstallData[name].mtime)) + '] [uninstall plugin] ' + name.slice(0, -1))); + uninstallData && Object.keys(uninstallData).forEach(function(name) { + console.log(colors.red('[' + comUtil.formatDate(new Date(uninstallData[name].mtime)) + '] [uninstall plugin] ' + name.slice(0, -1))); }); - installData && Object.keys(installData).forEach(function(name) { - console.log(colors.green('[' + comUtil.formatDate(new Date(installData[name].mtime)) + '] [install plugin] ' + name.slice(0, -1))); + installData && Object.keys(installData).forEach(function(name) { + console.log(colors.green('[' + comUtil.formatDate(new Date(installData[name].mtime)) + '] [install plugin] ' + name.slice(0, -1))); }); - updateData && Object.keys(updateData).forEach(function(name) { - console.log(colors.yellow('[' + comUtil.formatDate(new Date(updateData[name].mtime)) + '] [update plugin] ' + name.slice(0, -1))); + updateData && Object.keys(updateData).forEach(function(name) { + console.log(colors.yellow('[' + comUtil.formatDate(new Date(updateData[name].mtime)) + '] [update plugin] ' + name.slice(0, -1))); }); } function readPackages(obj, callback) { - var _plugins = {}; - var count = 0; - var callbackHandler = function() { - if (--count <= 0) { - callback(_plugins); + var _plugins = {}; + var count = 0; + var callbackHandler = function() { + if (--count <= 0) { + callback(_plugins); } }; - Object.keys(obj).forEach(function(name) { - var pkg = plugins[name]; - var newPkg = obj[name]; - if (!pkg || pkg.path != newPkg.path || pkg.mtime != newPkg.mtime) { - ++count; - fse.readJson(newPkg.pkgPath, function(err, pkg) { - if (pkg && pkg.version) { - newPkg.version = pkg.version; - newPkg.homepage = util.getHomePageFromPackage(pkg); - newPkg.description = pkg.description; - newPkg.moduleName = pkg.name; - _plugins[name] = newPkg; - fs.readFile(path.join(path.join(newPkg.path, 'rules.txt')), UTF8_OPTIONS, function(err, rulesText) { - newPkg.rules = comUtil.trim(rulesText); - fs.readFile(path.join(path.join(newPkg.path, '_rules.txt')), UTF8_OPTIONS, function(err, rulesText) { - newPkg._rules = comUtil.trim(rulesText); - callbackHandler(); + Object.keys(obj).forEach(function(name) { + var pkg = plugins[name]; + var newPkg = obj[name]; + if (!pkg || pkg.path != newPkg.path || pkg.mtime != newPkg.mtime) { + ++count; + fse.readJson(newPkg.pkgPath, function(err, pkg) { + if (pkg && pkg.version) { + newPkg.version = pkg.version; + newPkg.homepage = util.getHomePageFromPackage(pkg); + newPkg.description = pkg.description; + newPkg.moduleName = pkg.name; + _plugins[name] = newPkg; + fs.readFile(path.join(path.join(newPkg.path, 'rules.txt')), UTF8_OPTIONS, function(err, rulesText) { + newPkg.rules = comUtil.trim(rulesText); + fs.readFile(path.join(path.join(newPkg.path, '_rules.txt')), UTF8_OPTIONS, function(err, rulesText) { + newPkg._rules = comUtil.trim(rulesText); + callbackHandler(); }); }); } else { - callbackHandler(); + callbackHandler(); } }); } else { - _plugins[name] = pkg; + _plugins[name] = pkg; } }); - if (count <= 0) { - callback(_plugins); + if (count <= 0) { + callback(_plugins); } } (function update() { - setTimeout(function() { - getPlugin(function(result) { - readPackages(result, function(_plugins) { - var updatePlugins, uninstallPlugins; - Object.keys(plugins).forEach(function(name) { - var plugin = plugins[name]; - var newPlugin = _plugins[name]; - if (!newPlugin) { - uninstallPlugins = uninstallPlugins || {}; - uninstallPlugins[name] = plugin; + setTimeout(function() { + getPlugin(function(result) { + readPackages(result, function(_plugins) { + var updatePlugins, uninstallPlugins; + Object.keys(plugins).forEach(function(name) { + var plugin = plugins[name]; + var newPlugin = _plugins[name]; + if (!newPlugin) { + uninstallPlugins = uninstallPlugins || {}; + uninstallPlugins[name] = plugin; } else if (newPlugin.path != plugin.path || newPlugin.mtime != plugin.mtime) { - updatePlugins = updatePlugins || {}; - updatePlugins[name] = newPlugin; + updatePlugins = updatePlugins || {}; + updatePlugins[name] = newPlugin; } }); - showVerbose(plugins, _plugins); - plugins = _plugins; - if (uninstallPlugins || updatePlugins) { - uninstallPlugins && pluginMgr.emit('uninstall', uninstallPlugins); - updatePlugins && pluginMgr.emit('update', updatePlugins); - pluginMgr.emit('updateRules'); + showVerbose(plugins, _plugins); + plugins = _plugins; + if (uninstallPlugins || updatePlugins) { + uninstallPlugins && pluginMgr.emit('uninstall', uninstallPlugins); + updatePlugins && pluginMgr.emit('update', updatePlugins); + pluginMgr.emit('updateRules'); } - update(); + update(); }); }); }, INTERVAL); @@ -204,40 +204,40 @@ pluginMgr.STATUS_CODE_HEADER = STATUS_CODE_HEADER; pluginMgr.LOCAL_HOST_HEADER = LOCAL_HOST_HEADER; function loadPlugin(plugin, callback) { - p.fork({ - name: plugin.moduleName, - script: PLUGIN_MAIN, - value: plugin.path, - RULE_VALUE_HEADER: RULE_VALUE_HEADER, - SSL_FLAG_HEADER: SSL_FLAG_HEADER, - FULL_URL_HEADER: FULL_URL_HEADER, - REAL_URL_HEADER: REAL_URL_HEADER, - NEXT_RULE_HEADER: NEXT_RULE_HEADER, - CUR_RULE_HEADER: CUR_RULE_HEADER, - REQ_ID_HEADER: REQ_ID_HEADER, - DATA_ID_HEADER: DATA_ID_HEADER, - STATUS_CODE_HEADER: STATUS_CODE_HEADER, - LOCAL_HOST_HEADER: LOCAL_HOST_HEADER, - METHOD_HEADER: METHOD_HEADER, - CLIENT_IP_HEADER: CLIENT_IP_HEADER, - debugMode: config.debugMode, - config: conf + p.fork({ + name: plugin.moduleName, + script: PLUGIN_MAIN, + value: plugin.path, + RULE_VALUE_HEADER: RULE_VALUE_HEADER, + SSL_FLAG_HEADER: SSL_FLAG_HEADER, + FULL_URL_HEADER: FULL_URL_HEADER, + REAL_URL_HEADER: REAL_URL_HEADER, + NEXT_RULE_HEADER: NEXT_RULE_HEADER, + CUR_RULE_HEADER: CUR_RULE_HEADER, + REQ_ID_HEADER: REQ_ID_HEADER, + DATA_ID_HEADER: DATA_ID_HEADER, + STATUS_CODE_HEADER: STATUS_CODE_HEADER, + LOCAL_HOST_HEADER: LOCAL_HOST_HEADER, + METHOD_HEADER: METHOD_HEADER, + CLIENT_IP_HEADER: CLIENT_IP_HEADER, + debugMode: config.debugMode, + config: conf }, function(err, ports, child) { - callback && callback(err, ports, child); - logger.error(err); - if (config.debugMode) { - if (err) { - console.log(colors.red(err)); + callback && callback(err, ports, child); + logger.error(err); + if (config.debugMode) { + if (err) { + console.log(colors.red(err)); } else if (!child.debugMode) { - child.debugMode = true; - child.on('data', function(data) { - if (data && data.type == 'console.log') { - console.log('[' + comUtil.formatDate() + '] [plugin] [' + plugin.path.substring(plugin.path.lastIndexOf('.') + 1) + ']', data.message); + child.debugMode = true; + child.on('data', function(data) { + if (data && data.type == 'console.log') { + console.log('[' + comUtil.formatDate() + '] [plugin] [' + plugin.path.substring(plugin.path.lastIndexOf('.') + 1) + ']', data.message); } }); - child.sendData({ - type: 'console.log', - status: 'ready' + child.sendData({ + type: 'console.log', + status: 'ready' }); } } @@ -247,22 +247,22 @@ function loadPlugin(plugin, callback) { pluginMgr.loadPlugin = loadPlugin; pluginMgr.stopPlugin = function(plugin) { - p.kill({ - script: PLUGIN_MAIN, - value: plugin.path + p.kill({ + script: PLUGIN_MAIN, + value: plugin.path }, 10000); }; pluginMgr.getPlugins = function() { - return plugins; + return plugins; }; function pluginIsDisabled(name) { - if (properties.get('disabledAllPlugins')) { - return true; + if (properties.get('disabledAllPlugins')) { + return true; } - var disabledPlugins = properties.get('disabledPlugins') || {}; - return disabledPlugins[name]; + var disabledPlugins = properties.get('disabledPlugins') || {}; + return disabledPlugins[name]; } function _getPlugin(protocol) { @@ -272,21 +272,21 @@ function _getPlugin(protocol) { pluginMgr.getPlugin = _getPlugin; function getPluginByRuleUrl(ruleUrl) { - if (!ruleUrl || typeof ruleUrl != 'string') { - return; + if (!ruleUrl || typeof ruleUrl != 'string') { + return; } - var index = ruleUrl.indexOf(':'); - if (index == -1) { - return null; + var index = ruleUrl.indexOf(':'); + if (index == -1) { + return null; } - var protocol = ruleUrl.substring(0, index + 1); - return pluginIsDisabled(protocol.slice(0, -1)) ? null : plugins[protocol]; + var protocol = ruleUrl.substring(0, index + 1); + return pluginIsDisabled(protocol.slice(0, -1)) ? null : plugins[protocol]; } pluginMgr.getPluginByRuleUrl = getPluginByRuleUrl; pluginMgr.getPluginByHomePage = function(url) { - return PLUGIN_URL_RE.test(url) + return PLUGIN_URL_RE.test(url) && plugins[RegExp.$1 + ':']; }; @@ -310,34 +310,34 @@ function rulesToJson(body) { } function getRules(req, port, callback) { - if (!port) { - return callback(); + if (!port) { + return callback(); } - var rules = req.rules; - var options = url.parse(req.fullUrl); + var rules = req.rules; + var options = url.parse(req.fullUrl); options.headers = extend({}, req.headers); if (req.reqId) { - options.headers[REQ_ID_HEADER] = req.reqId; + options.headers[REQ_ID_HEADER] = req.reqId; } options.headers[FULL_URL_HEADER] = encodeURIComponent(req.fullUrl); options.headers[METHOD_HEADER] = encodeURIComponent(req.method || 'GET'); var nextRule = rulesMgr.resolveRule(req.fullUrl, 1); if (nextRule) { - options.headers[NEXT_RULE_HEADER] = encodeURIComponent(nextRule.rawPattern + ' ' + nextRule.matcher); + options.headers[NEXT_RULE_HEADER] = encodeURIComponent(nextRule.rawPattern + ' ' + nextRule.matcher); } var localHost = rules.host; if (localHost) { - options.headers[LOCAL_HOST_HEADER] = encodeURIComponent(comUtil.removeProtocol(localHost.matcher, true) + (localHost.port ? ':' + localHost.port : '')); + options.headers[LOCAL_HOST_HEADER] = encodeURIComponent(comUtil.removeProtocol(localHost.matcher, true) + (localHost.port ? ':' + localHost.port : '')); } if (rules.rule) { options.headers[CUR_RULE_HEADER] = encodeURIComponent(rules.rule.rawPattern + ' ' + rules.rule.matcher); } if (options.protocol == 'https:' || options.protocol == 'wss:') { - options.headers[SSL_FLAG_HEADER] = 'true'; + options.headers[SSL_FLAG_HEADER] = 'true'; } if (typeof req.clientIp == 'string') { - options.headers[CLIENT_IP_HEADER] = encodeURIComponent(req.clientIp); + options.headers[CLIENT_IP_HEADER] = encodeURIComponent(req.clientIp); } options.protocol = 'http:'; @@ -346,7 +346,7 @@ function getRules(req, port, callback) { options.hostname = null; var ruleValue = req.ruleValue || comUtil.getMatcherValue(req.rules.rule); if (ruleValue) { - options.headers[RULE_VALUE_HEADER] = encodeURIComponent(ruleValue); + options.headers[RULE_VALUE_HEADER] = encodeURIComponent(ruleValue); } delete options.headers.upgrade; delete options.headers.connection; @@ -354,29 +354,29 @@ function getRules(req, port, callback) { } pluginMgr.getRules = function(req, callback) { - var plugin = req.pluginMgr; - if (!plugin) { - return callback(); + var plugin = req.pluginMgr; + if (!plugin) { + return callback(); } - var retryCount = 0; - (function getRulesMgr() { - loadPlugin(plugin, function(err, ports) { - plugin.ports = ports; - getRules(req, ports && ports.rulesPort, function(err, body, values, raw) { - if (retryCount++ < 5 && err) { - setTimeout(getRulesMgr, 60); - return; + var retryCount = 0; + (function getRulesMgr() { + loadPlugin(plugin, function(err, ports) { + plugin.ports = ports; + getRules(req, ports && ports.rulesPort, function(err, body, values, raw) { + if (retryCount++ < 5 && err) { + setTimeout(getRulesMgr, 60); + return; } - if (err || !body) { - callback(plugin.rulesMgr); + if (err || !body) { + callback(plugin.rulesMgr); } else { - if (raw != plugin.__rules) { - var rulesMgr = new RulesMgr(values); - rulesMgr.parse(body + (plugin._rules ? '\n' + plugin._rules : ''), plugin.path); - plugin._rulesMgr = rulesMgr; - plugin.__rules = raw; + if (raw != plugin.__rules) { + var rulesMgr = new RulesMgr(values); + rulesMgr.parse(body + (plugin._rules ? '\n' + plugin._rules : ''), plugin.path); + plugin._rulesMgr = rulesMgr; + plugin.__rules = raw; } - callback(plugin._rulesMgr); + callback(plugin._rulesMgr); } }); }); @@ -385,71 +385,71 @@ pluginMgr.getRules = function(req, callback) { }; function getResRules(req, res, port, callback) { - if (!port) { - return callback(); + if (!port) { + return callback(); } - var options = url.parse(req.fullUrl); - options.headers = extend({}, res.headers); - options.headers[FULL_URL_HEADER] = encodeURIComponent(req.fullUrl); - if (req.realUrl) { - options.headers[REAL_URL_HEADER] = encodeURIComponent(req.realUrl); - } - if (req.reqId) { - options.headers[REQ_ID_HEADER] = req.reqId; - } - if (req.dataId) { - options.headers[DATA_ID_HEADER] = req.dataId; - } - if (typeof req.clientIp == 'string') { - options.headers[CLIENT_IP_HEADER] = encodeURIComponent(req.clientIp); - } + var options = url.parse(req.fullUrl); + options.headers = extend({}, res.headers); + options.headers[FULL_URL_HEADER] = encodeURIComponent(req.fullUrl); + if (req.realUrl) { + options.headers[REAL_URL_HEADER] = encodeURIComponent(req.realUrl); + } + if (req.reqId) { + options.headers[REQ_ID_HEADER] = req.reqId; + } + if (req.dataId) { + options.headers[DATA_ID_HEADER] = req.dataId; + } + if (typeof req.clientIp == 'string') { + options.headers[CLIENT_IP_HEADER] = encodeURIComponent(req.clientIp); + } - options.headers.host = req.headers.host; - options.headers[METHOD_HEADER] = encodeURIComponent(req.method || 'GET'); - options.headers[LOCAL_HOST_HEADER] = encodeURIComponent(req.hostIp || LOCALHOST); - options.headers[STATUS_CODE_HEADER] = encodeURIComponent(res.statusCode == null ? '' : res.statusCode + ''); - if (options.protocol == 'https:' || options.protocol == 'wss:') { - options.headers[SSL_FLAG_HEADER] = 'true'; - } + options.headers.host = req.headers.host; + options.headers[METHOD_HEADER] = encodeURIComponent(req.method || 'GET'); + options.headers[LOCAL_HOST_HEADER] = encodeURIComponent(req.hostIp || LOCALHOST); + options.headers[STATUS_CODE_HEADER] = encodeURIComponent(res.statusCode == null ? '' : res.statusCode + ''); + if (options.protocol == 'https:' || options.protocol == 'wss:') { + options.headers[SSL_FLAG_HEADER] = 'true'; + } - options.protocol = 'http:'; - options.host = LOCALHOST; - options.port = port; - options.hostname = null; - var ruleValue = req.ruleValue || comUtil.getMatcherValue(req.rules.rule); - if (ruleValue) { - options.headers[RULE_VALUE_HEADER] = encodeURIComponent(ruleValue); - } - delete options.headers.upgrade; - delete options.headers.connection; - requestRules(options, callback); + options.protocol = 'http:'; + options.host = LOCALHOST; + options.port = port; + options.hostname = null; + var ruleValue = req.ruleValue || comUtil.getMatcherValue(req.rules.rule); + if (ruleValue) { + options.headers[RULE_VALUE_HEADER] = encodeURIComponent(ruleValue); + } + delete options.headers.upgrade; + delete options.headers.connection; + requestRules(options, callback); } pluginMgr.getResRules = function(req, res, callback) { - var plugin = req.pluginMgr; - if (!plugin) { - return callback(); + var plugin = req.pluginMgr; + if (!plugin) { + return callback(); } - var retryCount = 0; - (function getRulesMgr() { - loadPlugin(plugin, function(err, ports) { - getResRules(req, res, ports && ports.resRulesPort, function(err, body, values, raw) { - if (retryCount++ < 5 && err) { - setTimeout(getRulesMgr, 60); - return; + var retryCount = 0; + (function getRulesMgr() { + loadPlugin(plugin, function(err, ports) { + getResRules(req, res, ports && ports.resRulesPort, function(err, body, values, raw) { + if (retryCount++ < 5 && err) { + setTimeout(getRulesMgr, 60); + return; } - if (err || !body) { - callback(plugin.rulesMgr); + if (err || !body) { + callback(plugin.rulesMgr); } else { - if (raw != plugin.__resRules) { - var rulesMgr = new RulesMgr(values); - rulesMgr.parse(body, plugin.path); - plugin._resRulesMgr = rulesMgr; - plugin.__resRules = raw; + if (raw != plugin.__resRules) { + var rulesMgr = new RulesMgr(values); + rulesMgr.parse(body, plugin.path); + plugin._resRulesMgr = rulesMgr; + plugin.__resRules = raw; } - callback(plugin._resRulesMgr); + callback(plugin._resRulesMgr); } }); }); @@ -458,54 +458,54 @@ pluginMgr.getResRules = function(req, res, callback) { function postStatus(plugin, data) { - if (!plugin) { - return; + if (!plugin) { + return; } - var retryCount = 0; - data = JSON.stringify(data); - function sendStatus() { - loadPlugin(plugin, function(err, ports) { - var port = ports && ports.statusPort; - if (port) { - var request = http.request({ - host: '127.0.0.1', - port: port, - method: 'POST' + var retryCount = 0; + data = JSON.stringify(data); + function sendStatus() { + loadPlugin(plugin, function(err, ports) { + var port = ports && ports.statusPort; + if (port) { + var request = http.request({ + host: '127.0.0.1', + port: port, + method: 'POST' }, function(response) { - response.on('error', errorHandler); + response.on('error', errorHandler); }); - request.on('error', errorHandler); - request.end(data); + request.on('error', errorHandler); + request.end(data); } }); } - function errorHandler() { - retryCount++ < 5 && setTimeout(sendStatus, 60); + function errorHandler() { + retryCount++ < 5 && setTimeout(sendStatus, 60); } - sendStatus(); + sendStatus(); } pluginMgr.postStatus = postStatus; function getTunnelRules(req, port, callback) { - if (!port) { - return callback(); + if (!port) { + return callback(); } - var options = { - host: '127.0.0.1', - port: port, - headers: req.headers + var options = { + host: '127.0.0.1', + port: port, + headers: req.headers }; - if (req.reqId) { - options.headers[REQ_ID_HEADER] = req.reqId; - } - var rules = req.rules; - var ruleValue = req.ruleValue || comUtil.getMatcherValue(rules.rule); + if (req.reqId) { + options.headers[REQ_ID_HEADER] = req.reqId; +} + var rules = req.rules; + var ruleValue = req.ruleValue || comUtil.getMatcherValue(rules.rule); if (ruleValue) { - options.headers[RULE_VALUE_HEADER] = encodeURIComponent(ruleValue); + options.headers[RULE_VALUE_HEADER] = encodeURIComponent(ruleValue); } if (rules.rule) { options.headers[CUR_RULE_HEADER] = encodeURIComponent(rules.rule.rawPattern + ' ' + rules.rule.matcher); @@ -515,36 +515,36 @@ function getTunnelRules(req, port, callback) { options.headers[LOCAL_HOST_HEADER] = encodeURIComponent(comUtil.removeProtocol(localHost.matcher, true) + (localHost.port ? ':' + localHost.port : '')); } if (typeof req.clientIp == 'string') { - options.headers[CLIENT_IP_HEADER] = encodeURIComponent(req.clientIp); + options.headers[CLIENT_IP_HEADER] = encodeURIComponent(req.clientIp); } requestRules(options, callback); } pluginMgr.getTunnelRules = function(req, callback) { - var plugin = req.pluginMgr; - if (!plugin) { - return callback(); + var plugin = req.pluginMgr; + if (!plugin) { + return callback(); } - var retryCount = 0; - (function getTunnelRulesMgr() { - loadPlugin(plugin, function(err, ports) { - plugin.ports = ports; - getTunnelRules(req, ports && ports.tunnelRulesPort, function(err, body, values, raw) { - if (retryCount++ < 5 && err) { - setTimeout(getTunnelRulesMgr, 60); - return; + var retryCount = 0; + (function getTunnelRulesMgr() { + loadPlugin(plugin, function(err, ports) { + plugin.ports = ports; + getTunnelRules(req, ports && ports.tunnelRulesPort, function(err, body, values, raw) { + if (retryCount++ < 5 && err) { + setTimeout(getTunnelRulesMgr, 60); + return; } - if (err || !body) { - callback(null); + if (err || !body) { + callback(null); } else { - if (raw != plugin.__tunnelRules) { - var rulesMgr = new RulesMgr(values); - rulesMgr.parse(body + (plugin._rules ? '\n' + plugin._rules : ''), plugin.path); - plugin._tunnelRulesMgr = rulesMgr; - plugin.__tunnelRules = raw; + if (raw != plugin.__tunnelRules) { + var rulesMgr = new RulesMgr(values); + rulesMgr.parse(body + (plugin._rules ? '\n' + plugin._rules : ''), plugin.path); + plugin._tunnelRulesMgr = rulesMgr; + plugin.__tunnelRules = raw; } - callback(plugin._tunnelRulesMgr); + callback(plugin._tunnelRulesMgr); } }); }); diff --git a/lib/plugins/load-plugin.js b/lib/plugins/load-plugin.js index 1fd272a45..ba9a64cbe 100644 --- a/lib/plugins/load-plugin.js +++ b/lib/plugins/load-plugin.js @@ -7,131 +7,131 @@ var MAX_PORT = 60000; var curPort = 45000; function getServer(callback) { - if (curPort > MAX_PORT) { - curPort = 40000; + if (curPort > MAX_PORT) { + curPort = 40000; } - var server = http.createServer(); - var port = curPort++; - var next = function() { - getServer(callback); + var server = http.createServer(); + var port = curPort++; + var next = function() { + getServer(callback); }; - server.on('error', next); - server.listen(port, function() { - server.removeListener('error', next); - callback(server, port); + server.on('error', next); + server.listen(port, function() { + server.removeListener('error', next); + callback(server, port); }); } module.exports = function(options, callback) { - options.getRootCAFile = ca.getRootCAFile; - options.createCertificate = ca.createCertificate; - options.storage = new Storage(path.join(options.config.DATA_DIR, '.plugins', options.name)); - if (options.debugMode) { - var cacheLogs = []; - console.log = function() { - var msg = util.format.apply(this, arguments); - if (cacheLogs) { - cacheLogs.push(msg); + options.getRootCAFile = ca.getRootCAFile; + options.createCertificate = ca.createCertificate; + options.storage = new Storage(path.join(options.config.DATA_DIR, '.plugins', options.name)); + if (options.debugMode) { + var cacheLogs = []; + console.log = function() { + var msg = util.format.apply(this, arguments); + if (cacheLogs) { + cacheLogs.push(msg); } else { - process.sendData({ - type: 'console.log', - message: msg + process.sendData({ + type: 'console.log', + message: msg }); } }; - process.on('data', function(data) { - if (cacheLogs && data && data.type == 'console.log' && data.status == 'ready') { - var _cacheLogs = cacheLogs; - cacheLogs = null; - _cacheLogs.forEach(function(msg) { - process.sendData({ - type: 'console.log', - message: msg + process.on('data', function(data) { + if (cacheLogs && data && data.type == 'console.log' && data.status == 'ready') { + var _cacheLogs = cacheLogs; + cacheLogs = null; + _cacheLogs.forEach(function(msg) { + process.sendData({ + type: 'console.log', + message: msg }); }); } }); } - var execPlugin = require(options.value); - var port, uiPort, rulesPort, resRulesPort, statusPort, tunnelRulesPort, tunnelPort; - var count = 0; - var callbackHandler = function() { - if (--count <= 0) { - callback(null, { - port: port, - uiPort: uiPort, - rulesPort: rulesPort, - resRulesPort: resRulesPort, - statusPort: statusPort, - tunnelRulesPort: tunnelRulesPort, - tunnelPort: tunnelPort + var execPlugin = require(options.value); + var port, uiPort, rulesPort, resRulesPort, statusPort, tunnelRulesPort, tunnelPort; + var count = 0; + var callbackHandler = function() { + if (--count <= 0) { + callback(null, { + port: port, + uiPort: uiPort, + rulesPort: rulesPort, + resRulesPort: resRulesPort, + statusPort: statusPort, + tunnelRulesPort: tunnelRulesPort, + tunnelPort: tunnelPort }); } }; - var startServer = execPlugin.pluginServer || execPlugin.server || execPlugin; - if (typeof startServer == 'function') { - ++count; - getServer(function(server, _port) { - startServer(server, options); - port = _port; - callbackHandler(); + var startServer = execPlugin.pluginServer || execPlugin.server || execPlugin; + if (typeof startServer == 'function') { + ++count; + getServer(function(server, _port) { + startServer(server, options); + port = _port; + callbackHandler(); }); } - var startUIServer = execPlugin.uiServer || execPlugin.innerServer || execPlugin.internalServer; - if (typeof startUIServer == 'function') { - ++count; - getServer(function(server, _port) { - startUIServer(server, options); - uiPort = _port; - callbackHandler(); + var startUIServer = execPlugin.uiServer || execPlugin.innerServer || execPlugin.internalServer; + if (typeof startUIServer == 'function') { + ++count; + getServer(function(server, _port) { + startUIServer(server, options); + uiPort = _port; + callbackHandler(); }); } - var startRulesServer = execPlugin.pluginRulesServer || execPlugin.rulesServer || execPlugin.reqRulesServer; - if (typeof startRulesServer == 'function') { - ++count; - getServer(function(server, _port) { - startRulesServer(server, options); - rulesPort = _port; - callbackHandler(); + var startRulesServer = execPlugin.pluginRulesServer || execPlugin.rulesServer || execPlugin.reqRulesServer; + if (typeof startRulesServer == 'function') { + ++count; + getServer(function(server, _port) { + startRulesServer(server, options); + rulesPort = _port; + callbackHandler(); }); } - var startResRulesServer = execPlugin.resRulesServer; - if (typeof startResRulesServer == 'function') { - ++count; - getServer(function(server, _port) { - startResRulesServer(server, options); - resRulesPort = _port; - callbackHandler(); + var startResRulesServer = execPlugin.resRulesServer; + if (typeof startResRulesServer == 'function') { + ++count; + getServer(function(server, _port) { + startResRulesServer(server, options); + resRulesPort = _port; + callbackHandler(); }); } - var startStatusServer = execPlugin.statusServer || execPlugin.stateServer; - if (typeof startStatusServer == 'function') { - ++count; - getServer(function(server, _port) { - startStatusServer(server, options); - statusPort = _port; - callbackHandler(); + var startStatusServer = execPlugin.statusServer || execPlugin.stateServer; + if (typeof startStatusServer == 'function') { + ++count; + getServer(function(server, _port) { + startStatusServer(server, options); + statusPort = _port; + callbackHandler(); }); } - var startTunnelRulesServer = execPlugin.pluginRulesServer || execPlugin.tunnelRulesServer; - if (typeof startTunnelRulesServer == 'function') { - ++count; - getServer(function(server, _port) { - startTunnelRulesServer(server, options); - tunnelRulesPort = _port; - callbackHandler(); + var startTunnelRulesServer = execPlugin.pluginRulesServer || execPlugin.tunnelRulesServer; + if (typeof startTunnelRulesServer == 'function') { + ++count; + getServer(function(server, _port) { + startTunnelRulesServer(server, options); + tunnelRulesPort = _port; + callbackHandler(); }); } - var startTunnelServer = execPlugin.pluginServer || execPlugin.tunnelServer || execPlugin.connectServer; + var startTunnelServer = execPlugin.pluginServer || execPlugin.tunnelServer || execPlugin.connectServer; if (typeof startTunnelServer == 'function') { ++count; getServer(function(server, _port) { @@ -141,8 +141,8 @@ module.exports = function(options, callback) { }); } - if (!count) { - callbackHandler(); + if (!count) { + callbackHandler(); } }; diff --git a/lib/plugins/module-paths.js b/lib/plugins/module-paths.js index 39b17e64f..dcc12f6e3 100644 --- a/lib/plugins/module-paths.js +++ b/lib/plugins/module-paths.js @@ -6,48 +6,48 @@ var appDataDir = formatPath(process.env && process.env.APPDATA); var pluginsPath = formatPath(path.join(config.DATA_DIR, 'node_modules')); if (paths.indexOf(pluginsPath) == -1) { - paths.unshift(pluginsPath); + paths.unshift(pluginsPath); } pluginsPath = formatPath(process.env && process.env.WHISTLE_PLUGINS_PATH); if (pluginsPath) { - pluginsPath = path.join(pluginsPath, 'node_modules'); - paths.indexOf(pluginsPath) == -1 && paths.unshift(pluginsPath); + pluginsPath = path.join(pluginsPath, 'node_modules'); + paths.indexOf(pluginsPath) == -1 && paths.unshift(pluginsPath); } if (appDataDir) { - appDataDir = path.join(appDataDir, 'npm/node_modules'); - paths.indexOf(appDataDir) == -1 && paths.push(appDataDir); + appDataDir = path.join(appDataDir, 'npm/node_modules'); + paths.indexOf(appDataDir) == -1 && paths.push(appDataDir); } if (globalDir && paths.indexOf(globalDir) == -1) { - paths.push(globalDir); + paths.push(globalDir); } function formatPath(path) { - return typeof path == 'string' ? path.replace(/\\/g, '/') : null; + return typeof path == 'string' ? path.replace(/\\/g, '/') : null; } function getGlobalDir() { - var globalPrefix; - if (process.env.PREFIX) { - globalPrefix = process.env.PREFIX; + var globalPrefix; + if (process.env.PREFIX) { + globalPrefix = process.env.PREFIX; } else if (process.platform === 'win32') { - globalPrefix = path.dirname(process.execPath); + globalPrefix = path.dirname(process.execPath); } else { - globalPrefix = path.dirname(path.dirname(process.execPath)); - if (process.env.DESTDIR) { - globalPrefix = path.join(process.env.DESTDIR, globalPrefix); + globalPrefix = path.dirname(path.dirname(process.execPath)); + if (process.env.DESTDIR) { + globalPrefix = path.join(process.env.DESTDIR, globalPrefix); } } - if (typeof globalPrefix == 'string') { - return (process.platform !== 'win32') + if (typeof globalPrefix == 'string') { + return (process.platform !== 'win32') ? path.resolve(globalPrefix, 'lib', 'node_modules') : path.resolve(globalPrefix, 'node_modules'); } } exports.getPaths = function() { - return paths; + return paths; }; diff --git a/lib/plugins/util.js b/lib/plugins/util.js index 28e8e27fb..7faac9d80 100644 --- a/lib/plugins/util.js +++ b/lib/plugins/util.js @@ -3,37 +3,37 @@ var WHISLTE_PLUGIN_RE = /^whistle\.[a-z\d_\-]+$/; var HTTP_RE = /^https?:\/\//i; function isOrgModule(name) { - return ORG_RE.test(name); + return ORG_RE.test(name); } exports.isOrgModule = isOrgModule; function isWhistleModule(name) { - return WHISLTE_PLUGIN_RE.test(name); + return WHISLTE_PLUGIN_RE.test(name); } exports.isWhistleModule = isWhistleModule; function getHomePageFromPackage(pkg) { - if (HTTP_RE.test(pkg.homepage)) { - return pkg.homepage; + if (HTTP_RE.test(pkg.homepage)) { + return pkg.homepage; } - return extractUrl(pkg.repository) || ''; + return extractUrl(pkg.repository) || ''; } function extractUrl(repository) { - if (!repository || repository.type != 'git' + if (!repository || repository.type != 'git' || typeof repository.url != 'string') { - return; + return; } - var url = repository.url.replace(/^git\+/i, ''); - if (!HTTP_RE.test(url)) { - url = url.replace(/^git@([^:]+):/, 'http://$1/'); + var url = repository.url.replace(/^git\+/i, ''); + if (!HTTP_RE.test(url)) { + url = url.replace(/^git@([^:]+):/, 'http://$1/'); } - return url.replace(/\.git\s*$/i, ''); + return url.replace(/\.git\s*$/i, ''); } exports.getHomePageFromPackage = getHomePageFromPackage; diff --git a/lib/rules/dns.js b/lib/rules/dns.js index ea169a68f..783dbe075 100644 --- a/lib/rules/dns.js +++ b/lib/rules/dns.js @@ -8,122 +8,122 @@ var TIMEOUT = 6000; var UPDATE_INTERVAL = 1000; function lookupDNS(hostname, callback) { - var list = callbacks[hostname]; - if (list) { - list.push(callback); - return; + var list = callbacks[hostname]; + if (list) { + list.push(callback); + return; } - callbacks[hostname] = list = [callback]; + callbacks[hostname] = list = [callback]; - var done; - function execCallback(err, ip) { - var host; - if (err) { - host = dnsCache[hostname]; + var done; + function execCallback(err, ip) { + var host; + if (err) { + host = dnsCache[hostname]; } else { - host = dnsCache[hostname] = { - ip: ip, - hostname: hostname, - time: Date.now() + host = dnsCache[hostname] = { + ip: ip, + hostname: hostname, + time: Date.now() }; } - addUpdateQueue(host); + addUpdateQueue(host); - if (done) { - return; + if (done) { + return; } - done = true; - callbacks[hostname] = null; - list.forEach(function(callback) { - callback(err, ip); + done = true; + callbacks[hostname] = null; + list.forEach(function(callback) { + callback(err, ip); }); } - var timeout = setTimeout(function() { - execCallback(new Error('Timeout')); + var timeout = setTimeout(function() { + execCallback(new Error('Timeout')); }, TIMEOUT); - try { - dns.lookup(hostname, function (err, ip, type) { - clearTimeout(timeout); - err ? execCallback(err) : + try { + dns.lookup(hostname, function (err, ip, type) { + clearTimeout(timeout); + err ? execCallback(err) : execCallback(null, ip || (!type || type == 4 ? '127.0.0.1' : '0:0:0:0:0:0:0:1')); }); } catch(err) {//如果断网,可能直接抛异常,https代理没有用到error-handler - execCallback(err); + execCallback(err); } } function addUpdateQueue(host, fast) { - if (!host) { - return; + if (!host) { + return; } - var len = updateQueue.length; - if (len > 24000) { - updateQueue.splice(7000, len - 12000); - dnsCache = {}; - updateQueue.forEach(function(item) { - dnsCache[item.hostname] = item; + var len = updateQueue.length; + if (len > 24000) { + updateQueue.splice(7000, len - 12000); + dnsCache = {}; + updateQueue.forEach(function(item) { + dnsCache[item.hostname] = item; }); } - updateQueue[fast ? 'push' : 'unshift'](host); - if (reqCount <= 0) { - return; + updateQueue[fast ? 'push' : 'unshift'](host); + if (reqCount <= 0) { + return; } - --reqCount; - if (fast) { - updateQueue.pop(); - updateHost(host); + --reqCount; + if (fast) { + updateQueue.pop(); + updateHost(host); } else { - setTimeout(function() { - var host = updateQueue.pop(); - if (host) { - updateHost(host); + setTimeout(function() { + var host = updateQueue.pop(); + if (host) { + updateHost(host); } else { - ++reqCount; + ++reqCount; } }, UPDATE_INTERVAL); } } function updateHost(host, fast) { - lookupDNS(host.hostname, function(err, ip) { - if (fast) { - ++fastReqCount; + lookupDNS(host.hostname, function(err, ip) { + if (fast) { + ++fastReqCount; } else { - ++reqCount; + ++reqCount; } }); } function fastUpdateHost(host) { - if (Date.now() - host.time < TIMEOUT) { - return; + if (Date.now() - host.time < TIMEOUT) { + return; } - var index = updateQueue.indexOf(host); - if (index == -1) { - return; + var index = updateQueue.indexOf(host); + if (index == -1) { + return; } - updateQueue.splice(index, 1); - if (fastReqCount <= 0) { - addUpdateQueue(host, true); + updateQueue.splice(index, 1); + if (fastReqCount <= 0) { + addUpdateQueue(host, true); } else { - --fastReqCount; - updateHost(host, true); + --fastReqCount; + updateHost(host, true); } } module.exports = function lookup(hostname, callback, allowDnsCache) { - var host = allowDnsCache ? dnsCache[hostname] : null; - if (host) { - callback(null, host.ip); - fastUpdateHost(host); + var host = allowDnsCache ? dnsCache[hostname] : null; + if (host) { + callback(null, host.ip); + fastUpdateHost(host); } else { - lookupDNS(hostname, function(err, ip) { - err ? lookupDNS(hostname, callback) : callback(err, ip); + lookupDNS(hostname, function(err, ip) { + err ? lookupDNS(hostname, callback) : callback(err, ip); }); } }; \ No newline at end of file diff --git a/lib/rules/index.js b/lib/rules/index.js index e3c973460..9437357f1 100644 --- a/lib/rules/index.js +++ b/lib/rules/index.js @@ -17,7 +17,7 @@ exports.resolveRule = rules.resolveRule.bind(rules); exports.clearAppend = rules.clearAppend.bind(rules); exports.disableDnsCache = function() { - Rules.disableDnsCache(); + Rules.disableDnsCache(); }; function findProxyFromPac(req, next) { @@ -43,8 +43,8 @@ function findProxyFromPac(req, next) { } return pac.findWhistleProxyForURL(req.fullUrl.replace('tunnel:', 'https:'), function(err, rule) { if (rule) { - pacRules.parse(rules.pac.rawPattern + ' ' + rule); - rules.rule = pacRules.resolveRules(req.fullUrl).rule; + pacRules.parse(rules.pac.rawPattern + ' ' + rule); + rules.rule = pacRules.resolveRules(req.fullUrl).rule; } next(); }); diff --git a/lib/rules/protocols.js b/lib/rules/protocols.js index 14249dd91..629aef063 100644 --- a/lib/rules/protocols.js +++ b/lib/rules/protocols.js @@ -13,63 +13,63 @@ exports.protocols = protocols; exports.resProtocols = resProtocols; function getRules() { - return resetRules({}); + return resetRules({}); } exports.getRules = getRules; function isBinProtocol(protocol) { - return binProtocols.indexOf(protocol) != -1; + return binProtocols.indexOf(protocol) != -1; } exports.isBinProtocol = isBinProtocol; function resetRules(rules) { - protocols.forEach(function(protocol) { - rules[protocol] = []; + protocols.forEach(function(protocol) { + rules[protocol] = []; }); - return rules; + return rules; } exports.resetRules = resetRules; function isResRule(protocol) { - return resProtocols.indexOf(protocol) != -1; + return resProtocols.indexOf(protocol) != -1; } exports.isResRule = isResRule; function isWebProtocol(protocol) { - return protocol == 'http:' || protocol == 'https:'; + return protocol == 'http:' || protocol == 'https:'; } exports.isWebProtocol = isWebProtocol; function isWebsocketProtocol(protocol) { - return protocol == 'ws:' || protocol == 'wss:'; + return protocol == 'ws:' || protocol == 'wss:'; } exports.isWebsocketProtocol = isWebsocketProtocol; function isProxyProtocol(protocol) { - return protocol == 'proxy:' || protocol == 'http-proxy:' || protocol == 'socks:'; + return protocol == 'proxy:' || protocol == 'http-proxy:' || protocol == 'socks:'; } exports.isProxyProtocol = isProxyProtocol; function isFileProxy(protocol) { - return RULE_RE.test(protocol); + return RULE_RE.test(protocol); } exports.isFileProxy = isFileProxy; function contains(name) { - if (protocols.indexOf(name) != -1) { - return true; + if (protocols.indexOf(name) != -1) { + return true; } - name += ':'; - return isWebsocketProtocol(name) || isWebProtocol(name) || isProxyProtocol(name) || isFileProxy(name) || name == 'tunnel:'; + name += ':'; + return isWebsocketProtocol(name) || isWebProtocol(name) || isProxyProtocol(name) || isFileProxy(name) || name == 'tunnel:'; } exports.contains = contains; \ No newline at end of file diff --git a/lib/rules/rules.js b/lib/rules/rules.js index 3979408cc..4f1b864b8 100644 --- a/lib/rules/rules.js +++ b/lib/rules/rules.js @@ -14,80 +14,80 @@ var HOST_RE = /^(?:(?:25[0-5]|2[0-4]\d|1\d{2}|[1-9]?\d)\.){3}(?:25[0-5]|2[0-4]\d var FILE_RE = /^(?:[a-z]:(?:\\|\/(?!\/))|\/)/i; function isRule(str) { - return util.hasProtocol(str) && !WEB_PROTOCOL_RE.test(str); + return util.hasProtocol(str) && !WEB_PROTOCOL_RE.test(str); } function detactShorthand(url) { - if (HOST_RE.test(url)) { - return 'host://' + url; + if (HOST_RE.test(url)) { + return 'host://' + url; } - if (FILE_RE.test(url) && !util.isRegExp(url)) { - return 'file://' + url; + if (FILE_RE.test(url) && !util.isRegExp(url)) { + return 'file://' + url; } - return url; + return url; } function formatUrl(pattern) { - var queryString = ''; - var queryIndex = pattern.indexOf('?'); - if (queryIndex != -1) { - queryString = pattern.substring(queryIndex); - pattern = pattern.substring(0, queryIndex); + var queryString = ''; + var queryIndex = pattern.indexOf('?'); + if (queryIndex != -1) { + queryString = pattern.substring(queryIndex); + pattern = pattern.substring(0, queryIndex); } - var index = pattern.indexOf('://'); - return (pattern.indexOf('/', index == -1 ? 0 : index + 3) == -1 ? + var index = pattern.indexOf('://'); + return (pattern.indexOf('/', index == -1 ? 0 : index + 3) == -1 ? pattern + '/' : pattern) + queryString; } function getKey(url) { - if (url.indexOf('{') == 0) { - var index = url.lastIndexOf('}'); - return index > 1 && url.substring(1, index); + if (url.indexOf('{') == 0) { + var index = url.lastIndexOf('}'); + return index > 1 && url.substring(1, index); } - return false; + return false; } function getValue(url) { - if (url.indexOf('(') == 0) { - var index = url.lastIndexOf(')'); - return index != -1 ? url.substring(1, index) : url; + if (url.indexOf('(') == 0) { + var index = url.lastIndexOf(')'); + return index != -1 ? url.substring(1, index) : url; } - return false; + return false; } function getPath(url) { - if (url.indexOf('<') == 0) { - var index = url.lastIndexOf('>'); - return index != -1 ? url.substring(1, index) : url; + if (url.indexOf('<') == 0) { + var index = url.lastIndexOf('>'); + return index != -1 ? url.substring(1, index) : url; } - return false; + return false; } function getFiles(path) { - return /^x?((raw)?file|tpl|jsonp|dust):\/\//.test(path) ? util.removeProtocol(path, true).split('|') : null; + return /^x?((raw)?file|tpl|jsonp|dust):\/\//.test(path) ? util.removeProtocol(path, true).split('|') : null; } function setProtocol(target, source) { - if (util.hasProtocol(target)) { - return target; + if (util.hasProtocol(target)) { + return target; } - var protocol = util.getProtocol(source); - if (protocol == null) { - return target; + var protocol = util.getProtocol(source); + if (protocol == null) { + return target; } - return protocol + '//' + target; + return protocol + '//' + target; } function isPathSeparator(ch) { - return ch == '/' || ch == '\\' || ch == '?'; + return ch == '/' || ch == '\\' || ch == '?'; } /** @@ -98,45 +98,45 @@ function isPathSeparator(ch) { * @returns */ function join(first, second) { - if (!first || !second) { - return first + second; + if (!first || !second) { + return first + second; } - var firstIndex = first.indexOf('?'); - var secondIndex = second.indexOf('?'); - var firstQuery = ''; - var secondQuery = ''; + var firstIndex = first.indexOf('?'); + var secondIndex = second.indexOf('?'); + var firstQuery = ''; + var secondQuery = ''; - if (firstIndex != -1) { - firstQuery = first.substring(firstIndex); - first = first.substring(0, firstIndex); + if (firstIndex != -1) { + firstQuery = first.substring(firstIndex); + first = first.substring(0, firstIndex); } - if (secondIndex != -1) { - secondQuery = second.substring(secondIndex); - second = second.substring(0, secondIndex); + if (secondIndex != -1) { + secondQuery = second.substring(secondIndex); + second = second.substring(0, secondIndex); } - var query = firstQuery && secondQuery ? firstQuery + secondQuery.substring(1) : (firstQuery || secondQuery); - if (second) { - var lastIndex = first.length - 1; - var startWithSep = isPathSeparator(second[0]); - if (isPathSeparator(first[lastIndex])) { - first = startWithSep ? first.substring(0, lastIndex) + second : first + second; + var query = firstQuery && secondQuery ? firstQuery + secondQuery.substring(1) : (firstQuery || secondQuery); + if (second) { + var lastIndex = first.length - 1; + var startWithSep = isPathSeparator(second[0]); + if (isPathSeparator(first[lastIndex])) { + first = startWithSep ? first.substring(0, lastIndex) + second : first + second; } else { - first = first + (startWithSep ? '' : '/') + second; + first = first + (startWithSep ? '' : '/') + second; } } - return WEB_PROTOCOL_RE.test(first) ? formatUrl(first + query) : first + query; + return WEB_PROTOCOL_RE.test(first) ? formatUrl(first + query) : first + query; } function getLines(text) { - if (!text || !(text = text.trim())) { - return []; + if (!text || !(text = text.trim())) { + return []; } - return text.split(/\n|\r\n|\r/g); + return text.split(/\n|\r\n|\r/g); } function getValueFor(key, vals) { @@ -152,93 +152,93 @@ function getValueFor(key, vals) { } function getRule(url, list, vals, index) { - var rule = _getRule(url, list, index); - if (rule) { - var matcher = rule.matcher; - index = matcher.indexOf('://') + 3; - var protocol = matcher.substring(0, index); - matcher = matcher.substring(index); - var key = getKey(matcher); - if (key) { - rule.key = key; + var rule = _getRule(url, list, index); + if (rule) { + var matcher = rule.matcher; + index = matcher.indexOf('://') + 3; + var protocol = matcher.substring(0, index); + matcher = matcher.substring(index); + var key = getKey(matcher); + if (key) { + rule.key = key; } - var value = getValueFor(key, vals); - if (value == null) { - value = false; + var value = getValueFor(key, vals); + if (value == null) { + value = false; } - if (value !== false || (value = getValue(matcher)) !== false) { - rule.value = protocol + value; + if (value !== false || (value = getValue(matcher)) !== false) { + rule.value = protocol + value; } else if ((value = getPath(matcher)) !== false) { - rule.path = protocol + value; - rule.files = getFiles(rule.path); + rule.path = protocol + value; + rule.files = getFiles(rule.path); } } - return rule; + return rule; } function _getRule(url, list, index) { - url = formatUrl(url); + url = formatUrl(url); //支持域名匹配 - domainUrl = formatUrl(url).replace(/^((?:https?|wss?|tunnel):\/\/[^\/]+):\d*(\/.*)/i, '$1$2'); - index = index || 0; - var _url = url.replace(/[?#].*$/, ''); - var _domainUrl = domainUrl.replace(/[?#].*$/, ''); - var matchedUrl; - for (var i = 0, rule; rule = list[i]; i++) { - var pattern = rule.isRegExp ? rule.pattern : setProtocol(rule.pattern, url); + domainUrl = formatUrl(url).replace(/^((?:https?|wss?|tunnel):\/\/[^\/]+):\d*(\/.*)/i, '$1$2'); + index = index || 0; + var _url = url.replace(/[?#].*$/, ''); + var _domainUrl = domainUrl.replace(/[?#].*$/, ''); + var matchedUrl; + for (var i = 0, rule; rule = list[i]; i++) { + var pattern = rule.isRegExp ? rule.pattern : setProtocol(rule.pattern, url); - if (rule.isRegExp) { - if ((pattern.test(url) || (rule.isDomain && pattern.test(domainUrl))) && --index < 0) { - var regExp = {}; - for (var i = 1; i < 10; i++) { - regExp['$' + i] = RegExp['$' + i] || ''; + if (rule.isRegExp) { + if ((pattern.test(url) || (rule.isDomain && pattern.test(domainUrl))) && --index < 0) { + var regExp = {}; + for (var i = 1; i < 10; i++) { + regExp['$' + i] = RegExp['$' + i] || ''; } - function replaceSubMatcher(url) { - return url.replace(/(^|.)?(\$[1-9])/g, + function replaceSubMatcher(url) { + return url.replace(/(^|.)?(\$[1-9])/g, function(matched, $1, $2) { - return $1 == '\\' ? $2 : ($1 || '') + regExp[$2]; + return $1 == '\\' ? $2 : ($1 || '') + regExp[$2]; }); } - var matcher = rule.matcher; - var files = getFiles(matcher); - matcher = setProtocol(replaceSubMatcher(matcher), url); - var result = extend({ - url: matcher, - files: files && files.map(function(file) { - return replaceSubMatcher(file); + var matcher = rule.matcher; + var files = getFiles(matcher); + matcher = setProtocol(replaceSubMatcher(matcher), url); + var result = extend({ + url: matcher, + files: files && files.map(function(file) { + return replaceSubMatcher(file); }) }, rule); - result.matcher = matcher; - return result; + result.matcher = matcher; + return result; } } else if (rule.isExact) { - if (pattern == url && --index < 0) { - var matcher = setProtocol(rule.matcher, url); - return extend({ - files: getFiles(matcher), - url: matcher - }, rule); + if (pattern == url && --index < 0) { + var matcher = setProtocol(rule.matcher, url); + return extend({ + files: getFiles(matcher), + url: matcher +}, rule); } } else if ((matchedUrl = (url.indexOf(pattern) === 0)) || (rule.isDomain && domainUrl.indexOf(pattern) === 0)) { - var len = pattern.length; - var matcher = setProtocol(rule.matcher, url); - var files = getFiles(matcher); - var hasQuery = pattern.indexOf('?') != -1; - if ((hasQuery || (matchedUrl ? (pattern == _url || isPathSeparator(_url[len])) : + var len = pattern.length; + var matcher = setProtocol(rule.matcher, url); + var files = getFiles(matcher); + var hasQuery = pattern.indexOf('?') != -1; + if ((hasQuery || (matchedUrl ? (pattern == _url || isPathSeparator(_url[len])) : (pattern == _domainUrl || isPathSeparator(_domainUrl[len]))) || isPathSeparator(pattern[len - 1])) && --index < 0) { - var filePath = (matchedUrl ? url : domainUrl).substring(len); - if (hasQuery && filePath) { - filePath = '?' + filePath; + var filePath = (matchedUrl ? url : domainUrl).substring(len); + if (hasQuery && filePath) { + filePath = '?' + filePath; } - return extend({ - files: files && files.map(function(file) { - return join(file, filePath); + return extend({ + files: files && files.map(function(file) { + return join(file, filePath); }), - url: join(matcher, filePath) + url: join(matcher, filePath) }, rule); } } @@ -246,88 +246,88 @@ function _getRule(url, list, index) { } function resolveProperties(url, rules, vals) { - var rule = getRule(url, rules, vals); - var result = {}; - if (rule) { - util.getMatcherValue(rule) + var rule = getRule(url, rules, vals); + var result = {}; + if (rule) { + util.getMatcherValue(rule) .split('|').forEach(function(action) { - result[action] = true; + result[action] = true; }); } - return result; + return result; } function parseRule(rules, pattern, matcher, raw, root) { - var isRegExp; - var rawPattern = pattern; - if (!pattern || !matcher || + var isRegExp; + var rawPattern = pattern; + if (!pattern || !matcher || ((isRegExp = util.isRegExp(pattern)) && !(pattern = util.toRegExp(pattern)))) { - return; + return; } - if (PLUGIN_RE.test(matcher)) { - matcher = 'plugin://' + RegExp.$1; - } + if (PLUGIN_RE.test(matcher)) { + matcher = 'plugin://' + RegExp.$1; +} - var list, port, protocol, isExact; - if (isExactPattern(pattern)) { - isExact = true; - pattern = pattern.slice(1); + var list, port, protocol, isExact; + if (isExactPattern(pattern)) { + isExact = true; + pattern = pattern.slice(1); } - if (net.isIP(matcher)) { - list = rules.host; - protocol = 'host'; + if (net.isIP(matcher)) { + list = rules.host; + protocol = 'host'; } else { - protocol = matcher.match(/^([\w\-]+):\/\//); - protocol = protocol && protocol[1]; - list = rules[protocol]; - if (!list) { - protocol = 'rule'; - list = rules.rule; + protocol = matcher.match(/^([\w\-]+):\/\//); + protocol = protocol && protocol[1]; + list = rules[protocol]; + if (!list) { + protocol = 'rule'; + list = rules.rule; } - if (protocol == 'host' && PORT_RE.test(matcher)) { - matcher = RegExp.$1; - port = RegExp.$2; + if (protocol == 'host' && PORT_RE.test(matcher)) { + matcher = RegExp.$1; + port = RegExp.$2; } } - list.push({ - name: protocol, - root: root, - isRegExp: isRegExp, - isExact: isExact, - protocol: isRegExp ? null : util.getProtocol(pattern), - pattern: isRegExp ? pattern : formatUrl(pattern), - matcher: matcher, - port: port, - raw: raw, - isDomain: !isRegExp && util.removeProtocol(rawPattern, true).indexOf('/') == -1, - rawPattern: rawPattern + list.push({ + name: protocol, + root: root, + isRegExp: isRegExp, + isExact: isExact, + protocol: isRegExp ? null : util.getProtocol(pattern), + pattern: isRegExp ? pattern : formatUrl(pattern), + matcher: matcher, + port: port, + raw: raw, + isDomain: !isRegExp && util.removeProtocol(rawPattern, true).indexOf('/') == -1, + rawPattern: rawPattern }); } function parse(rules, text, root, append) { - !append && protoMgr.resetRules(rules); - getLines(text).forEach(function(line) { - var raw = line; - line = line.replace(/#.*$/, '').trim(); - if (!line) { - return; + !append && protoMgr.resetRules(rules); + getLines(text).forEach(function(line) { + var raw = line; + line = line.replace(/#.*$/, '').trim(); + if (!line) { + return; } - line = line.split(/\s+/).map(detactShorthand); - var pattern = line[0]; - if (!isExactPattern(pattern) && ((net.isIP(pattern) && !isRule(line[1])) || isRule(pattern) + line = line.split(/\s+/).map(detactShorthand); + var pattern = line[0]; + if (!isExactPattern(pattern) && ((net.isIP(pattern) && !isRule(line[1])) || isRule(pattern) || (!util.isRegExp(pattern) && (isExactPattern(line[1]) || util.isRegExp(line[1]))))) { //supports: operator-uri pattern1 pattern2 ... patternN - line.slice(1).forEach(function(matcher) { - parseRule(rules, matcher, pattern, raw, root); + line.slice(1).forEach(function(matcher) { + parseRule(rules, matcher, pattern, raw, root); }); } else { //supports: pattern operator-uri1 operator-uri2 ... operator-uriN - line.slice(1).forEach(function(matcher) { - parseRule(rules, pattern, matcher, raw, root); + line.slice(1).forEach(function(matcher) { + parseRule(rules, pattern, matcher, raw, root); }); } }); @@ -338,111 +338,111 @@ function isExactPattern(pattern) { } function Rules(values) { - this._rules = protoMgr.getRules(); - this._values = values || {}; + this._rules = protoMgr.getRules(); + this._values = values || {}; } var proto = Rules.prototype; proto.parse = function(text, root) { - var item = { - first: true, - text: text, - root: root + var item = { + first: true, + text: text, + root: root }; - this.disabled = !arguments.length; - if (this._rawText) { - if (this._rawText[0].first) { - this._rawText.shift(); + this.disabled = !arguments.length; + if (this._rawText) { + if (this._rawText[0].first) { + this._rawText.shift(); } - this._rawText.unshift(item); + this._rawText.unshift(item); } else { - this._rawText = [item]; + this._rawText = [item]; } - parse(this._rules, text, root); - if (!this.disabled) { - for (var i = 1, len = this._rawText.length; i < len; i++) { - item = this._rawText[i]; - parse(this._rules, item.text, item.root, true); + parse(this._rules, text, root); + if (!this.disabled) { + for (var i = 1, len = this._rawText.length; i < len; i++) { + item = this._rawText[i]; + parse(this._rules, item.text, item.root, true); } } }; proto.clearAppend = function() { - if (this._rawText && this._rawText[0].first) { - var item = this._rawText[0]; - !this.disabled && parse(this._rules, item.text, item.root); - this._rawText = [item]; + if (this._rawText && this._rawText[0].first) { + var item = this._rawText[0]; + !this.disabled && parse(this._rules, item.text, item.root); + this._rawText = [item]; } else { - this._rawText = null; + this._rawText = null; } }; proto.append = function(text, root) { - var item = { - text: text, - root: root + var item = { + text: text, + root: root }; - if (this._rawText) { - this._rawText.push(item); - !this.disabled && parse(this._rules, text, root, true); + if (this._rawText) { + this._rawText.push(item); + !this.disabled && parse(this._rules, text, root, true); } else { - this._rawText = [item]; + this._rawText = [item]; } }; proto.resolveHost = function(_url, callback, pluginRules) { - _url = formatUrl(util.setProtocol(_url)); - var options = url.parse(_url); - if (!options.hostname || (!protoMgr.isWebsocketProtocol(options.protocol) + _url = formatUrl(util.setProtocol(_url)); + var options = url.parse(_url); + if (!options.hostname || (!protoMgr.isWebsocketProtocol(options.protocol) && !protoMgr.isWebProtocol(options.protocol) && options.protocol != 'tunnel:')) { - return callback(null, null); + return callback(null, null); } - var filterHost = this.resolveFilter(_url).host || (pluginRules && pluginRules.resolveFilter(_url).host); - var vals = this._values; - var host = !filterHost && ((pluginRules && getRule(_url, pluginRules._rules.host, vals)) || getRule(_url, this._rules.host, vals)); - if (host) { - return callback(null, util.removeProtocol(host.matcher, true), host.port, host); + var filterHost = this.resolveFilter(_url).host || (pluginRules && pluginRules.resolveFilter(_url).host); + var vals = this._values; + var host = !filterHost && ((pluginRules && getRule(_url, pluginRules._rules.host, vals)) || getRule(_url, this._rules.host, vals)); + if (host) { + return callback(null, util.removeProtocol(host.matcher, true), host.port, host); } - lookup(options.hostname, callback, allowDnsCache && !this.resolveDisable(_url).dnsCache); + lookup(options.hostname, callback, allowDnsCache && !this.resolveDisable(_url).dnsCache); }; proto.resolveFilter = function(url) { - var filter = resolveProperties(url, this._rules.filter, this._values); - delete filter.filter; - return filter; + var filter = resolveProperties(url, this._rules.filter, this._values); + delete filter.filter; + return filter; }; proto.resolveDisable = function(url) { - return resolveProperties(url, this._rules.disable, this._values); + return resolveProperties(url, this._rules.disable, this._values); }; proto.resolveRules = function resolveRules(url) { - url = formatUrl(util.setProtocol(url)); + url = formatUrl(util.setProtocol(url)); - var rule; - var rules = this._rules; - var _rules = {}; - var filter = this.resolveFilter(url); - var vals = this._values; - protocols.forEach(function(protocol) { - if ((protocol == 'filter' || !filter[protocol]) && (rule = getRule(url, rules[protocol], vals))) { - _rules[protocol] = rule; + var rule; + var rules = this._rules; + var _rules = {}; + var filter = this.resolveFilter(url); + var vals = this._values; + protocols.forEach(function(protocol) { + if ((protocol == 'filter' || !filter[protocol]) && (rule = getRule(url, rules[protocol], vals))) { + _rules[protocol] = rule; } }); - return _rules; + return _rules; }; proto.resolveRule = function(url, index) { - if (index = index || 0) { - index = parseInt(index, 10); + if (index = index || 0) { + index = parseInt(index, 10); } - return getRule(url, this._rules.rule, this._values, index); + return getRule(url, this._rules.rule, this._values, index); }; Rules.disableDnsCache = function() { - allowDnsCache = false; + allowDnsCache = false; }; module.exports = Rules; diff --git a/lib/rules/storage.js b/lib/rules/storage.js index af36efc27..92b67656c 100644 --- a/lib/rules/storage.js +++ b/lib/rules/storage.js @@ -5,82 +5,82 @@ var logger = require('../util/logger'); var RETRY_INTERVAL = 16000; function readFileSafe(file) { - try { - file = fs.readFileSync(file, {encoding: 'utf8'}); + try { + file = fs.readFileSync(file, {encoding: 'utf8'}); } catch(e) { - file = null; - logger.error(e); + file = null; + logger.error(e); } - return file || ''; + return file || ''; } function readJsonSafe(file) { - try { - file = fse.readJsonSync(file); + try { + file = fse.readJsonSync(file); } catch(e) { - file = null; - logger.error(e); + file = null; + logger.error(e); } - return file || {}; + return file || {}; } function copyFileObj(file) { - if (!file) { - return file; + if (!file) { + return file; } - return { - index: file.index, - name: file.name, - data: file.data, - selected: file.selected + return { + index: file.index, + name: file.name, + data: file.data, + selected: file.selected }; } function noop() {} function Storage(dir) { - var self = this; - if (!(self instanceof Storage)) { - return new Storage(dir); + var self = this; + if (!(self instanceof Storage)) { + return new Storage(dir); } - fse.ensureDirSync(dir); + fse.ensureDirSync(dir); - self._files = path.join(dir, 'files'); - self._properties = path.join(dir, 'properties'); - fse.ensureDirSync(self._files); - fse.ensureFileSync(self._properties); + self._files = path.join(dir, 'files'); + self._properties = path.join(dir, 'properties'); + fse.ensureDirSync(self._files); + fse.ensureFileSync(self._properties); - var maxIndex = -1; - var files = {}; - fs.readdirSync(self._files) + var maxIndex = -1; + var files = {}; + fs.readdirSync(self._files) .forEach(function(file) { - if (!/^(\d+)\.(.+)$/.test(file)) { - return; + if (!/^(\d+)\.(.+)$/.test(file)) { + return; } - try { - var index = parseInt(RegExp.$1, 10); - var filename = decodeURIComponent(RegExp.$2); - if (index > maxIndex) { - maxIndex = index; + try { + var index = parseInt(RegExp.$1, 10); + var filename = decodeURIComponent(RegExp.$2); + if (index > maxIndex) { + maxIndex = index; } - files[filename] = { - index: index, - name: filename, - data: readFileSafe(path.join(self._files, file)) + files[filename] = { + index: index, + name: filename, + data: readFileSafe(path.join(self._files, file)) }; } catch(e) { - logger.error(e); + logger.error(e); } }); - self._cache = { - maxIndex: maxIndex, - files: files, - properties: readJsonSafe(self._properties) + self._cache = { + maxIndex: maxIndex, + files: files, + properties: readJsonSafe(self._properties) }; } @@ -88,205 +88,205 @@ function Storage(dir) { var proto = Storage.prototype; proto._writeProperties = function _writeProperties() { - var self = this; - if (self._writePropertiesPending) { - self._writePropertiesWaiting = true; - return; + var self = this; + if (self._writePropertiesPending) { + self._writePropertiesWaiting = true; + return; } - clearTimeout(self._writePropertiesTimeout); - self._writePropertiesPending = true; - fse.outputJson(self._properties, self._cache.properties, function(err) { - self._writePropertiesPending = false; - if (self._writePropertiesWaiting) { - self._writePropertiesWaiting = false; - self._writeProperties(); + clearTimeout(self._writePropertiesTimeout); + self._writePropertiesPending = true; + fse.outputJson(self._properties, self._cache.properties, function(err) { + self._writePropertiesPending = false; + if (self._writePropertiesWaiting) { + self._writePropertiesWaiting = false; + self._writeProperties(); } else if (err) { - self._writePropertiesTimeout = setTimeout(self._writeProperties.bind(self), RETRY_INTERVAL); - logger.error(err); + self._writePropertiesTimeout = setTimeout(self._writeProperties.bind(self), RETRY_INTERVAL); + logger.error(err); } }); }; proto._writeFile = function _writeFile(file) { - var self = this; - if (!(file = self._cache.files[file])) { - return; + var self = this; + if (!(file = self._cache.files[file])) { + return; } - if (file._pending) { - file._waiting = true; - return; + if (file._pending) { + file._waiting = true; + return; } - clearTimeout(file._timeout); - file._pending = true; - fs.writeFile(self._getFilePath(file), file.data, function(err) { - file._pending = false; - if (file._waiting) { - file._waiting = false; - self._writeFile(file.name); + clearTimeout(file._timeout); + file._pending = true; + fs.writeFile(self._getFilePath(file), file.data, function(err) { + file._pending = false; + if (file._waiting) { + file._waiting = false; + self._writeFile(file.name); } else if (err) { - file._timeout = setTimeout(function() { - self._writeFile(file.name); + file._timeout = setTimeout(function() { + self._writeFile(file.name); }, RETRY_INTERVAL); - logger.error(err); + logger.error(err); } }); }; proto._getFilePath = function _getFilePath(file) { - file = typeof file == 'string' ? this._cache.files[file] : file; - var name = file.name; - try { - name = encodeURIComponent(file.name); + file = typeof file == 'string' ? this._cache.files[file] : file; + var name = file.name; + try { + name = encodeURIComponent(file.name); } catch(e) { - logger.error(e); + logger.error(e); } - return file && path.join(this._files, file.index + '.' + name); + return file && path.join(this._files, file.index + '.' + name); }; proto.count = function count() { - return Object.keys(this._cache.files).length; + return Object.keys(this._cache.files).length; }; proto.existsFile = function existsFile(file) { - return this._cache.files[file]; + return this._cache.files[file]; }; proto.getFileList = function getFileList(origObj) { - var cache = this._cache; - var list = []; - Object.keys(cache.files) + var cache = this._cache; + var list = []; + Object.keys(cache.files) .forEach(function(file) { - list.push(origObj ? cache.files[file] : copyFileObj(cache.files[file])); + list.push(origObj ? cache.files[file] : copyFileObj(cache.files[file])); }); - list.sort(function(prev, next) { - return prev.index > next.index ? 1 : -1; + list.sort(function(prev, next) { + return prev.index > next.index ? 1 : -1; }); - return list; + return list; }; proto.writeFile = function writeFile(file, data) { - if (!file) { - return; + if (!file) { + return; } - var self = this; - var cache = self._cache; - var fileData = cache.files[file]; - if (!fileData) { - fileData = cache.files[file] = { - index: ++cache.maxIndex, - name: file + var self = this; + var cache = self._cache; + var fileData = cache.files[file]; + if (!fileData) { + fileData = cache.files[file] = { + index: ++cache.maxIndex, + name: file }; } - fileData.data = data == null ? '' : data; - self._writeFile(file); - return fileData; + fileData.data = data == null ? '' : data; + self._writeFile(file); + return fileData; }; proto.updateFile = function updateFile(file, data) { - return this.existsFile(file) && this.writeFile(file, data); + return this.existsFile(file) && this.writeFile(file, data); }; proto.readFile = function(file) { - file = file && this._cache.files[file]; - return file && file.data; + file = file && this._cache.files[file]; + return file && file.data; }; proto.removeFile = function removeFile(file) { - var files = this._cache.files; - file = file && files[file]; - if (!file) { - return; + var files = this._cache.files; + file = file && files[file]; + if (!file) { + return; } - delete files[file.name]; - fs.unlink(this._getFilePath(file), noop); - return true; + delete files[file.name]; + fs.unlink(this._getFilePath(file), noop); + return true; }; proto.renameFile = function renameFile(file, newFile) { - var cache = this._cache; - if (!newFile || !(file = cache.files[file]) + var cache = this._cache; + if (!newFile || !(file = cache.files[file]) || cache.files[newFile]) { - return; + return; } - var path = this._getFilePath(file); - delete cache.files[file.name]; - file.name = newFile; - cache.files[newFile] = file; - fs.rename(path, this._getFilePath(file), noop); //不考虑并发 - return true; + var path = this._getFilePath(file); + delete cache.files[file.name]; + file.name = newFile; + cache.files[newFile] = file; + fs.rename(path, this._getFilePath(file), noop); //不考虑并发 + return true; }; proto.moveUp = function moveUp(file) { - var cache = this._cache; - if (!(file = cache.files[file])) { - return; + var cache = this._cache; + if (!(file = cache.files[file])) { + return; } - var list = this.getFileList(true); - var prev = list[list.indexOf(file) - 1]; - if (prev) { - this._swap(file, prev); - return prev.name; + var list = this.getFileList(true); + var prev = list[list.indexOf(file) - 1]; + if (prev) { + this._swap(file, prev); + return prev.name; } }; proto.moveDown = function moveDown(file) { - var cache = this._cache; - if (!(file = cache.files[file])) { - return; + var cache = this._cache; + if (!(file = cache.files[file])) { + return; } - var list = this.getFileList(true); - var next = list[list.indexOf(file) + 1]; - if (next) { - this._swap(file, next); - return next.name; + var list = this.getFileList(true); + var next = list[list.indexOf(file) + 1]; + if (next) { + this._swap(file, next); + return next.name; } }; proto._swap = function swap(file1, file2) { - var path1 = this._getFilePath(file1); - var path2 = this._getFilePath(file2); - var index = file1.index; - file1.index = file2.index; - file2.index = index; - fs.rename(path1, this._getFilePath(file1), noop); //不考虑并发 - fs.rename(path2, this._getFilePath(file2), noop); //不考虑并发 + var path1 = this._getFilePath(file1); + var path2 = this._getFilePath(file2); + var index = file1.index; + file1.index = file2.index; + file2.index = index; + fs.rename(path1, this._getFilePath(file1), noop); //不考虑并发 + fs.rename(path2, this._getFilePath(file2), noop); //不考虑并发 }; proto.setProperty = function setProperty(name, value) { - this._cache.properties[name] = value; - this._writeProperties(); + this._cache.properties[name] = value; + this._writeProperties(); }; proto.hasProperty = function hasProperty(name) { - return name in this._cache.properties; + return name in this._cache.properties; }; proto.setProperties = function setProperties(obj) { - if (!obj) { - return; + if (!obj) { + return; } - var props = this._cache.properties; - Object.keys(obj).forEach(function(key) { - props[key] = obj[key]; + var props = this._cache.properties; + Object.keys(obj).forEach(function(key) { + props[key] = obj[key]; }); - this._writeProperties(); - return true; + this._writeProperties(); + return true; }; proto.getProperty = function getProperty(name) { - return this._cache.properties[name]; + return this._cache.properties[name]; }; proto.removeProperty = function removeProperty(name) { - if (this.hasProperty(name)) { - delete this._cache.properties[name]; - this._writeProperties(); + if (this.hasProperty(name)) { + delete this._cache.properties[name]; + this._writeProperties(); } }; diff --git a/lib/rules/system.js b/lib/rules/system.js index 5cb943db6..632f4e31b 100644 --- a/lib/rules/system.js +++ b/lib/rules/system.js @@ -1,17 +1,17 @@ var os = require('os'); var fs = require('fs'); var HOSTS_MAP = { - darwin: '/private/etc/hosts', - win32:'C:/Windows/system32/drivers/etc/hosts' + darwin: '/private/etc/hosts', + win32:'C:/Windows/system32/drivers/etc/hosts' }; var hostsFilePath = HOSTS_MAP[os.platform()] || '/etc/hosts'; function getHosts(callback) { - fs.readFile(hostsFilePath, {encoding: 'utf8'}, callback); + fs.readFile(hostsFilePath, {encoding: 'utf8'}, callback); } function setHosts(hosts, callback) { - fs.writeFile(hostsFilePath, hosts || '', callback); + fs.writeFile(hostsFilePath, hosts || '', callback); } function getProxy() { @@ -27,10 +27,10 @@ function resetProxy() { } module.exports = { - getHosts: getHosts, - setHosts: setHosts, - getProxy: getProxy, - setProxy: setProxy, - resetProxy: resetProxy + getHosts: getHosts, + setHosts: setHosts, + getProxy: getProxy, + setProxy: setProxy, + resetProxy: resetProxy }; diff --git a/lib/rules/util.js b/lib/rules/util.js index 82bda7714..e601cb765 100644 --- a/lib/rules/util.js +++ b/lib/rules/util.js @@ -12,12 +12,12 @@ var system = require('./system'); var filter; function setFilter(text) { - if (!text || typeof text != 'string') { - text = ''; + if (!text || typeof text != 'string') { + text = ''; } - text = text.substring(0, 128); - propertiesStorage.setProperty('filterText', text); - filter = util.toRegExp(text) || text; + text = text.substring(0, 128); + propertiesStorage.setProperty('filterText', text); + filter = util.toRegExp(text) || text; } exports.setFilter = setFilter; @@ -25,233 +25,233 @@ exports.setFilter = setFilter; setFilter(propertiesStorage.getProperty('filterText')); exports.filterUrl = function filterUrl(url) { - if (!url) { - return false; + if (!url) { + return false; } - if (!filter) { - return true; + if (!filter) { + return true; } - if (filter.test) { - return filter.test(url); + if (filter.test) { + return filter.test(url); } - return url.indexOf(filter) != -1; + return url.indexOf(filter) != -1; }; process.nextTick(function() { - parseRules(); + parseRules(); }); /** * rules */ function parseHosts(text) { - if (typeof text != 'string' + if (typeof text != 'string' || !(text = text.trim())) { - return ''; + return ''; } - var result = []; - text.split(/\n|\r\n|\r/g) + var result = []; + text.split(/\n|\r\n|\r/g) .forEach(function(line) { - line = line.replace(/#.*$/, '').trim(); - if (!line) { - return; + line = line.replace(/#.*$/, '').trim(); + if (!line) { + return; } - line = line.split(/\s+/); - var pattern = line[0]; - if (net.isIP(pattern)) { - line.slice(1).forEach(function(matcher) { - !/\//.test(matcher) && result.push(pattern + ' ' + matcher); + line = line.split(/\s+/); + var pattern = line[0]; + if (net.isIP(pattern)) { + line.slice(1).forEach(function(matcher) { + !/\//.test(matcher) && result.push(pattern + ' ' + matcher); }); } else if (!/\//.test(pattern) && line[1] && net.isIP(line[1])) { - result.push(line[1] + ' ' + pattern); + result.push(line[1] + ' ' + pattern); } }); - return result.join('\r\n'); + return result.join('\r\n'); } function parseRules(defaultRules) { - if (propertiesStorage.getProperty('disabledAllRules')) { - return rules.parse(); + if (propertiesStorage.getProperty('disabledAllRules')) { + return rules.parse(); } - var value = []; - var hosts = propertiesStorage.getProperty('syncWithSysHosts') ? [] : null; - getAllRulesFile().forEach(function(file) { - if (file.selected) { - value.push(file.data); - if (hosts) { - var sysHosts = parseHosts(file.data); - if (sysHosts) { - hosts.push('#\r\n# ' + file.name + '\r\n#' + '\r\n' + sysHosts); + var value = []; + var hosts = propertiesStorage.getProperty('syncWithSysHosts') ? [] : null; + getAllRulesFile().forEach(function(file) { + if (file.selected) { + value.push(file.data); + if (hosts) { + var sysHosts = parseHosts(file.data); + if (sysHosts) { + hosts.push('#\r\n# ' + file.name + '\r\n#' + '\r\n' + sysHosts); } } } }); - if (typeof defaultRules == 'string') { - setDefaultRules(defaultRules); - value.push(defaultRules); - rulesStorage.setProperty('disabledDefalutRules', false); + if (typeof defaultRules == 'string') { + setDefaultRules(defaultRules); + value.push(defaultRules); + rulesStorage.setProperty('disabledDefalutRules', false); }else if (!defaultRulesIsDisabled()) { - defaultRules = getDefaultRules(); - value.push(defaultRules); + defaultRules = getDefaultRules(); + value.push(defaultRules); } - if (hosts && defaultRules) { - var sysHosts = parseHosts(defaultRules); - if (sysHosts) { - hosts.push('#\r\n# Default\r\n#' + '\r\n' + sysHosts); + if (hosts && defaultRules) { + var sysHosts = parseHosts(defaultRules); + if (sysHosts) { + hosts.push('#\r\n# Default\r\n#' + '\r\n' + sysHosts); } } - rules.parse(value.join('\r\n')); - if (hosts) { - hosts = hosts.join('\r\n\r\n'); - system.setHosts(hosts, util.noop); + rules.parse(value.join('\r\n')); + if (hosts) { + hosts = hosts.join('\r\n\r\n'); + system.setHosts(hosts, util.noop); } } exports.parseRules = parseRules; function setDefaultRules(data) { - data = typeof data != 'string' ? '' : data; - rulesStorage.setProperty('defalutRules', data); - parseRules(); + data = typeof data != 'string' ? '' : data; + rulesStorage.setProperty('defalutRules', data); + parseRules(); } function getDefaultRules() { - return rulesStorage.getProperty('defalutRules'); + return rulesStorage.getProperty('defalutRules'); } function disableDefaultRules() { - rulesStorage.setProperty('disabledDefalutRules', true); - parseRules(); + rulesStorage.setProperty('disabledDefalutRules', true); + parseRules(); } function enableDefaultRules() { - rulesStorage.setProperty('disabledDefalutRules', false); - parseRules(); + rulesStorage.setProperty('disabledDefalutRules', false); + parseRules(); } function defaultRulesIsDisabled() { - return rulesStorage.getProperty('disabledDefalutRules'); + return rulesStorage.getProperty('disabledDefalutRules'); } function selectRulesFile(file) { - if (!rulesStorage.existsFile(file)) { - return; + if (!rulesStorage.existsFile(file)) { + return; } - var selectedList = allowMultipleChoice() ? getSelectedRulesList() : []; - if (selectedList.indexOf(file) == -1) { - selectedList.push(file); - rulesStorage.setProperty('selectedList', selectedList); + var selectedList = allowMultipleChoice() ? getSelectedRulesList() : []; + if (selectedList.indexOf(file) == -1) { + selectedList.push(file); + rulesStorage.setProperty('selectedList', selectedList); } - parseRules(); - return selectedList; + parseRules(); + return selectedList; } function unselectRulesFile(file) { - var selectedList; + var selectedList; - if (allowMultipleChoice()) { - selectedList = getSelectedRulesList(); - var index = selectedList.indexOf(file); - if (index != -1) { - selectedList.splice(index, 1); - rulesStorage.setProperty('selectedList', selectedList); + if (allowMultipleChoice()) { + selectedList = getSelectedRulesList(); + var index = selectedList.indexOf(file); + if (index != -1) { + selectedList.splice(index, 1); + rulesStorage.setProperty('selectedList', selectedList); } } else { - selectedList = []; - rulesStorage.setProperty('selectedList', selectedList); + selectedList = []; + rulesStorage.setProperty('selectedList', selectedList); } - parseRules(); + parseRules(); - return selectedList; + return selectedList; } function allowMultipleChoice() { - return propertiesStorage.getProperty('allowMultipleChoice'); + return propertiesStorage.getProperty('allowMultipleChoice'); } function clearSelection() { - rulesStorage.setProperty('selectedList', []); - parseRules(); + rulesStorage.setProperty('selectedList', []); + parseRules(); } function getSelectedRulesList() { - var selectedList = rulesStorage.getProperty('selectedList'); - if (!selectedList) { - selectedList = []; - rulesStorage.setProperty('selectedList', selectedList); + var selectedList = rulesStorage.getProperty('selectedList'); + if (!selectedList) { + selectedList = []; + rulesStorage.setProperty('selectedList', selectedList); } - return selectedList; + return selectedList; } function removeRulesFile(file) { - unselectRulesFile(file); - rulesStorage.removeFile(file); + unselectRulesFile(file); + rulesStorage.removeFile(file); } function renameRulesFile(file, newFile) { - if (!rulesStorage.renameFile(file, newFile)) { - return; + if (!rulesStorage.renameFile(file, newFile)) { + return; } - var selectedList = getSelectedRulesList(); - var index = selectedList.indexOf(file); - if (index != -1) { - selectedList[index] = newFile; - rulesStorage.setProperty('selectedList', selectedList); + var selectedList = getSelectedRulesList(); + var index = selectedList.indexOf(file); + if (index != -1) { + selectedList[index] = newFile; + rulesStorage.setProperty('selectedList', selectedList); } } function addRulesFile(file, data) { - rulesStorage.writeFile(file, data); + rulesStorage.writeFile(file, data); } function getAllRulesFile() { - var list = rulesStorage.getFileList(); - var selectedList = getSelectedRulesList(); - list.forEach(function(file) { - file.selected = selectedList.indexOf(file.name) != -1; + var list = rulesStorage.getFileList(); + var selectedList = getSelectedRulesList(); + list.forEach(function(file) { + file.selected = selectedList.indexOf(file.name) != -1; }); - return list; + return list; } function resetRulesIfSwap(next, prev) { - if (!next || !prev) { - return; + if (!next || !prev) { + return; } - var selectedList = getSelectedRulesList(); - if (selectedList.indexOf(next) == -1 || selectedList.indexOf(prev) == -1) { - return; + var selectedList = getSelectedRulesList(); + if (selectedList.indexOf(next) == -1 || selectedList.indexOf(prev) == -1) { + return; } - parseRules(); + parseRules(); } exports.rules = { - getSysHosts: system.getHosts, - setSysHosts: system.setHosts, - remove: removeRulesFile, - add: addRulesFile, - rename: renameRulesFile, - select: selectRulesFile, - unselect: unselectRulesFile, - list: getAllRulesFile, - getDefault: getDefaultRules, - setDefault: setDefaultRules, - enableDefault: enableDefaultRules, - disableDefault: disableDefaultRules, - defaultRulesIsDisabled: defaultRulesIsDisabled, - parseRules: parseRules, - clearSelection:clearSelection, - getSelectedList: getSelectedRulesList, - moveUp: function(file) { - resetRulesIfSwap(file, rulesStorage.moveUp(file)); + getSysHosts: system.getHosts, + setSysHosts: system.setHosts, + remove: removeRulesFile, + add: addRulesFile, + rename: renameRulesFile, + select: selectRulesFile, + unselect: unselectRulesFile, + list: getAllRulesFile, + getDefault: getDefaultRules, + setDefault: setDefaultRules, + enableDefault: enableDefaultRules, + disableDefault: disableDefaultRules, + defaultRulesIsDisabled: defaultRulesIsDisabled, + parseRules: parseRules, + clearSelection:clearSelection, + getSelectedList: getSelectedRulesList, + moveUp: function(file) { + resetRulesIfSwap(file, rulesStorage.moveUp(file)); }, - moveDown: function(file) { - resetRulesIfSwap(file, rulesStorage.moveDown(file)); + moveDown: function(file) { + resetRulesIfSwap(file, rulesStorage.moveDown(file)); } }; @@ -261,63 +261,63 @@ exports.rules = { */ function addValuesFile(file, data) { - valuesStorage.writeFile(file, data); + valuesStorage.writeFile(file, data); } exports.values = { - add: addValuesFile, - get: function(file) { - return valuesStorage.readFile(file); + add: addValuesFile, + get: function(file) { + return valuesStorage.readFile(file); }, - remove: function remove(file) { - valuesStorage.removeFile(file); + remove: function remove(file) { + valuesStorage.removeFile(file); }, - rename: function(file, newFile) { - valuesStorage.renameFile(file, newFile); + rename: function(file, newFile) { + valuesStorage.renameFile(file, newFile); }, - list: function list() { - var selectedFile = valuesStorage.getProperty('selectedFile'); - var list = valuesStorage.getFileList(); - if (selectedFile) { - list.forEach(function(file) { - file.selected = file.name == selectedFile; + list: function list() { + var selectedFile = valuesStorage.getProperty('selectedFile'); + var list = valuesStorage.getFileList(); + if (selectedFile) { + list.forEach(function(file) { + file.selected = file.name == selectedFile; }); } - return list; + return list; }, - select: function(file) { - typeof file == 'string' && valuesStorage.setProperty('selectedFile', file); + select: function(file) { + typeof file == 'string' && valuesStorage.setProperty('selectedFile', file); }, - unselect: function() { - valuesStorage.removeProperty('selectedFile'); + unselect: function() { + valuesStorage.removeProperty('selectedFile'); }, - moveUp: function(file) { - valuesStorage.moveUp(file); + moveUp: function(file) { + valuesStorage.moveUp(file); }, - moveDown: function(file) { - valuesStorage.moveDown(file); + moveDown: function(file) { + valuesStorage.moveDown(file); } }; setTimeout(function getWhistleVersion() { - http.get(config.registry, function(res) { - res.setEncoding('utf8'); - var body = ''; - res.on('data', function(data) { - body += data; + http.get(config.registry, function(res) { + res.setEncoding('utf8'); + var body = ''; + res.on('data', function(data) { + body += data; }); - res.on('error', util.noop); - res.on('end', function() { - var ver = util.parseJSON(body); - ver = ver && ver['dist-tags']; - if (ver = ver && ver['latest']) { - propertiesStorage.setProperty('latestVersion', ver); + res.on('error', util.noop); + res.on('end', function() { + var ver = util.parseJSON(body); + ver = ver && ver['dist-tags']; + if (ver = ver && ver['latest']) { + propertiesStorage.setProperty('latestVersion', ver); } }); - setTimeout(getWhistleVersion, 1000 * 60 * 60 * 12); + setTimeout(getWhistleVersion, 1000 * 60 * 60 * 12); }).on('error', util.noop); }, 1000); //等待package的信息配置更新完成 @@ -326,15 +326,15 @@ setTimeout(function getWhistleVersion() { */ exports.properties = { - set: function(name, value) { - typeof name == 'string' ? propertiesStorage.setProperty(name, value) : + set: function(name, value) { + typeof name == 'string' ? propertiesStorage.setProperty(name, value) : propertiesStorage.setProperties(name); }, - remove: function(name) { - propertiesStorage.removeProperty(name); + remove: function(name) { + propertiesStorage.removeProperty(name); }, - get: function(name) { - return propertiesStorage.getProperty(name); + get: function(name) { + return propertiesStorage.getProperty(name); } }; diff --git a/lib/util/data-server.js b/lib/util/data-server.js index 69b6fadd2..aeb7d95cb 100644 --- a/lib/util/data-server.js +++ b/lib/util/data-server.js @@ -11,22 +11,22 @@ var data = {}; var proxy, binded, timeout, interval; function disable() { - proxy.removeListener('request', handleRequest); - ids = []; - data = {}; - interval && clearInterval(interval); - interval = null; - binded = false; + proxy.removeListener('request', handleRequest); + ids = []; + data = {}; + interval && clearInterval(interval); + interval = null; + binded = false; } function enable() { - !binded && proxy.on('request', handleRequest); + !binded && proxy.on('request', handleRequest); - binded = true; - clearTimeout(timeout); - timeout = setTimeout(disable, TIMEOUT); - if (!interval) { - interval = setInterval(clearCache, CLEAR_INTERVAL); + binded = true; + clearTimeout(timeout); + timeout = setTimeout(disable, TIMEOUT); + if (!interval) { + interval = setInterval(clearCache, CLEAR_INTERVAL); } } @@ -36,112 +36,112 @@ function enable() { * 2. 请求#1前面的未结束且未被ui读取过的请求 */ function clearCache() { - var len = ids.length; - if (len <= MAX_LENGTH) { - return; + var len = ids.length; + if (len <= MAX_LENGTH) { + return; } - var index = -1; //已经完成,且缓存超过10s的最后一个请求 - var now = Date.now(); - for (var i = len - 1; i >= 0; i--) { - var curData = data[ids[i]]; - if (curData.endTime && now - curData.endTime > TIMEOUT) { - index = i; - break; + var index = -1; //已经完成,且缓存超过10s的最后一个请求 + var now = Date.now(); + for (var i = len - 1; i >= 0; i--) { + var curData = data[ids[i]]; + if (curData.endTime && now - curData.endTime > TIMEOUT) { + index = i; + break; } } - if (index < 0) { - return; + if (index < 0) { + return; } - var _ids = []; - ++index; - for (var i = 0; i < index; i++) { - var id = ids[i]; - var curData = data[id]; - if (curData.read && (!curData.endTime || now - curData.endTime < CACHE_TIME + var _ids = []; + ++index; + for (var i = 0; i < index; i++) { + var id = ids[i]; + var curData = data[id]; + if (curData.read && (!curData.endTime || now - curData.endTime < CACHE_TIME || now - curData.startTime < TIMEOUT)) { - _ids.push(id); + _ids.push(id); } else { - delete data[id]; - if (--len <= MIN_LENGTH) { - _ids.push.apply(_ids, ids.slice(i + 1, index)); - break; + delete data[id]; + if (--len <= MIN_LENGTH) { + _ids.push.apply(_ids, ids.slice(i + 1, index)); + break; } } } - ids = _ids.concat(ids.slice(index)); + ids = _ids.concat(ids.slice(index)); } function getIds(startTime, count) { - var len = ids.length; - if (!len) { - return []; + var len = ids.length; + if (!len) { + return []; } - startTime = ((startTime || Date.now() - 3000) + '').split('-'); - count = Math.min(count || COUNT, len); + startTime = ((startTime || Date.now() - 3000) + '').split('-'); + count = Math.min(count || COUNT, len); - startTime[0] = parseInt(startTime[0], 10) || 0; - startTime[1] = parseInt(startTime[1], 10) || 0; + startTime[0] = parseInt(startTime[0], 10) || 0; + startTime[1] = parseInt(startTime[1], 10) || 0; - if (compareId(ids[0], startTime)) { + if (compareId(ids[0], startTime)) { - return ids.slice(0, count); + return ids.slice(0, count); } - var end = len - 1; - if (!end || !compareId(ids[end], startTime)) { + var end = len - 1; + if (!end || !compareId(ids[end], startTime)) { - return []; + return []; } - var index = getIndex(startTime, 0, end); - return ids.slice(index, index + count); + var index = getIndex(startTime, 0, end); + return ids.slice(index, index + count); } function compareId(curId, refId) { - curId = curId.split('-'); - return curId[0] > refId[0] || (curId[0] == refId[0] && curId[1] > refId[1]); + curId = curId.split('-'); + return curId[0] > refId[0] || (curId[0] == refId[0] && curId[1] > refId[1]); } function getIndex(startTime, start, end) { - if (end - start <= 1) { - return compareId(ids[start], startTime) ? start : end; + if (end - start <= 1) { + return compareId(ids[start], startTime) ? start : end; } - var mid = Math.floor((start + end) / 2); - var id = ids[mid]; - return compareId(id, startTime) ? getIndex(startTime, start, mid) : getIndex(startTime, mid + 1, end); + var mid = Math.floor((start + end) / 2); + var id = ids[mid]; + return compareId(id, startTime) ? getIndex(startTime, start, mid) : getIndex(startTime, mid + 1, end); } function getList(ids) { - var result = []; - for (var i = 0, len = ids && ids.length; i < len; i++) { - var id = ids[i]; - var curData = data[id]; - if (curData) { - curData.read = true; - result[i] = curData; + var result = []; + for (var i = 0, len = ids && ids.length; i < len; i++) { + var id = ids[i]; + var curData = data[id]; + if (curData) { + curData.read = true; + result[i] = curData; } } - return result; + return result; } function handleRequest(req) { - var curData = req.data; - if (!util.filterUrl(curData.url)) { - return; + var curData = req.data; + if (!util.filterUrl(curData.url)) { + return; } - var id = curData.id = curData.id || (curData.startTime + '-' + ++count); - data[id] = curData; - ids.push(id); + var id = curData.id = curData.id || (curData.startTime + '-' + ++count); + data[id] = curData; + ids.push(id); } module.exports = function init(_proxy) { - proxy = _proxy; + proxy = _proxy; /** * options: { * startTime: timestamp || timestamp + '-' + count @@ -151,23 +151,23 @@ module.exports = function init(_proxy) { * * @param options */ - proxy.getData = function get(options) { - enable(); - options = options || {}; - var data = {}; - var newIds = options.startTime == -1 ? [] : getIds(options.startTime, options.count); - var list = getList(newIds).concat(getList(options.ids)); - for (var i = 0, len = list.length; i < len; i++) { - var item = list[i]; - if (item) { - data[item.id] = item; + proxy.getData = function get(options) { + enable(); + options = options || {}; + var data = {}; + var newIds = options.startTime == -1 ? [] : getIds(options.startTime, options.count); + var list = getList(newIds).concat(getList(options.ids)); + for (var i = 0, len = list.length; i < len; i++) { + var item = list[i]; + if (item) { + data[item.id] = item; } } - return { - ids: options.ids || [], - newIds: newIds, - data: data + return { + ids: options.ids || [], + newIds: newIds, + data: data }; }; }; \ No newline at end of file diff --git a/lib/util/file-writer-transform.js b/lib/util/file-writer-transform.js index 77deb46ed..aa0366e59 100644 --- a/lib/util/file-writer-transform.js +++ b/lib/util/file-writer-transform.js @@ -4,44 +4,44 @@ var config = require('../config'); var STATUS_CODES = require('http').STATUS_CODES || {}; function FileWriterTransform(writer, source, isRaw, req, isReq) { - if (!(this instanceof FileWriterTransform)) { - return new FileWriterTransform(options); + if (!(this instanceof FileWriterTransform)) { + return new FileWriterTransform(options); } - var self = this; - Transform.call(self); - self._writer = writer; - source.on('error', function() { - writer.end(); + var self = this; + Transform.call(self); + self._writer = writer; + source.on('error', function() { + writer.end(); }); - isRaw && writer.write(getRawData(source, req, isReq)); + isRaw && writer.write(getRawData(source, req, isReq)); } function getRawData(source, req, isReq) { - var firstLine = req ? ['HTTP/' + (req.httpVersion || '1.1'), source.statusCode, source.statusMessage || STATUS_CODES[source.statusCode] || ''].join(' ') + var firstLine = req ? ['HTTP/' + (req.httpVersion || '1.1'), source.statusCode, source.statusMessage || STATUS_CODES[source.statusCode] || ''].join(' ') : [source.method, source.url, 'HTTP/' + (source.httpVersion || '1.1')].join(' '); - var headers = []; - Object.keys(source.headers).forEach(function(key) { - var val = source.headers[key]; - if (!isReq || (key != config.HTTPS_FIELD && key != config.CLIENT_IP_HEAD)) { - headers.push(Array.isArray(val) ? val.map(function(item) { - return key + ': ' + item; + var headers = []; + Object.keys(source.headers).forEach(function(key) { + var val = source.headers[key]; + if (!isReq || (key != config.HTTPS_FIELD && key != config.CLIENT_IP_HEAD)) { + headers.push(Array.isArray(val) ? val.map(function(item) { + return key + ': ' + item; }).join('\r\n') : key + ': ' + val); } }); - return firstLine + '\r\n' + headers.join('\r\n') + '\r\n\r\n'; + return firstLine + '\r\n' + headers.join('\r\n') + '\r\n\r\n'; } util.inherits(FileWriterTransform, Transform); FileWriterTransform.prototype._transform = function(chunk, encoding, callback) { - if (chunk) { - this._writer.write(chunk); + if (chunk) { + this._writer.write(chunk); } else { - this._writer.end(); + this._writer.end(); } - callback(null, chunk); + callback(null, chunk); }; module.exports = FileWriterTransform; \ No newline at end of file diff --git a/lib/util/index.js b/lib/util/index.js index 786948ac0..26ca514ec 100644 --- a/lib/util/index.js +++ b/lib/util/index.js @@ -37,125 +37,125 @@ function noop() {} exports.noop = noop; function changePort(url, port) { - var index = url.indexOf('/', url.indexOf('://') + 3); - if (index != -1) { - var host = url.substring(0, index).replace(/:\d*$/, ''); - url = host + ':' + port + url.substring(index); + var index = url.indexOf('/', url.indexOf('://') + 3); + if (index != -1) { + var host = url.substring(0, index).replace(/:\d*$/, ''); + url = host + ':' + port + url.substring(index); } - return url; + return url; } exports.changePort = changePort; function getStatusCode(statusCode) { - statusCode |= 0; - return (statusCode < 100 || statusCode > 999) ? 0 : statusCode; + statusCode |= 0; + return (statusCode < 100 || statusCode > 999) ? 0 : statusCode; } exports.getStatusCode = getStatusCode; var scriptCache = {}; var VM_OPTIONS = { - displayErrors: false, - timeout: 100 + displayErrors: false, + timeout: 100 }; var MAX_SCRIPT_SIZE = 1024 * 256; var MAX_SCRIPT_CACHE_COUNT = 64; var MIN_SCRIPT_CACHE_COUNT = 32; function getScript(content) { - content = content.trim(); - var len = content.length; - if (!len || len > MAX_SCRIPT_SIZE) { - return; + content = content.trim(); + var len = content.length; + if (!len || len > MAX_SCRIPT_SIZE) { + return; } - var script = scriptCache[content]; - delete scriptCache[content]; + var script = scriptCache[content]; + delete scriptCache[content]; - var list = Object.keys(scriptCache); - if (list.length > MAX_SCRIPT_CACHE_COUNT) { - list = list.map(function(content) { - var script = scriptCache[content]; - script.content = content; - return script; + var list = Object.keys(scriptCache); + if (list.length > MAX_SCRIPT_CACHE_COUNT) { + list = list.map(function(content) { + var script = scriptCache[content]; + script.content = content; + return script; }).sort(function(a, b) { - return a.time > b.time ? -1 : 1; + return a.time > b.time ? -1 : 1; }).splice(0, MIN_SCRIPT_CACHE_COUNT); - scriptCache = {}; - list.forEach(function(script) { - scriptCache[script.content] = { - script: script.script, - time: script.time + scriptCache = {}; + list.forEach(function(script) { + scriptCache[script.content] = { + script: script.script, + time: script.time }; }); } - script = scriptCache[content] = script || { - script: new vm.Script(content) + script = scriptCache[content] = script || { + script: new vm.Script(content) }; - script.time = Date.now(); + script.time = Date.now(); - return script.script; + return script.script; } function execScriptSync(script, context) { - try { - if (script = getScript(script)) { - script.runInNewContext(context, VM_OPTIONS); + try { + if (script = getScript(script)) { + script.runInNewContext(context, VM_OPTIONS); } - return true; + return true; } catch(e) { - logger.error(e); + logger.error(e); } } exports.execScriptSync = execScriptSync; function toMultipart(name, value) { - if (value == null) { - value = ''; + if (value == null) { + value = ''; } - if (typeof value == 'object') { - var filename = value.filename || value.name; - filename = filename == null ? '' : filename + ''; - value = value.content || value.value || ''; - return new Buffer('Content-Disposition: form-data; name="' + name + '"; filename="' + filename + if (typeof value == 'object') { + var filename = value.filename || value.name; + filename = filename == null ? '' : filename + ''; + value = value.content || value.value || ''; + return new Buffer('Content-Disposition: form-data; name="' + name + '"; filename="' + filename + '"\r\nContent-Type: ' + mime.lookup(filename) + '\r\n\r\n' + value); } - return new Buffer('Content-Disposition: form-data; name="' + name + '"\r\n\r\n' + value); + return new Buffer('Content-Disposition: form-data; name="' + name + '"\r\n\r\n' + value); } exports.toMultipart = toMultipart; function toMultiparts(params, boundary) { - var content = Object.keys(params).map(function(name) { - return boundary + '\r\n' + toMultipart(name, params[name]); + var content = Object.keys(params).map(function(name) { + return boundary + '\r\n' + toMultipart(name, params[name]); }).join('\r\n'); - return new Buffer(content ? '\r\n' + content : ''); + return new Buffer(content ? '\r\n' + content : ''); } exports.toMultiparts = toMultiparts; function getFileWriter(file, callback) { - if (!file || fileWriterCache[file]) { - return callback(); + if (!file || fileWriterCache[file]) { + return callback(); } - var execCallback = function(writer) { - delete fileWriterCache[file]; - callback(writer); + var execCallback = function(writer) { + delete fileWriterCache[file]; + callback(writer); }; - fs.stat(file, function(err, stat) { - if (!err) { - return execCallback(); + fs.stat(file, function(err, stat) { + if (!err) { + return execCallback(); } - logger.warn(err); - fse.ensureFile(file, function(err) { - execCallback(err ? null : fs.createWriteStream(file).on('error', logger.error)); - logger.error(err); + logger.warn(err); + fse.ensureFile(file, function(err) { + execCallback(err ? null : fs.createWriteStream(file).on('error', logger.error)); + logger.error(err); }); }); } @@ -163,77 +163,77 @@ function getFileWriter(file, callback) { exports.getFileWriter = getFileWriter; function getFileWriters(files, callback) { - if (!Array.isArray(files)) { - files = [files]; + if (!Array.isArray(files)) { + files = [files]; } - Q.all(files.map(function(file) { - var defer = Q.defer(); - getFileWriter(file, function(writer) { - defer.resolve(writer); + Q.all(files.map(function(file) { + var defer = Q.defer(); + getFileWriter(file, function(writer) { + defer.resolve(writer); }); - return defer.promise; + return defer.promise; })).spread(callback); } exports.getFileWriters = getFileWriters; function clone(obj) { - if (!obj || typeof obj != 'object') { - return obj; + if (!obj || typeof obj != 'object') { + return obj; } - var result = Array.isArray(obj) ? [] : {}; - Object.keys(obj).forEach(function(name) { - result[name] = clone(obj[name]); + var result = Array.isArray(obj) ? [] : {}; + Object.keys(obj).forEach(function(name) { + result[name] = clone(obj[name]); }); - return result; + return result; } exports.clone = clone; function toBuffer(buf) { - if (buf == null || buf instanceof Buffer) { - return buf; + if (buf == null || buf instanceof Buffer) { + return buf; } - return new Buffer(buf + ''); + return new Buffer(buf + ''); } exports.toBuffer = toBuffer; exports.mkdir = function mkdir(path) { - !fs.existsSync(path) && fs.mkdirSync(path); - return path; + !fs.existsSync(path) && fs.mkdirSync(path); + return path; }; function getErrorStack(err) { - if (!err) { - return ''; + if (!err) { + return ''; } - var stack; - try { - stack = err.stack; + var stack; + try { + stack = err.stack; } catch(e) {} - return 'Date: ' + formatDate() + '\r\n' + (stack || err.message || err); + return 'Date: ' + formatDate() + '\r\n' + (stack || err.message || err); } exports.getErrorStack = getErrorStack; function formatDate(now) { - now = now || new Date(); - var date = [now.getFullYear(), paddingLeft(now.getMonth() + 1), + now = now || new Date(); + var date = [now.getFullYear(), paddingLeft(now.getMonth() + 1), paddingLeft(now.getDate())].join('-'); - var time = [paddingLeft(now.getHours()), paddingLeft(now.getMinutes()), + var time = [paddingLeft(now.getHours()), paddingLeft(now.getMinutes()), paddingLeft(now.getSeconds())].join(':'); - return date + ' ' + time + '.' + (now % 1000); + return date + ' ' + time + '.' + (now % 1000); } function paddingLeft(num) { - return num < 10 ? '0' + num : num; + return num < 10 ? '0' + num : num; } exports.formatDate = formatDate; @@ -241,148 +241,148 @@ exports.formatDate = formatDate; var REG_EXP_RE = /^\/(.+)\/(i)?$/; exports.isRegExp = function isRegExp(regExp) { - return REG_EXP_RE.test(regExp); + return REG_EXP_RE.test(regExp); }; var ORIG_REG_EXP = /^\/(.+)\/([igm]{0,3})$/; exports.isOriginalRegExp = function isOriginalRegExp(regExp) { - if (!ORIG_REG_EXP.test(regExp) || /[igm]{2}/.test(regExp.$2)) { - return false; + if (!ORIG_REG_EXP.test(regExp) || /[igm]{2}/.test(regExp.$2)) { + return false; } - return true; + return true; }; exports.toOriginalRegExp = function toRegExp(regExp) { - regExp = ORIG_REG_EXP.test(regExp); - try { - regExp = regExp && new RegExp(RegExp.$1, RegExp.$2); + regExp = ORIG_REG_EXP.test(regExp); + try { + regExp = regExp && new RegExp(RegExp.$1, RegExp.$2); } catch(e) { - regExp = null; + regExp = null; } - return regExp; + return regExp; }; exports.emitError = function(obj, err) { - if (obj) { - obj.once('error', noop); - obj.emit('error', err || new Error('Unknown')); + if (obj) { + obj.once('error', noop); + obj.emit('error', err || new Error('Unknown')); } }; exports.indexOfList = function(buf, subBuf, start) { - start = start || 0; - if (buf.indexOf) { - return buf.indexOf(subBuf, start); + start = start || 0; + if (buf.indexOf) { + return buf.indexOf(subBuf, start); } - var subLen = subBuf.length; - if (subLen) { - for (var i = start, len = buf.length - subLen; i <= len; i++) { - var j = 0; - for (; j < subLen; j++) { - if (subBuf[j] !== buf[i + j]) { - break; + var subLen = subBuf.length; + if (subLen) { + for (var i = start, len = buf.length - subLen; i <= len; i++) { + var j = 0; + for (; j < subLen; j++) { + if (subBuf[j] !== buf[i + j]) { + break; } } - if (j == subLen) { - return i; + if (j == subLen) { + return i; } } } - return -1; + return -1; }; exports.startWithList = function(buf, subBuf, start) { - var len = subBuf.length; - if (!len) { - return false; + var len = subBuf.length; + if (!len) { + return false; } - start = start || 0; - for (var i = 0; i < len; i++) { - if (buf[i + start] != subBuf[i]) { - return false; + start = start || 0; + for (var i = 0; i < len; i++) { + if (buf[i + start] != subBuf[i]) { + return false; } } - return true; + return true; }; exports.endWithList = function(buf, subBuf, end) { - var subLen = subBuf.length; - if (!subLen) { - return false; + var subLen = subBuf.length; + if (!subLen) { + return false; } - if (!(end >= 0)) { - end = buf.length - 1; + if (!(end >= 0)) { + end = buf.length - 1; } - for (var i = 0; i < subLen; i++) { - if (subBuf[subLen - i - 1] != buf[end - i]) { - return false; + for (var i = 0; i < subLen; i++) { + if (subBuf[subLen - i - 1] != buf[end - i]) { + return false; } } - return true; + return true; }; exports.getHost = function parseHost(_url) { - _url = url.parse(setProtocol(_url || '')).hostname; - return _url && _url.toLowerCase(); + _url = url.parse(setProtocol(_url || '')).hostname; + return _url && _url.toLowerCase(); }; exports.setTimeout = function(callback) { - var timeout = parseInt(config.timeout, 10); - return setTimeout(callback, timeout > 0 ? timeout : 36000); + var timeout = parseInt(config.timeout, 10); + return setTimeout(callback, timeout > 0 ? timeout : 36000); }; exports.toRegExp = function toRegExp(regExp) { - regExp = REG_EXP_RE.test(regExp); - try { - regExp = regExp && new RegExp(RegExp.$1, RegExp.$2); + regExp = REG_EXP_RE.test(regExp); + try { + regExp = regExp && new RegExp(RegExp.$1, RegExp.$2); } catch(e) { - regExp = null; + regExp = null; } - return regExp; + return regExp; }; exports.getFullUrl = function getFullUrl(req) { - if (hasProtocol(req.url)) { - req.url = url.parse(req.url).path; + if (hasProtocol(req.url)) { + req.url = url.parse(req.url).path; } - var host = req.headers.host; - if (host) { - host = req.isHttps ? host.replace(/:443$/, '') : host.replace(/:80$/, ''); + var host = req.headers.host; + if (host) { + host = req.isHttps ? host.replace(/:443$/, '') : host.replace(/:80$/, ''); } - return _getProtocol(req.isHttps) + host + req.url; + return _getProtocol(req.isHttps) + host + req.url; }; function setProtocol(url, isHttps) { - return hasProtocol(url) ? url : _getProtocol(isHttps) + url; + return hasProtocol(url) ? url : _getProtocol(isHttps) + url; } function _getProtocol(isHttps) { - return isHttps ? 'https://' : 'http://'; + return isHttps ? 'https://' : 'http://'; } function hasProtocol(url) { - return /^[a-z0-9.+-]+:\/\//i.test(url); + return /^[a-z0-9.+-]+:\/\//i.test(url); } function getProtocol(url) { - return hasProtocol(url) ? url.substring(0, url.indexOf('://') + 1) : null; + return hasProtocol(url) ? url.substring(0, url.indexOf('://') + 1) : null; } function removeProtocol(url, clear) { - return hasProtocol(url) ? url.substring(url.indexOf('://') + (clear ? 3 : 1)) : url; + return hasProtocol(url) ? url.substring(url.indexOf('://') + (clear ? 3 : 1)) : url; } function replaceProtocol(url, protocol) { - return (protocol || 'http:') + removeProtocol(url); + return (protocol || 'http:') + removeProtocol(url); } exports.hasProtocol = hasProtocol; @@ -392,56 +392,56 @@ exports.removeProtocol = removeProtocol; exports.replaceProtocol = replaceProtocol; function disableCSP(headers) { - delete headers['content-security-policy']; - delete headers['content-security-policy-report-only']; - delete headers['x-content-security-policy']; - delete headers['x-content-security-policy-report-only']; - delete headers['x-webkit-csp']; + delete headers['content-security-policy']; + delete headers['content-security-policy-report-only']; + delete headers['x-content-security-policy']; + delete headers['x-content-security-policy-report-only']; + delete headers['x-webkit-csp']; } exports.disableCSP = disableCSP; function isLocalAddress(address) { - if (!address || typeof address != 'string') { - return false; + if (!address || typeof address != 'string') { + return false; } - if (address == '127.0.0.1' || address == '0:0:0:0:0:0:0:1') { - return true; + if (address == '127.0.0.1' || address == '0:0:0:0:0:0:0:1') { + return true; } - address = address.toLowerCase(); - var interfaces = os.networkInterfaces(); - for (var i in interfaces) { - var list = interfaces[i]; - if (Array.isArray(list)) { - for (var j = 0, info; info = list[j]; j++) { - if (info.address.toLowerCase() == address) { - return true; + address = address.toLowerCase(); + var interfaces = os.networkInterfaces(); + for (var i in interfaces) { + var list = interfaces[i]; + if (Array.isArray(list)) { + for (var j = 0, info; info = list[j]; j++) { + if (info.address.toLowerCase() == address) { + return true; } } } } - return false; + return false; } exports.isLocalAddress = isLocalAddress; exports.drain = function drain(stream, endHandler) { - var emitEndStream = new PassThrough(); - emitEndStream.on('data', noop) + var emitEndStream = new PassThrough(); + emitEndStream.on('data', noop) .on('error', noop); - typeof endHandler == 'function' && emitEndStream.on('end', endHandler); - stream.pipe(emitEndStream); + typeof endHandler == 'function' && emitEndStream.on('end', endHandler); + stream.pipe(emitEndStream); }; exports.encodeNonAsciiChar = function encodeNonAsciiChar(str) { - if (!str || typeof str != 'string') { - return ''; + if (!str || typeof str != 'string') { + return ''; } - return str && str.replace(/[^\x00-\x7F]/g, safeEncodeURIComponent); + return str && str.replace(/[^\x00-\x7F]/g, safeEncodeURIComponent); }; /** @@ -451,455 +451,455 @@ exports.encodeNonAsciiChar = function encodeNonAsciiChar(str) { * @returns */ function safeEncodeURIComponent(ch) { - try { - return encodeURIComponent(ch); + try { + return encodeURIComponent(ch); } catch(e) {} - return ch; + return ch; } exports.encodeURIComponent = safeEncodeURIComponent; function getPath(url, noProtocol) { - if (url) { - url = url.replace(/\/?[?#].*$/, ''); - var index = noProtocol ? -1 : url.indexOf('://'); - url = index > -1 ? url.substring(index + 3) : url; + if (url) { + url = url.replace(/\/?[?#].*$/, ''); + var index = noProtocol ? -1 : url.indexOf('://'); + url = index > -1 ? url.substring(index + 3) : url; } - return url; + return url; } exports.getPath = getPath; function getFilename(url) { - if (typeof url == 'string' && (url = getPath(url).trim())) { - var index = url.lastIndexOf('/'); - if (index != -1) { - url = url.substring(index + 1); + if (typeof url == 'string' && (url = getPath(url).trim())) { + var index = url.lastIndexOf('/'); + if (index != -1) { + url = url.substring(index + 1); } else { - url = null; + url = null; } } else { - url = null; + url = null; } - return url || 'index.html'; + return url || 'index.html'; } exports.getFilename = getFilename; function disableReqCache(headers) { - delete headers['if-modified-since']; - delete headers['if-none-match']; - delete headers['last-modified']; - delete headers.etag; + delete headers['if-modified-since']; + delete headers['if-none-match']; + delete headers['last-modified']; + delete headers.etag; - headers['pragma'] = 'no-cache'; - headers['cache-control'] = 'no-cache'; + headers['pragma'] = 'no-cache'; + headers['cache-control'] = 'no-cache'; } exports.disableReqCache = disableReqCache; function wrapResponse(res) { - var passThrough = new PassThrough(); - passThrough.statusCode = res.statusCode; - passThrough.headers = lowerCaseify(res.headers); - passThrough.trailers = lowerCaseify(res.trailers); - passThrough.headers.server = config.name; - res.body != null && passThrough.push(String(res.body)); - passThrough.push(null); - return passThrough; + var passThrough = new PassThrough(); + passThrough.statusCode = res.statusCode; + passThrough.headers = lowerCaseify(res.headers); + passThrough.trailers = lowerCaseify(res.trailers); + passThrough.headers.server = config.name; + res.body != null && passThrough.push(String(res.body)); + passThrough.push(null); + return passThrough; } exports.wrapResponse = wrapResponse; function wrapGatewayError(body) { - return wrapResponse({ - statusCode: 502, - headers: { - 'content-type': 'text/plain' + return wrapResponse({ + statusCode: 502, + headers: { + 'content-type': 'text/plain' }, - body: body + body: body }); } exports.wrapGatewayError = wrapGatewayError; exports.sendStatusCodeError = function(cltRes, svrRes) { - delete svrRes.headers['content-length']; - cltRes.writeHead(502, svrRes.headers); - cltRes.src(wrapGatewayError('Invalid status code: ' + svrRes.statusCode)); + delete svrRes.headers['content-length']; + cltRes.writeHead(502, svrRes.headers); + cltRes.src(wrapGatewayError('Invalid status code: ' + svrRes.statusCode)); }; function parseInlineJSON(text, isValue) { - if (!text || typeof text != 'string' || /\s/.test(text) + if (!text || typeof text != 'string' || /\s/.test(text) || (!isValue && (/\\|\//.test(text) && !/^&/.test(text)))) { - return; + return; } - return qs.parse(text); + return qs.parse(text); } function parseLinesJSON(text) { - if (!text || typeof text != 'string' + if (!text || typeof text != 'string' || !(text = text.trim()) || /^[\{\[]/.test(text)) { - return null; + return null; } - var obj = {}; - text.split(/\r\n|\n|\r/g).forEach(function(line) { - if (line = line.trim()) { - var index = line.indexOf(': '); - if (index != -1) { - var name = line.substring(0, index).trim(); - obj[name] = line.substring(index + 2).trim(); + var obj = {}; + text.split(/\r\n|\n|\r/g).forEach(function(line) { + if (line = line.trim()) { + var index = line.indexOf(': '); + if (index != -1) { + var name = line.substring(0, index).trim(); + obj[name] = line.substring(index + 2).trim(); } else { - obj[line.trim()] = ''; + obj[line.trim()] = ''; } } }); - return obj; + return obj; } function parseJSON(data) { - return _parseJSON(data, true) || parseLinesJSON(data); + return _parseJSON(data, true) || parseLinesJSON(data); } function _parseJSON(data, isValue) { - if (typeof data != 'string' || !(data = data.trim())) { - return null; + if (typeof data != 'string' || !(data = data.trim())) { + return null; } - try { - return JSON.parse(data); + try { + return JSON.parse(data); } catch(e) { - logger.error(e); + logger.error(e); } - return parseInlineJSON(data, isValue); + return parseInlineJSON(data, isValue); } exports.parseJSON = parseJSON; function readFiles(files, callback) { - if (!Array.isArray(files)) { - files = [files]; + if (!Array.isArray(files)) { + files = [files]; } - Q.all(files.map(function(file) { - var defer = Q.defer(); - if (file && typeof file == 'string') { - fs.readFile(file, UTF8_OPTIONS, function(err, data) { - defer.resolve(err ? null : data); - logger.error(err); + Q.all(files.map(function(file) { + var defer = Q.defer(); + if (file && typeof file == 'string') { + fs.readFile(file, UTF8_OPTIONS, function(err, data) { + defer.resolve(err ? null : data); + logger.error(err); }); } else { - defer.resolve(); + defer.resolve(); } - return defer.promise; + return defer.promise; })).spread(callback); } exports.readFiles = readFiles; function readFileSync(file) { - try { - return fs.readFileSync(file, UTF8_OPTIONS); + try { + return fs.readFileSync(file, UTF8_OPTIONS); } catch(e) { - logger.error(e); + logger.error(e); } } exports.readFileSync = readFileSync; function trim(text) { - return text && text.trim(); + return text && text.trim(); } exports.trim = trim; function readInjectFiles(data, callback) { - if (!data) { - return callback(); + if (!data) { + return callback(); } - readFiles([data.prepend, data.replace, data.append], function(top, body, bottom) { - if (top != null) { - data.top = top; + readFiles([data.prepend, data.replace, data.append], function(top, body, bottom) { + if (top != null) { + data.top = top; } - if (body != null) { - data.body = body; + if (body != null) { + data.body = body; } - if (bottom != null) { - data.bottom = bottom; + if (bottom != null) { + data.bottom = bottom; } - callback(data); + callback(data); }); } exports.readInjectFiles = readInjectFiles; function lowerCaseify(obj) { - var result = {}; - for (var i in obj) { - var value = obj[i]; - if (value !== undefined) { - result[i.toLowerCase()] = Array.isArray(value) ? value : value + ''; + var result = {}; + for (var i in obj) { + var value = obj[i]; + if (value !== undefined) { + result[i.toLowerCase()] = Array.isArray(value) ? value : value + ''; } } - return result; + return result; } exports.lowerCaseify = lowerCaseify; function parseHeaders(headers) { - if (typeof headers == 'string') { - headers = headers.split(CRLF_RE); + if (typeof headers == 'string') { + headers = headers.split(CRLF_RE); } - var _headers = {}; - headers.forEach(function(line) { - var index = line.indexOf(':'); - var value; - if (index != -1 && (value = line.substring(index + 1).trim())) { - var name = line.substring(0, index).trim().toLowerCase(); - var list = _headers[name]; - if (list) { - if (!Array.isArray(list)) { - _headers[name] = list = [list]; + var _headers = {}; + headers.forEach(function(line) { + var index = line.indexOf(':'); + var value; + if (index != -1 && (value = line.substring(index + 1).trim())) { + var name = line.substring(0, index).trim().toLowerCase(); + var list = _headers[name]; + if (list) { + if (!Array.isArray(list)) { + _headers[name] = list = [list]; } - list.push(value); + list.push(value); } else { - _headers[name] = value; + _headers[name] = value; } } }); - return lowerCaseify(_headers); + return lowerCaseify(_headers); } exports.parseHeaders = parseHeaders; function parseRuleJson(rules, callback) { - if (!Array.isArray(rules)) { - rules = [rules]; + if (!Array.isArray(rules)) { + rules = [rules]; } - Q.all(rules.map(function(rule) { - var defer = Q.defer(); - var json = _parseJSON(rule && removeProtocol(getMatcher(rule), true)); - if (json) { - defer.resolve(json); + Q.all(rules.map(function(rule) { + var defer = Q.defer(); + var json = _parseJSON(rule && removeProtocol(getMatcher(rule), true)); + if (json) { + defer.resolve(json); } else { - _getRuleValue(rule, function(data) { - defer.resolve(parseJSON(data)); + _getRuleValue(rule, function(data) { + defer.resolve(parseJSON(data)); }); } - return defer.promise; + return defer.promise; })).spread(callback); } exports.parseRuleJson = parseRuleJson; function _getRuleValue(rule, callback) { - if (!rule) { - return callback(); + if (!rule) { + return callback(); } - if (rule.value) { - return callback(removeProtocol(rule.value, true)); + if (rule.value) { + return callback(removeProtocol(rule.value, true)); } - var filePath = decodePath(getPath(getMatcher(rule))); - if (rule.root) { - filePath = join(rule.root, filePath); + var filePath = decodePath(getPath(getMatcher(rule))); + if (rule.root) { + filePath = join(rule.root, filePath); } - protoMgr.isBinProtocol(rule.name) ? fs.readFile(filePath, function(err, data) { - callback(err ? null : data); - logger.error(err); + protoMgr.isBinProtocol(rule.name) ? fs.readFile(filePath, function(err, data) { + callback(err ? null : data); + logger.error(err); }) : fs.readFile(filePath, UTF8_OPTIONS, function(err, data) { - callback(err ? null : data); - logger.error(err); + callback(err ? null : data); + logger.error(err); }); } function getRuleValue(rules, callback, noBody) { - if (noBody) { - return callback(); + if (noBody) { + return callback(); } - if (!Array.isArray(rules)) { - rules = [rules]; + if (!Array.isArray(rules)) { + rules = [rules]; } - Q.all(rules.map(function(rule) { - var defer = Q.defer(); - _getRuleValue(rule, function(data) { - defer.resolve(data); + Q.all(rules.map(function(rule) { + var defer = Q.defer(); + _getRuleValue(rule, function(data) { + defer.resolve(data); }); - return defer.promise; + return defer.promise; })).spread(callback); } exports.getRuleValue = getRuleValue; function decodePath(path) { - path = getPath(path, true); - try { - return decodeURIComponent(path); + path = getPath(path, true); + try { + return decodeURIComponent(path); } catch (e) { - logger.error(e); + logger.error(e); } - try { - return qs.unescape(path); + try { + return qs.unescape(path); } catch(e) { - logger.error(e); + logger.error(e); } - return path; + return path; } function getRuleFiles(rule) { - var files = rule.files || [getPath(getUrl(rule))]; - var root = rule.root; - return files.map(function(file) { - return root ? join(root, decodePath(file)) : decodePath(file); + var files = rule.files || [getPath(getUrl(rule))]; + var root = rule.root; + return files.map(function(file) { + return root ? join(root, decodePath(file)) : decodePath(file); }); } exports.getRuleFiles = getRuleFiles; function getRuleFile(rule) { - var filePath = getPath(getUrl(rule)); - if (!filePath) { - return filePath; + var filePath = getPath(getUrl(rule)); + if (!filePath) { + return filePath; } - return rule.root ? join(rule.root, decodePath(filePath)) : decodePath(filePath); + return rule.root ? join(rule.root, decodePath(filePath)) : decodePath(filePath); } exports.getRuleFile = getRuleFile; function getValue(rule) { - return rule.value || rule.path; + return rule.value || rule.path; } function getMatcher(rule) { - return rule && (getValue(rule) || rule.matcher); + return rule && (getValue(rule) || rule.matcher); } function getUrl(rule) { - return rule && (getValue(rule) || rule.url); + return rule && (getValue(rule) || rule.url); } exports.rule = { - getMatcher: getMatcher, - getUrl: getUrl, - getProxy: function getProxy(rule) { - var proxyUrl = getMatcher(rule); - return protoMgr.isProxyProtocol(getProtocol(proxyUrl)) ? proxyUrl : null; + getMatcher: getMatcher, + getUrl: getUrl, + getProxy: function getProxy(rule) { + var proxyUrl = getMatcher(rule); + return protoMgr.isProxyProtocol(getProtocol(proxyUrl)) ? proxyUrl : null; } }; function getMatcherValue(rule) { - rule = getMatcher(rule); - return rule && removeProtocol(rule, true); + rule = getMatcher(rule); + return rule && removeProtocol(rule, true); } exports.getMatcherValue = getMatcherValue; function getContentType(contentType) { - if (contentType && typeof contentType != 'string') { - contentType = contentType['content-type'] || contentType.contentType; + if (contentType && typeof contentType != 'string') { + contentType = contentType['content-type'] || contentType.contentType; } - if (typeof contentType == 'string') { - contentType = contentType.toLowerCase(); - if (contentType.indexOf('javascript') != -1) { - return 'JS'; + if (typeof contentType == 'string') { + contentType = contentType.toLowerCase(); + if (contentType.indexOf('javascript') != -1) { + return 'JS'; } - if (contentType.indexOf('css') != -1) { - return 'CSS'; + if (contentType.indexOf('css') != -1) { + return 'CSS'; } - if (contentType.indexOf('html') != -1) { - return 'HTML'; + if (contentType.indexOf('html') != -1) { + return 'HTML'; } - if (contentType.indexOf('json') != -1) { - return 'JSON'; + if (contentType.indexOf('json') != -1) { + return 'JSON'; } - if (contentType.indexOf('xml') != -1) { - return 'XML'; + if (contentType.indexOf('xml') != -1) { + return 'XML'; } - if (contentType.indexOf('text/') != -1) { - return 'TEXT'; + if (contentType.indexOf('text/') != -1) { + return 'TEXT'; } - if (contentType.indexOf('image') != -1) { - return 'IMG'; + if (contentType.indexOf('image') != -1) { + return 'IMG'; } } - return null; + return null; } exports.getContentType = getContentType; function supportHtmlTransform(res) { - var headers = res.headers; - if (getContentType(headers) != 'HTML' || !hasBody(res)) { - return false; + var headers = res.headers; + if (getContentType(headers) != 'HTML' || !hasBody(res)) { + return false; } - var contentEncoding = toLowerCase(headers && headers['content-encoding']); + var contentEncoding = toLowerCase(headers && headers['content-encoding']); //chrome新增了sdch压缩算法,对此类响应无法解码,deflate无法区分deflate还是deflateRaw - return !contentEncoding || contentEncoding == 'gzip'; + return !contentEncoding || contentEncoding == 'gzip'; } exports.supportHtmlTransform = supportHtmlTransform; function removeUnsupportsHeaders(headers, supportsDeflate) {//只保留支持的zip格式:gzip、deflate - if (!headers || !headers['accept-encoding']) { - return; + if (!headers || !headers['accept-encoding']) { + return; } - var list = headers['accept-encoding'].split(/\s*,\s*/g); - var acceptEncoding = []; - for (var i = 0, len = list.length; i < len; i++) { - var ae = list[i].toLowerCase(); - if (ae && (supportsDeflate && ae == 'deflate' || ae == 'gzip')) { - acceptEncoding.push(ae); + var list = headers['accept-encoding'].split(/\s*,\s*/g); + var acceptEncoding = []; + for (var i = 0, len = list.length; i < len; i++) { + var ae = list[i].toLowerCase(); + if (ae && (supportsDeflate && ae == 'deflate' || ae == 'gzip')) { + acceptEncoding.push(ae); } } - if (acceptEncoding = acceptEncoding.join(', ')) { - headers['accept-encoding'] = acceptEncoding; + if (acceptEncoding = acceptEncoding.join(', ')) { + headers['accept-encoding'] = acceptEncoding; } else { - delete headers['accept-encoding']; + delete headers['accept-encoding']; } } exports.removeUnsupportsHeaders = removeUnsupportsHeaders; function hasBody(res) { - var statusCode = res.statusCode; - return !(statusCode == 204 || (statusCode >= 300 && statusCode < 400) || + var statusCode = res.statusCode; + return !(statusCode == 204 || (statusCode >= 300 && statusCode < 400) || (100 <= statusCode && statusCode <= 199)); } exports.hasBody = hasBody; function hasRequestBody(req) { - req = typeof req == 'string' ? req : req.method; - if (typeof req != 'string') { - return false; + req = typeof req == 'string' ? req : req.method; + if (typeof req != 'string') { + return false; } - req = req.toUpperCase(); - return !(req === 'GET' || req === 'HEAD' || + req = req.toUpperCase(); + return !(req === 'GET' || req === 'HEAD' || req === 'DELETE' || req === 'OPTIONS' || req === 'CONNECT'); } @@ -907,103 +907,103 @@ function hasRequestBody(req) { exports.hasRequestBody = hasRequestBody; function getPipeZipStream(headers) { - var pipeStream = new PipeStream(); - switch (toLowerCase(headers && headers['content-encoding'])) { + var pipeStream = new PipeStream(); + switch (toLowerCase(headers && headers['content-encoding'])) { case 'gzip': - pipeStream.addHead(zlib.createGunzip()); - pipeStream.addTail(zlib.createGzip()); - break; + pipeStream.addHead(zlib.createGunzip()); + pipeStream.addTail(zlib.createGzip()); + break; case 'deflate': - pipeStream.addHead(zlib.createInflate()); - pipeStream.addTail(zlib.createDeflate()); - break; + pipeStream.addHead(zlib.createInflate()); + pipeStream.addTail(zlib.createDeflate()); + break; } - return pipeStream; + return pipeStream; } exports.getPipeZipStream = getPipeZipStream; function isEmptyObject(obj) { - return !obj || !Object.keys(obj).length; + return !obj || !Object.keys(obj).length; } exports.isEmptyObject = isEmptyObject; function getPipeIconvStream(headers, plainText) { - var pipeStream = new PipeStream(); - var charset = plainText ? null : getCharset(headers['content-type']); + var pipeStream = new PipeStream(); + var charset = plainText ? null : getCharset(headers['content-type']); - if (charset) { - pipeStream.addHead(iconv.decodeStream(charset)); - pipeStream.addTail(iconv.encodeStream(charset)); + if (charset) { + pipeStream.addHead(iconv.decodeStream(charset)); + pipeStream.addTail(iconv.encodeStream(charset)); } else { - pipeStream.addHead(function(res, next) { - var buffer, iconvDecoder; - var decoder = new StringDecoder(); - var content = ''; + pipeStream.addHead(function(res, next) { + var buffer, iconvDecoder; + var decoder = new StringDecoder(); + var content = ''; - res.on('data', function(chunk) { - buffer = buffer ? Buffer.concat([buffer, chunk]) : chunk; - if (!charset) { - try { - content += chunk ? decoder.write(chunk) : decoder.end(); + res.on('data', function(chunk) { + buffer = buffer ? Buffer.concat([buffer, chunk]) : chunk; + if (!charset) { + try { + content += chunk ? decoder.write(chunk) : decoder.end(); } catch(e) {//可能抛出异常RangeError: out of range index,具体原因未知 - content = (buffer || '') + ''; - logger.error(e); + content = (buffer || '') + ''; + logger.error(e); } - if (!plainText) {//如果没charset - charset = getMetaCharset(content); + if (!plainText) {//如果没charset + charset = getMetaCharset(content); } } - resolveCharset(buffer); + resolveCharset(buffer); }); - res.on('end', resolveCharset); + res.on('end', resolveCharset); - function resolveCharset(chunk) { - if (!charset && (!chunk || content.length >= 51200)) { - charset = content.indexOf('�') != -1 ? 'gbk' : 'utf8'; - content = null; + function resolveCharset(chunk) { + if (!charset && (!chunk || content.length >= 51200)) { + charset = content.indexOf('�') != -1 ? 'gbk' : 'utf8'; + content = null; } - if (!charset) { - return; + if (!charset) { + return; } - if (!iconvDecoder) { - iconvDecoder = iconv.decodeStream(charset); - next(iconvDecoder); + if (!iconvDecoder) { + iconvDecoder = iconv.decodeStream(charset); + next(iconvDecoder); } - if (buffer) { - iconvDecoder.write(buffer); - buffer = null; + if (buffer) { + iconvDecoder.write(buffer); + buffer = null; } - !chunk && iconvDecoder.end(); + !chunk && iconvDecoder.end(); } }); - pipeStream.addTail(function(src, next) { - next(src.pipe(iconv.encodeStream(charset))); + pipeStream.addTail(function(src, next) { + next(src.pipe(iconv.encodeStream(charset))); }); } - return pipeStream; + return pipeStream; } exports.getPipeIconvStream = getPipeIconvStream; function toLowerCase(str) { - return typeof str == 'string' ? str.trim().toLowerCase() : str; + return typeof str == 'string' ? str.trim().toLowerCase() : str; } exports.toLowerCase = toLowerCase; function toUpperCase(str) { - return typeof str == 'string' ? str.trim().toUpperCase() : str; + return typeof str == 'string' ? str.trim().toUpperCase() : str; } exports.toUpperCase = toUpperCase; @@ -1013,222 +1013,222 @@ var META_CHARSET_RE = /]*\bcharset=(?:'|")?([\w-]+)[^>]*>/i; function getCharset(str) { - return _getCharset(str); + return _getCharset(str); } function getMetaCharset(str) { - return _getCharset(str, true); + return _getCharset(str, true); } function _getCharset(str, isMeta) { - var charset; - if ((isMeta ? META_CHARSET_RE : CHARSET_RE).test(str)) { - charset = RegExp.$1; - if (!iconv.encodingExists(charset)) { - charset = null; + var charset; + if ((isMeta ? META_CHARSET_RE : CHARSET_RE).test(str)) { + charset = RegExp.$1; + if (!iconv.encodingExists(charset)) { + charset = null; } } - return charset; + return charset; } exports.getCharset = getCharset; exports.getMetaCharset = getMetaCharset; function getClientIp(req, forwarded) { - var ip; - var headers = req.headers || {}; - try { - ip = (forwarded && headers['x-forwarded-for']) + var ip; + var headers = req.headers || {}; + try { + ip = (forwarded && headers['x-forwarded-for']) || headers[config.CLIENT_IP_HEAD] || req.connection.remoteAddress || req.socket.remoteAddress; } catch(e) {} - return removeIPV6Prefix(ip); + return removeIPV6Prefix(ip); } exports.getClientIp = getClientIp; function removeIPV6Prefix(ip) { - if (typeof ip != 'string') { - return ip; + if (typeof ip != 'string') { + return ip; } - return ip.indexOf('::ffff:') === 0 ? ip.substring(7) : ip; + return ip.indexOf('::ffff:') === 0 ? ip.substring(7) : ip; } exports.removeIPV6Prefix = removeIPV6Prefix; function isUrlEncoded(req) { - return /^post$/i.test(req.method) && /urlencoded/i.test(req.headers && req.headers['content-type']); + return /^post$/i.test(req.method) && /urlencoded/i.test(req.headers && req.headers['content-type']); } exports.isUrlEncoded = isUrlEncoded; function isMultipart(req) { - return /multipart/i.test(req.headers['content-type']); + return /multipart/i.test(req.headers['content-type']); } exports.isMultipart = isMultipart; function getQueryString(url) { - var index = url.indexOf('?'); - return index == -1 ? '' : url.substring(index + 1); + var index = url.indexOf('?'); + return index == -1 ? '' : url.substring(index + 1); } exports.getQueryString = getQueryString; function replaceQueryString(query, replaceQuery) { - if (replaceQuery && typeof replaceQuery != 'string') { - replaceQuery = qs.stringify(replaceQuery); + if (replaceQuery && typeof replaceQuery != 'string') { + replaceQuery = qs.stringify(replaceQuery); } - if (!query || !replaceQuery) { - return query || replaceQuery; + if (!query || !replaceQuery) { + return query || replaceQuery; } - var queryList = []; - var params = {}; + var queryList = []; + var params = {}; - query = query.split('&').map(filterName); - replaceQuery = replaceQuery.split('&').map(filterName); - query.concat(replaceQuery).forEach(function(name) { - if (name) { - var value = params[name]; - queryList.push(name + (value == null ? '' : '=' + value)); + query = query.split('&').map(filterName); + replaceQuery = replaceQuery.split('&').map(filterName); + query.concat(replaceQuery).forEach(function(name) { + if (name) { + var value = params[name]; + queryList.push(name + (value == null ? '' : '=' + value)); } }); - function filterName(param) { - var index = param.indexOf('='); - var name, value; - if (index == -1) { - name = param; - value = null; + function filterName(param) { + var index = param.indexOf('='); + var name, value; + if (index == -1) { + name = param; + value = null; } else { - name = param.substring(0, index); - value = param.substring(index + 1); + name = param.substring(0, index); + value = param.substring(index + 1); } - var exists = name in params; - params[name] = value; - return exists ? null : name; + var exists = name in params; + params[name] = value; + return exists ? null : name; } - return queryList.join('&'); + return queryList.join('&'); } exports.replaceQueryString = replaceQueryString; function replaceUrlQueryString(url, queryString) { - if (!queryString) { - return url; + if (!queryString) { + return url; } - url = url || ''; - var hashIndex = url.indexOf('#'); - var hashString = ''; - if (hashIndex != -1) { - hashString = url.substring(hashIndex); - url = url.substring(0, hashIndex); + url = url || ''; + var hashIndex = url.indexOf('#'); + var hashString = ''; + if (hashIndex != -1) { + hashString = url.substring(hashIndex); + url = url.substring(0, hashIndex); } - queryString = replaceQueryString(getQueryString(url), queryString); + queryString = replaceQueryString(getQueryString(url), queryString); - return url.replace(/\?.*$/, '') + (queryString ? '?' + queryString : '') + hashString; + return url.replace(/\?.*$/, '') + (queryString ? '?' + queryString : '') + hashString; } exports.replaceUrlQueryString = replaceUrlQueryString; function isEmptyObject(obj) { - for (var i in obj) { - return false; + for (var i in obj) { + return false; } - return true; + return true; } exports.isEmptyObject = isEmptyObject; function decodeBuffer(buffer) { - if (!buffer) { - return ''; + if (!buffer) { + return ''; } - var text = buffer + ''; - return text.indexOf('�') == -1 ? text : iconv.decode(buffer, 'GB18030'); + var text = buffer + ''; + return text.indexOf('�') == -1 ? text : iconv.decode(buffer, 'GB18030'); } exports.decodeBuffer = decodeBuffer; function setHeaders(data, obj) { - data.headers = data.headers || {}; - for (var i in obj) { - data.headers[i] = obj[i]; + data.headers = data.headers || {}; + for (var i in obj) { + data.headers[i] = obj[i]; } - return data; + return data; } exports.setHeaders = setHeaders; function setHeader(data, name, value) { - data.headers = data.headers || {}; - data.headers[name] = value; - return data; + data.headers = data.headers || {}; + data.headers[name] = value; + return data; } exports.setHeader = setHeader; function getResponseBody(options, callback) { - var done; - var body = ''; - var callbackHandler = function(err) { - clearTimeout(timer); - if (!done) { - done = true; - callback(err, body); + var done; + var body = ''; + var callbackHandler = function(err) { + clearTimeout(timer); + if (!done) { + done = true; + callback(err, body); } - err && client.abort(); + err && client.abort(); }; - var timeoutHandler = function() { - callbackHandler(new Error('Timeout')); + var timeoutHandler = function() { + callbackHandler(new Error('Timeout')); }; - var timer = setTimeout(timeoutHandler, REQUEST_TIMEOUT); - var client = http.get(options, function(res) { - res.on('error', callbackHandler); - res.setEncoding('utf8'); - res.on('data', function(data) { - body += data; - if (body.length > MAX_RULES_SIZE) { - client.abort(); - callbackHandler(); + var timer = setTimeout(timeoutHandler, REQUEST_TIMEOUT); + var client = http.get(options, function(res) { + res.on('error', callbackHandler); + res.setEncoding('utf8'); + res.on('data', function(data) { + body += data; + if (body.length > MAX_RULES_SIZE) { + client.abort(); + callbackHandler(); } else { - clearTimeout(timer); - timer = setTimeout(timeoutHandler, REQUEST_TIMEOUT); + clearTimeout(timer); + timer = setTimeout(timeoutHandler, REQUEST_TIMEOUT); } }); - res.on('end', callbackHandler); + res.on('end', callbackHandler); }); - client.on('error', callbackHandler); - client.end(); + client.on('error', callbackHandler); + client.end(); } exports.getResponseBody = getResponseBody; function handlePluginRules(req, rulesMgr, isResRules) { - if (!rulesMgr) { - return; + if (!rulesMgr) { + return; } - var _rules = req.rules; - var filter = req.filter; - var fullUrl = req.fullUrl; + var _rules = req.rules; + var filter = req.filter; + var fullUrl = req.fullUrl; - req.disable && extend(req.disable, rulesMgr.resolveDisable(fullUrl)); - if (filter) { - extend(filter, rulesMgr.resolveFilter(fullUrl)); - Object.keys(filter).forEach(function(name) { - if (!isResRules || protoMgr.resProtocols.indexOf(name) != -1) { - delete _rules[name]; + req.disable && extend(req.disable, rulesMgr.resolveDisable(fullUrl)); + if (filter) { + extend(filter, rulesMgr.resolveFilter(fullUrl)); + Object.keys(filter).forEach(function(name) { + if (!isResRules || protoMgr.resProtocols.indexOf(name) != -1) { + delete _rules[name]; } }); } diff --git a/lib/util/log-server.js b/lib/util/log-server.js index 46197547f..a53a48b6c 100644 --- a/lib/util/log-server.js +++ b/lib/util/log-server.js @@ -6,75 +6,75 @@ var count = 0; var logs = []; function getLogs(startTime, count) { - var len = logs.length; - if (!len || startTime == -1) { - return []; + var len = logs.length; + if (!len || startTime == -1) { + return []; } - count = Math.min(count || COUNT, len); - if (startTime == -2) { - return logs.slice(0, count); + count = Math.min(count || COUNT, len); + if (startTime == -2) { + return logs.slice(0, count); } - startTime = ((startTime || Date.now() - 3000) + '').split('-'); + startTime = ((startTime || Date.now() - 3000) + '').split('-'); - startTime[0] = parseInt(startTime[0], 10) || 0; - startTime[1] = parseInt(startTime[1], 10) || 0; + startTime[0] = parseInt(startTime[0], 10) || 0; + startTime[1] = parseInt(startTime[1], 10) || 0; - if (compareId(logs[0].id, startTime)) { + if (compareId(logs[0].id, startTime)) { - return logs.slice(0, count); + return logs.slice(0, count); } - var end = len - 1; - if (!end || !compareId(logs[end].id, startTime)) { - return []; + var end = len - 1; + if (!end || !compareId(logs[end].id, startTime)) { + return []; } - var index = getIndex(startTime, 0, end); - return logs.slice(index, index + count); + var index = getIndex(startTime, 0, end); + return logs.slice(index, index + count); } function getIndex(startTime, start, end) { - if (end - start <= 1) { - return compareId(logs[start].id, startTime) ? start : end; + if (end - start <= 1) { + return compareId(logs[start].id, startTime) ? start : end; } - var mid = Math.floor((start + end) / 2); - return compareId(logs[mid].id, startTime) ? getIndex(startTime, start, mid) : getIndex(startTime, mid + 1, end); + var mid = Math.floor((start + end) / 2); + return compareId(logs[mid].id, startTime) ? getIndex(startTime, start, mid) : getIndex(startTime, mid + 1, end); } function compareId(curId, refId) { - curId = curId.split('-'); - return curId[0] > refId[0] || (curId[0] == refId[0] && curId[1] > refId[1]); + curId = curId.split('-'); + return curId[0] > refId[0] || (curId[0] == refId[0] && curId[1] > refId[1]); } module.exports = function init(proxy) { - proxy.addLog = function set(log) { - if (!log) { - return; + proxy.addLog = function set(log) { + if (!log) { + return; } - var now = Date.now(); - var text = log.text; - if (text == null) { - text = ''; + var now = Date.now(); + var text = log.text; + if (text == null) { + text = ''; } else if (typeof text != 'string') { - text += ''; + text += ''; } - logs.push({ - id: now + '-' + ++count, - date: now, - level: /^fatal|error|warn|info|debug$/.test(log.level) ? log.level : 'info', - text: text.substring(0, SIZE) + logs.push({ + id: now + '-' + ++count, + date: now, + level: /^fatal|error|warn|info|debug$/.test(log.level) ? log.level : 'info', + text: text.substring(0, SIZE) }); - var len = logs.length; - if (len > MAX_LENGTH) { - logs = logs.slice(len - MIN_LENGTH, len); + var len = logs.length; + if (len > MAX_LENGTH) { + logs = logs.slice(len - MIN_LENGTH, len); } }; - proxy.getLogs = getLogs; + proxy.getLogs = getLogs; }; \ No newline at end of file diff --git a/lib/util/logger.js b/lib/util/logger.js index 319b3357b..37f55250f 100644 --- a/lib/util/logger.js +++ b/lib/util/logger.js @@ -6,75 +6,75 @@ var logs = []; var LEVELS = ['fatal', 'error', 'warn', 'info', 'debug']; function getLogs(startTime, count) { - var len = logs.length; - if (!len || startTime == -1) { - return []; + var len = logs.length; + if (!len || startTime == -1) { + return []; } - count = Math.min(count || COUNT, len); - if (startTime == -2) { - return logs.slice(0, count); + count = Math.min(count || COUNT, len); + if (startTime == -2) { + return logs.slice(0, count); } - startTime = ((startTime || Date.now() - 3000) + '').split('-'); - startTime[0] = parseInt(startTime[0], 10) || 0; - startTime[1] = parseInt(startTime[1], 10) || 0; + startTime = ((startTime || Date.now() - 3000) + '').split('-'); + startTime[0] = parseInt(startTime[0], 10) || 0; + startTime[1] = parseInt(startTime[1], 10) || 0; - if (compareId(logs[0].id, startTime)) { + if (compareId(logs[0].id, startTime)) { - return logs.slice(0, count); + return logs.slice(0, count); } - var end = len - 1; - if (!end || !compareId(logs[end].id, startTime)) { - return []; + var end = len - 1; + if (!end || !compareId(logs[end].id, startTime)) { + return []; } - var index = getIndex(startTime, 0, end); - return logs.slice(index, index + count); + var index = getIndex(startTime, 0, end); + return logs.slice(index, index + count); } function getIndex(startTime, start, end) { - if (end - start <= 1) { - return compareId(logs[start].id, startTime) ? start : end; + if (end - start <= 1) { + return compareId(logs[start].id, startTime) ? start : end; } - var mid = Math.floor((start + end) / 2); - return compareId(logs[mid].id, startTime) ? getIndex(startTime, start, mid) : getIndex(startTime, mid + 1, end); + var mid = Math.floor((start + end) / 2); + return compareId(logs[mid].id, startTime) ? getIndex(startTime, start, mid) : getIndex(startTime, mid + 1, end); } function compareId(curId, refId) { - curId = curId.split('-'); - return curId[0] > refId[0] || (curId[0] == refId[0] && curId[1] > refId[1]); + curId = curId.split('-'); + return curId[0] > refId[0] || (curId[0] == refId[0] && curId[1] > refId[1]); } function getStack(err) { - return err && String(err && err.stack || err); + return err && String(err && err.stack || err); } function log(err, level) { - if (!(err = getStack(err))) { - return; + if (!(err = getStack(err))) { + return; } - var now = Date.now(); - logs.push({ - id: now + '-' + ++count, - date: now, - level: LEVELS.indexOf(level) != -1 ? level : 'info', - text: err + var now = Date.now(); + logs.push({ + id: now + '-' + ++count, + date: now, + level: LEVELS.indexOf(level) != -1 ? level : 'info', + text: err }); - var len = logs.length; - if (len > MAX_LENGTH) { - logs = logs.slice(len - MIN_LENGTH, len); + var len = logs.length; + if (len > MAX_LENGTH) { + logs = logs.slice(len - MIN_LENGTH, len); } } exports.getLogs = getLogs; LEVELS.forEach(function(level) { - exports[level] = function(err) { - log(err, level); + exports[level] = function(err) { + log(err, level); }; }); diff --git a/lib/util/multipart-parser.js b/lib/util/multipart-parser.js index 58733c553..f9894e7d0 100644 --- a/lib/util/multipart-parser.js +++ b/lib/util/multipart-parser.js @@ -4,43 +4,43 @@ var MAX_SIZE = 5120; var NAME_RE = /name=(?:"([^"]+)"|([^;]+))/i; function MultipartParser(params) { - this._params = params; + this._params = params; } function getName(firstLine) { - return NAME_RE.test(firstLine) ? (RegExp.$1 || RegExp.$2 || '') : null; + return NAME_RE.test(firstLine) ? (RegExp.$1 || RegExp.$2 || '') : null; } var proto = MultipartParser.prototype; proto.transform = function(chunk) { - if (this._notMatched) { - return chunk; + if (this._notMatched) { + return chunk; } - if (this._ended) { - return; + if (this._ended) { + return; } - chunk = this._buffer ? Buffer.concat([this._buffer, chunk]) : chunk; - this._buffer = null; - var index = util.indexOfList(chunk, CRLF); - if (index != -1) { - var name = getName(chunk.slice(0, index) + ''); - if (name == null || !(name in this._params)) { - this._notMatched = true; + chunk = this._buffer ? Buffer.concat([this._buffer, chunk]) : chunk; + this._buffer = null; + var index = util.indexOfList(chunk, CRLF); + if (index != -1) { + var name = getName(chunk.slice(0, index) + ''); + if (name == null || !(name in this._params)) { + this._notMatched = true; } else { - this._ended = true; - chunk = util.toMultipart(name, this._params[name]); - delete this._params[name]; + this._ended = true; + chunk = util.toMultipart(name, this._params[name]); + delete this._params[name]; } } else if (chunk.length > MAX_SIZE) { - this._notMatched = true; + this._notMatched = true; } else { - this._buffer = chunk; - chunk = null; + this._buffer = chunk; + chunk = null; } - return chunk; + return chunk; }; module.exports = MultipartParser; diff --git a/lib/util/parse-req.js b/lib/util/parse-req.js index 7517bb97c..2a601b7fc 100644 --- a/lib/util/parse-req.js +++ b/lib/util/parse-req.js @@ -4,118 +4,118 @@ var MAX_BYTES = 1024 * 256; var CRLF_BUF = new Buffer('\r\n'); function parsePairs(pairs, buffer) { - for (var i = 0, len = buffer.length; i < len; i++) { - var pair = getPair(buffer[i]); - if (pair) { - var value = pairs[pair.key]; - if (value) { - if (!Array.isArray(value)) { - value = [value]; + for (var i = 0, len = buffer.length; i < len; i++) { + var pair = getPair(buffer[i]); + if (pair) { + var value = pairs[pair.key]; + if (value) { + if (!Array.isArray(value)) { + value = [value]; } - value.push(pair.value); + value.push(pair.value); } - pairs[pair.key] = value || pair.value; + pairs[pair.key] = value || pair.value; } } - return pairs; + return pairs; } function getPair(line) { - if (!(line = line && line.trim())) { - return; + if (!(line = line && line.trim())) { + return; } - var index = line.indexOf(':'); - return index != -1 ? { - key: line.substring(0, index).trim().toLowerCase(), - value: line.substring(index + 1).trim() + var index = line.indexOf(':'); + return index != -1 ? { + key: line.substring(0, index).trim().toLowerCase(), + value: line.substring(index + 1).trim() } : null; } function endIndexOf(buffer, start, end) { - start = start || 0; - end = end || buffer.length; - for (; start < end; start++) { - if (buffer[start] == CRLF_BUF[0] && buffer[start + 1] == CRLF_BUF[1] + start = start || 0; + end = end || buffer.length; + for (; start < end; start++) { + if (buffer[start] == CRLF_BUF[0] && buffer[start + 1] == CRLF_BUF[1] && buffer[start + 2] == CRLF_BUF[0] && buffer[start + 3] == CRLF_BUF[1]) { - return start; + return start; } } - return -1; + return -1; } module.exports = function parseReq(socket, callback, readBuffer, neadModifyHeaders) { - if (typeof readBuffer == 'boolean') { - var temp = neadModifyHeaders; - neadModifyHeaders = readBuffer; - readBuffer = temp; + if (typeof readBuffer == 'boolean') { + var temp = neadModifyHeaders; + neadModifyHeaders = readBuffer; + readBuffer = temp; } - var timeoutId, buffer; - socket.on('error', callback); - if (socket.readable) { - socket.on('data', parseData); + var timeoutId, buffer; + socket.on('error', callback); + if (socket.readable) { + socket.on('data', parseData); } - readBuffer && parseData(readBuffer); + readBuffer && parseData(readBuffer); - function parseData(data) { - clearTimeout(timeoutId); - buffer = buffer ? Buffer.concat([buffer, data]) : data; - var endIndex = endIndexOf(buffer); - if (endIndex == -1) { - if (buffer.length > MAX_BYTES) { - callback(new Error('Parse error')); + function parseData(data) { + clearTimeout(timeoutId); + buffer = buffer ? Buffer.concat([buffer, data]) : data; + var endIndex = endIndexOf(buffer); + if (endIndex == -1) { + if (buffer.length > MAX_BYTES) { + callback(new Error('Parse error')); } else { - timeoutId = setTimeout(showTimeout, TIMEOUT); + timeoutId = setTimeout(showTimeout, TIMEOUT); } - return; + return; } - socket.removeListener('data', parseData); - var req = neadModifyHeaders ? socket : new PassThrough(); - var headers = {}; - var rawHeaders = buffer.slice(0, endIndex).toString().trim().split(/\r\n/g); - var firstLine = rawHeaders.shift(); - var status = firstLine.split(/\s/g); - parsePairs(headers, rawHeaders, 1); + socket.removeListener('data', parseData); + var req = neadModifyHeaders ? socket : new PassThrough(); + var headers = {}; + var rawHeaders = buffer.slice(0, endIndex).toString().trim().split(/\r\n/g); + var firstLine = rawHeaders.shift(); + var status = firstLine.split(/\s/g); + parsePairs(headers, rawHeaders, 1); - req.method = status[0] || 'GET'; - req.url = status[1] || '/'; - req.statusCode = status[1] || 0; - req.httpVersion = status[2] && status[2].split('/')[1] || '1.1'; - req.headers = headers; + req.method = status[0] || 'GET'; + req.url = status[1] || '/'; + req.statusCode = status[1] || 0; + req.httpVersion = status[2] && status[2].split('/')[1] || '1.1'; + req.headers = headers; - if (neadModifyHeaders) { - req.getBuffer = function(headers) { - if (!headers) { - return buffer; + if (neadModifyHeaders) { + req.getBuffer = function(headers) { + if (!headers) { + return buffer; } - var rawData = [firstLine]; - Object.keys(headers).forEach(function(key) { - var value = headers[key]; - value && rawData.push(key + ':' + value); + var rawData = [firstLine]; + Object.keys(headers).forEach(function(key) { + var value = headers[key]; + value && rawData.push(key + ':' + value); }); - return Buffer.concat([new Buffer(rawData.join('\r\n')), buffer.slice(endIndex)]); + return Buffer.concat([new Buffer(rawData.join('\r\n')), buffer.slice(endIndex)]); }; } else { - req.on('error', function () { - socket.destroy(); + req.on('error', function () { + socket.destroy(); }); - req.destroy = function() { - socket.destroy(); + req.destroy = function() { + socket.destroy(); }; - req.socket = socket; - req.write(buffer); - socket.pipe(req); + req.socket = socket; + req.write(buffer); + socket.pipe(req); } - callback(null, req); + callback(null, req); } - function showTimeout() { - callback(new Error('Timeout')); + function showTimeout() { + callback(new Error('Timeout')); } }; \ No newline at end of file diff --git a/lib/util/replace-pattern-transform.js b/lib/util/replace-pattern-transform.js index 6d8d678e0..afbbf995e 100644 --- a/lib/util/replace-pattern-transform.js +++ b/lib/util/replace-pattern-transform.js @@ -3,42 +3,42 @@ var util = require('util'); var LENGTH = 5120; function ReplacePatternTransform(pattern, value) { - Transform.call(this); - this._pattern = pattern; - this._value = value == null ? '' : value + ''; - this._rest = ''; + Transform.call(this); + this._pattern = pattern; + this._value = value == null ? '' : value + ''; + this._rest = ''; } util.inherits(ReplacePatternTransform, Transform); var proto = ReplacePatternTransform.prototype; proto._transform = function(chunk, encoding, callback) { - if (chunk != null) { - chunk = this._rest + chunk; - var index = 0; - var value = this._value; - var result = chunk.replace(this._pattern, function() { - var matcher = replace(value, arguments); - var lastIndex = arguments.length - 1; - index = arguments[lastIndex - 1] + arguments[lastIndex].length; - return matcher; + if (chunk != null) { + chunk = this._rest + chunk; + var index = 0; + var value = this._value; + var result = chunk.replace(this._pattern, function() { + var matcher = replace(value, arguments); + var lastIndex = arguments.length - 1; + index = arguments[lastIndex - 1] + arguments[lastIndex].length; + return matcher; }); - index = Math.max(index, chunk.length + 1 - LENGTH); - this._rest = chunk.substring(index); - chunk = result.substring(0, result.length - this._rest.length); + index = Math.max(index, chunk.length + 1 - LENGTH); + this._rest = chunk.substring(index); + chunk = result.substring(0, result.length - this._rest.length); } else if (this._rest) { - chunk = this._rest.replace(this._pattern, function() { - return replace(this._value, arguments); + chunk = this._rest.replace(this._pattern, function() { + return replace(this._value, arguments); }); } - callback(null, chunk); + callback(null, chunk); }; function replace(replacement, args) { - return replacement ? replacement.replace(/(^|.)?(\$[1-9])/g, + return replacement ? replacement.replace(/(^|.)?(\$[1-9])/g, function(matched, $1, $2) { - return $1 == '\\' ? $2 : ($1 || '') + (args[$2.substring(1)] || ''); + return $1 == '\\' ? $2 : ($1 || '') + (args[$2.substring(1)] || ''); }) : ''; } diff --git a/lib/util/replace-string-transform.js b/lib/util/replace-string-transform.js index 055e33731..465f64ef7 100644 --- a/lib/util/replace-string-transform.js +++ b/lib/util/replace-string-transform.js @@ -2,38 +2,38 @@ var Transform = require('pipestream').Transform; var util = require('util'); function ReplaceStringTransform(str, value) { - Transform.call(this); - this._str = str; - this._length = this._str.length; - this._value = value == null ? '' : value + ''; - this._rest = ''; + Transform.call(this); + this._str = str; + this._length = this._str.length; + this._value = value == null ? '' : value + ''; + this._rest = ''; } util.inherits(ReplaceStringTransform, Transform); var proto = ReplaceStringTransform.prototype; proto._transform = function(chunk, encoding, callback) { - if (chunk != null) { - chunk = this._rest + chunk; - var minIndex = chunk.length + 1 - this._length; - var index = chunk.lastIndexOf(this._str); + if (chunk != null) { + chunk = this._rest + chunk; + var minIndex = chunk.length + 1 - this._length; + var index = chunk.lastIndexOf(this._str); - if (index != -1) { - index = Math.max(minIndex, index + this._length); + if (index != -1) { + index = Math.max(minIndex, index + this._length); } else { - index = minIndex; + index = minIndex; } - this._rest = chunk.substring(index); - chunk = chunk.substring(0, index); + this._rest = chunk.substring(index); + chunk = chunk.substring(0, index); } else { - chunk = this._rest; + chunk = this._rest; } - callback(null, replace(chunk, this._str, this._value)); + callback(null, replace(chunk, this._str, this._value)); }; function replace(chunk, str, value) { - return chunk ? chunk.split(str).join(value) : null; + return chunk ? chunk.split(str).join(value) : null; } module.exports = ReplaceStringTransform; \ No newline at end of file diff --git a/lib/util/speed-transform.js b/lib/util/speed-transform.js index 5ea90d9e8..bbf3172bb 100644 --- a/lib/util/speed-transform.js +++ b/lib/util/speed-transform.js @@ -2,42 +2,42 @@ var Transform = require('pipestream').Transform; var util = require('util'); function SpeedTransform(options) { - if (!(this instanceof SpeedTransform)) { - return new SpeedTransform(options); + if (!(this instanceof SpeedTransform)) { + return new SpeedTransform(options); } - Transform.call(this); - options = options || {}; - var value = parseInt(options.speed * 1000 / 8); - if (value > 0) { - this._speed = value; + Transform.call(this); + options = options || {}; + var value = parseInt(options.speed * 1000 / 8); + if (value > 0) { + this._speed = value; } - if ((value = parseInt(options.delay)) > 0) { - this._delay = value; + if ((value = parseInt(options.delay)) > 0) { + this._delay = value; } } util.inherits(SpeedTransform, Transform); SpeedTransform.prototype._transform = function(chunk, encoding, callback) { - var self = this; - var cb = function() { - if (chunk && self._speed) { - setTimeout(function() { - callback(null, chunk); + var self = this; + var cb = function() { + if (chunk && self._speed) { + setTimeout(function() { + callback(null, chunk); }, Math.round(chunk.length * 1000 / self._speed)); } else { - callback(null, chunk); + callback(null, chunk); } }; - if (self._delay) { - var delay = self._delay; - self._delay = null; - return setTimeout(cb, delay); + if (self._delay) { + var delay = self._delay; + self._delay = null; + return setTimeout(cb, delay); } - cb(); + cb(); }; module.exports = SpeedTransform; \ No newline at end of file diff --git a/lib/util/whistle-transform.js b/lib/util/whistle-transform.js index 5b8a8f75d..db1af0761 100644 --- a/lib/util/whistle-transform.js +++ b/lib/util/whistle-transform.js @@ -3,75 +3,75 @@ var util = require('util'); var iconv = require('iconv-lite'); function WhistleTransform(options) { - if (!(this instanceof WhistleTransform)) { - return new WhistleTransform(options); + if (!(this instanceof WhistleTransform)) { + return new WhistleTransform(options); } - Transform.call(this); - options = options || {}; - var value = parseInt(options.speed * 1000 / 8); - if (value > 0) { - this._speed = value; + Transform.call(this); + options = options || {}; + var value = parseInt(options.speed * 1000 / 8); + if (value > 0) { + this._speed = value; } - if ((value = parseInt(options.delay)) > 0) { - this._delay = value; + if ((value = parseInt(options.delay)) > 0) { + this._delay = value; } - var charset = options.charset && String(options.charset); - if (!iconv.encodingExists(charset)) { - charset = 'utf8'; + var charset = options.charset && String(options.charset); + if (!iconv.encodingExists(charset)) { + charset = 'utf8'; } - this._body = getBuffer(options, 'body', charset); - this._top = getBuffer(options, 'top', charset); - this._bottom = getBuffer(options, 'bottom', charset); + this._body = getBuffer(options, 'body', charset); + this._top = getBuffer(options, 'top', charset); + this._bottom = getBuffer(options, 'bottom', charset); } function getBuffer(options, name, charset) { - var buf = options[name]; - return (buf == null || buf instanceof Buffer) ? buf : iconv.encode(buf + '', charset); + var buf = options[name]; + return (buf == null || buf instanceof Buffer) ? buf : iconv.encode(buf + '', charset); } util.inherits(WhistleTransform, Transform); WhistleTransform.prototype._transform = function(chunk, encoding, callback) { - var self = this; - var cb = function() { - if (self._ended && self._bottom) { - chunk = chunk ? Buffer.concat([chunk, self._bottom]) : self._bottom; - self._bottom = null; + var self = this; + var cb = function() { + if (self._ended && self._bottom) { + chunk = chunk ? Buffer.concat([chunk, self._bottom]) : self._bottom; + self._bottom = null; } - if (chunk && self._speed) { - setTimeout(function() { - callback(null, chunk); + if (chunk && self._speed) { + setTimeout(function() { + callback(null, chunk); }, Math.round(chunk.length * 1000 / self._speed)); } else { - callback(null, chunk); + callback(null, chunk); } }; - if (!self._ended) { - self._ended = !chunk; + if (!self._ended) { + self._ended = !chunk; } - if (!self._inited) { - self._inited = true; - if (self._body) { - self._ended = true; - chunk = self._body; + if (!self._inited) { + self._inited = true; + if (self._body) { + self._ended = true; + chunk = self._body; } - if (self._top) { - chunk = chunk ? Buffer.concat([self._top, chunk]) : self._top; - self._top = null; + if (self._top) { + chunk = chunk ? Buffer.concat([self._top, chunk]) : self._top; + self._top = null; } - return self._delay ? setTimeout(cb, self._delay) : cb(); + return self._delay ? setTimeout(cb, self._delay) : cb(); } - if (self._ended) { - chunk = null; + if (self._ended) { + chunk = null; } - cb(); + cb(); }; module.exports = WhistleTransform; \ No newline at end of file