catproxy
Version:
a node proxy or host change tools
333 lines (301 loc) • 10.3 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.parseRule = exports.getRules = exports.saveRules = undefined;
var _config = require('./config');
var config = _interopRequireWildcard(_config);
var _log = require('../log');
var _log2 = _interopRequireDefault(_log);
var _path = require('path');
var _path2 = _interopRequireDefault(_path);
var _promise = require('promise');
var _promise2 = _interopRequireDefault(_promise);
var _url = require('url');
var _url2 = _interopRequireDefault(_url);
var _dns = require('dns');
var _dns2 = _interopRequireDefault(_dns);
var _tools = require('../tools');
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
var parseOneRule = void 0,
parseBranch = void 0,
parseOneBranch = void 0,
_execParse = void 0,
standardUrl = void 0; /**
* 规则管理入口
*/
var isStringReg = /^\/.+\/$/;
var isStartHttp = /^http(s)?:\/\//;
var isStartSlash = /^\//;
var escapeReg = /(\*|\.|\?|\+|\$|\^|\[|\]|\(|\)|\{|\}|\||\\|\/)/g;
/**
* 保存规则
* @param {[type]} rules 规则数据
*/
var saveRules = exports.saveRules = function saveRules(rules) {
// 覆盖旧的rule
config.set('hosts', rules);
// 存入文件中
config.save('hosts');
};
/**
* 获取规则
* @return {[Array]} 获取到得规则对象
*/
var getRules = exports.getRules = function getRules() {
return config.get('hosts') || [];
};
/**
* messageInfo 包含的信息
* {
* headers: "请求头"
* host: "请求地址"
* method: "请求方法"
* protocol: "请求协议"
* originalFullUrl: "原始请求地址,包括参数"
* req: "请求对象,请勿删除"
* port: "请求端口"
* startTime: "请求开始时间"
* path: "请求路径,包括参数"
* originalUrl: "原始的请求地址,不包括参数,请不要修改"
* }
*/
var parseRule = exports.parseRule = function parseRule(messageInfo) {
var rules = getRules();
if (!rules || !rules.length) {
return _promise2.default.resolve(messageInfo);
}
// 多个信息以|| 分割
messageInfo.ruleInfo = [];
return _execParse(rules.map(function (current) {
return {
fun: parseOneRule,
param: [current, messageInfo]
};
})).then(function (result) {
if (result) {
delete result.__match;
messageInfo.ruleInfo = messageInfo.ruleInfo.join('||');
if (!messageInfo.ruleInfo) {
delete messageInfo.ruleInfo;
}
return result;
}
return messageInfo;
});
};
parseOneRule = function parseOneRule(group, messageInfo) {
var branches = void 0;
branches = group.branch;
// 如果禁用这个分组直接跳出,不存在分支
if (group.disable || !branches || !branches.length || messageInfo.__match) {
return;
}
return _execParse(branches.map(function (current) {
return {
fun: parseBranch,
param: [current, messageInfo, group.name]
};
}));
};
parseBranch = function parseBranch(branch, messageInfo, name) {
var rules = branch.rules;
if (branch.disable || !rules || !rules.length || messageInfo.__match) {
return;
}
return _execParse(rules.map(function (current) {
return {
fun: parseOneBranch,
param: [current, messageInfo, name, branch.name]
};
}));
};
parseOneBranch = function parseOneBranch(rule, messageInfo, groupName, branchName) {
var test = rule.test,
exec = rule.exec,
type = rule.type,
_rule$virtualPath = rule.virtualPath,
virtualPath = _rule$virtualPath === undefined ? '' : _rule$virtualPath;
if (isStringReg.test(test)) {
test = test.slice(1, test.length - 1);
} else {
test = isStartHttp.test(test) ? test : messageInfo.protocol === 'https' ? 'https://' + test : 'http://' + test;
test = test.replace(escapeReg, '\\$1');
test = '^' + test;
}
// 将test转换成正则
test = new RegExp(test);
// 如果url被替换过,则使用replaceUrl
var currentUrl = messageInfo.replaceUrl || messageInfo.originalFullUrl;
// 测试没有通过
if (!test.test(currentUrl) || rule.disable) {
return;
}
// 设置了 weinre
if (type === 'weinre') {
messageInfo.weinre = true;
return;
}
// 正则替换,即用正则替换url
// 替换后还可以执行下一个规则
// 使用exec替换test
if (type === 'regReplace') {
var newUrl = currentUrl.replace(test, exec);
_log2.default.debug('replace url:' + newUrl);
var execObj = standardUrl(newUrl, messageInfo.protocol);
messageInfo.host = execObj.host;
messageInfo.protocol = execObj.protocol.split(':')[0];
messageInfo.port = execObj.port ? execObj.port : messageInfo.protocol === 'https' ? 443 : 80;
messageInfo.path = type === 'host' ? messageInfo.path : execObj.path;
messageInfo.replaceUrl = execObj.href;
messageInfo.ruleInfo.push('\u6B63\u5219\u66FF\u6362url\uFF1A' + newUrl);
return;
}
// 已经匹配了
if (messageInfo.__match) {
return;
}
messageInfo.__match = true;
_log2.default.debug('\u89E3\u6790\u89C4\u5219,\u5F53\u524Durl:' + currentUrl + ', \u89C4\u5219\u7C7B\u578B:' + type + ',\u89C4\u5219\u6B63\u5219' + test + ',\u89C4\u5219\u6267\u884C' + exec);
switch (type) {
// host模式下只能修改 host protocol port
case 'host':
// 远程文件替换整个url路径包括参数
case 'remoteFile':
if (exec) {
// 转换成一个url的对象
var _execObj = standardUrl(exec, messageInfo.protocol);
messageInfo.host = _execObj.host;
messageInfo.protocol = _execObj.protocol.split(':')[0];
messageInfo.port = _execObj.port ? _execObj.port : messageInfo.protocol === 'https' ? 443 : 80;
messageInfo.path = type === 'host' ? messageInfo.path : _execObj.path;
// log.debug('', messageInfo.protocol, messageInfo.port, exec);
messageInfo.ruleInfo.push('\u5206\u7EC4:' + groupName + '-\u5206\u652F:' + branchName + '-\u89C4\u5219\u7C7B\u578B:' + type + '-\u89C4\u5219\u6B63\u5219:' + test + '-\u89C4\u5219\u6267\u884C:' + exec);
} else {
// 没有配置exec如果是 host就访问线上,如果是 remoteFile就跳过
if (type === 'host') {
return new _promise2.default(function (resolve, reject) {
_dns2.default.resolve(messageInfo.host.split(':')[0], function (err, addresses) {
if (err || !addresses || !addresses.length) {
_log2.default.error('\u89C4\u5219\u89E3\u6790\u4E2D, dns\u89E3\u6790\u51FA\u73B0\u9519\u8BEF\uFF0C\u89C4\u5219\u7C7B\u578B:' + type + ',\u89C4\u5219\u6B63\u5219' + test);
reject(messageInfo);
} else {
messageInfo.host = addresses[0];
resolve(messageInfo);
}
});
});
}
}
break;
case 'redirect':
if (exec) {
messageInfo.redirect = isStartHttp.test(exec) ? exec : messageInfo.protocol + '://' + exec;
messageInfo.ruleInfo.push('\u5206\u7EC4:' + groupName + '-\u5206\u652F:' + branchName + '-\u89C4\u5219\u7C7B\u578B:' + type + '-\u89C4\u5219\u6B63\u5219:' + test + '-\u89C4\u5219\u6267\u884C:' + exec);
}
break;
case 'localFile':
if (exec) {
messageInfo.sendToFile = exec;
messageInfo.ruleInfo.push('\u5206\u7EC4:' + groupName + '-\u5206\u652F:' + branchName + '-\u89C4\u5219\u7C7B\u578B:' + type + '-\u89C4\u5219\u6B63\u5219:' + test + '-\u89C4\u5219\u6267\u884C:' + exec);
}
break;
case 'localDir':
if (exec) {
// 去掉hash和param
var p = messageInfo.path.split('?')[0];
p = messageInfo.path.split('#')[0];
if (!isStartSlash.test(virtualPath)) {
virtualPath = '/' + virtualPath;
}
p = p.replace(new RegExp('^' + virtualPath), '');
messageInfo.sendToFile = _path2.default.join(exec, p);
messageInfo.ruleInfo.push('\u5206\u7EC4:' + groupName + '-\u5206\u652F:' + branchName + '-\u89C4\u5219\u7C7B\u578B:' + type + '-\u89C4\u5219\u6B63\u5219:' + test + '-\u89C4\u5219\u6267\u884C:' + exec);
}
break;
default:
}
return messageInfo;
};
// 转换url为一个标准对象
standardUrl = function standardUrl(originalUrl, protocol) {
originalUrl = isStartHttp.test(originalUrl) ? originalUrl : protocol + '://' + originalUrl;
return _url2.default.parse(originalUrl);
};
/**
* 按tasks的顺序执行promise
*
* @param {[array]} tasks [任务列表]
* [{
* fun: fun,
* param: [param]
* }]
* index 从第几个开始执行
* 每个函数会得到多个参数,参数的最后一个是 前一个 任务得执行结果
* @return {[promise]} [promise]
*/
_execParse = function execParse(tasks, index, preResult) {
if (!tasks || !tasks.length) {
return _promise2.default.resolve();
}
if (!index) {
index = 0;
}
var current = tasks[index];
var next = tasks[index + 1];
var result = null;
if (typeof current === 'function') {
if (preResult) {
result = current.apply(null, [preResult]);
} else {
result = current.apply(null, []);
}
} else {
var param = current.param || [];
if (preResult) {
param.push(preResult);
}
result = current.fun.apply(null, param);
}
result = _promise2.default.resolve(result);
return result.then(function (res) {
return next ? _execParse(tasks, index + 1, res) : res;
});
};
// test===========
// let messageInfo = {
// headers: {},
// host: "g.caipiao.163.com",
// protocol: "http",
// port: 80,
// path: "/caipiao/test/mm/bb.html",
// originalFullUrl: "http://g.caipiao.163.com/caipiao/test/mm/bb.html"
// };
// parseRule(messageInfo)
// .then((result) => {
// log.debug(result);
// });
// parseOneBranch({
// type: "host",
// test: '/zhuhu.com/test/',
// exec: "http://192.168.199.100/test?aaa"
// }, messageInfo);
// parseOneBranch({
// type: "remoteFile",
// test: '/zhuhu.com/test/',
// exec: "http://192.168.199.100/test?aaa"
// }, messageInfo);
//
// parseOneBranch({
// type: "localFile",
// test: '/zhuhu.com/test/',
// exec: "D:/test/1111/1222"
// }, messageInfo);
// parseOneBranch({
// type: "localDir",
// test: '/zhuhu.com/test/',
// exec: "D:/test/1111/cjx",
// virtualPath: "/test/"
// }, messageInfo);
// console.log(standardUrl("test:8080?a=1"));