catproxy
Version:
a node proxy or host change tools
281 lines (246 loc) • 9.48 kB
JavaScript
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = function (catproxy) {
if (!catproxy || !catproxy.onBeforeReq) {
throw new Error('catproxy是必须得');
}
var monitorBeforeReq, monitorBeforeRes, monitorAfterRes;
// 检测是不是本地的一个服务器
// 只要ip是localhost ui服务器 或者是weinre的请求就忽略
var checkIsInnerServer = function checkIsInnerServer(originalUrl) {
return catproxy.localUiReg.test(originalUrl) || originalUrl.toLowerCase().indexOf(_defCfg.WEINRE_PATH + '/' + _tools.weinreId) >= 0;
};
// 请求发送前
monitorBeforeReq = function monitorBeforeReq(result) {
if (result && result.id && config.get('monitor:monitorStatus') && !checkIsInnerServer(result.originalUrl)) {
/**
*
* 目前没有把请求数据直接保存到文件,后期可以考虑
请求头部数据一共三种,一种是 post提交数据 一种是 get提交数据, 还有一种是表单提交数据,表单提交数据如果带 二进制就存储,否则直接返回
contentType 的三种情况
application/x-www-form-urlencoded 在发送前编码所有字符(默认)// 转换成 form data & 符号链接的数据, <xml 数据 等等, 直接返回json ???
text/plain 空格转换为 "+" 加号,但不对特殊字符编码。 // 转换成form data 任意不是二进制的数据 -- 可以检查 是不是{}或者 []开始判断是不是json
上面2种类似
multipart/form-data 不对字符编码。在使用包含文件上传控件的表单时,必须使用该值。 去掉二进制数据转换 multipart request payload
**/
var contentType = result.headers['content-type'];
var addMontiorData = {
id: result.id,
name: result.originalFullUrl,
protocol: result.protocol,
method: result.method,
reqHeaders: result.headers,
startTime: result.startTime
};
if (result.ruleInfo) {
addMontiorData.reqRuleInfo = result.ruleInfo;
}
var bodyData = result.bodyData;
if (result.bodyData) {
var isb = (0, _dataHelper.isBinary)(result.bodyData);
addMontiorData.isReqBinary = isb;
if (isb) {
if (contentType) {
// 混合流,里面有二进制的文件数据也有 字段数据,需要解析下
if (contentType.indexOf('boundary=') > -1) {
bodyData = detailMultipartData(contentType, bodyData);
} else {
// 不认识的二进制数据忽略
bodyData = '二进制数据!!!';
}
} else {
bodyData = '二进制数据!!!';
}
}
addMontiorData.reqBodyData = (bodyData || '').toString();
// log.debug(contentType, "************\n" ,result.bodyData.length, "**************\n", result.originalFullUrl);
// log.debug("isBinary", isb);
// log.debug('content--', addMontiorData.bodyData);
// 先记录到缓存中
monitorList[result.id] = addMontiorData;
}
}
};
// 准备发送请求
monitorBeforeRes = function monitorBeforeRes(result) {
if (result && result.id && config.get('monitor:monitorStatus') && !checkIsInnerServer(result.originalUrl)) {
var addMontiorData = (0, _merge2.default)(monitorList[result.id], {
ext: result.ext,
resHeaders: result.headers,
serverIp: result.serverIp
});
var type = (0, _dataHelper.getReqType)(addMontiorData, result.ext) || 'other';
addMontiorData.type = type;
// 当所有用户调用结束在看是否是二进制数据
result.isBinary = (0, _dataHelper.isBinary)(result.bodyData);
addMontiorData.isResbinary = result.isBinary;
// 修改缓存数据
monitorList[result.id] = {
startTime: addMontiorData.startTime
};
// startTime不需要传递到前端
delete addMontiorData.startTime;
// 调用数据增加
(0, _sendMsg.addMonitor)(addMontiorData);
}
};
// 请求发送后
monitorAfterRes = function monitorAfterRes(result) {
if (result && +result.id && config.get('monitor:monitorStatus') && !checkIsInnerServer(result.originalUrl)) {
if (monitorList[result.id]) {
var startTime = monitorList[result.id].startTime;
var bodyData = result.bodyData;
var fileName = void 0;
var resBodyData = void 0;
if (bodyData && bodyData.length) {
var contentType = result.headers['content-type'];
// 是二进制数据并且是图片,或者不是二进制数据
if (!result.isBinary || result.isBinary && _dataHelper.isImage.test(contentType)) {
var md5 = _crypto2.default.createHash('md5');
md5.update(bodyData);
fileName = md5.digest('hex');
fileName = resBodyName + fileName;
// 缓存文件
(0, _cacheFile.cacheFile)(fileName, bodyData);
} else {
resBodyData = '二进制数据!!!';
}
} else {
if (result.bodyDataErr) {
resBodyData = result.bodyDataErr;
} else {
// 可能是 302,等请求没有响应内容
resBodyData = '';
}
}
var updateData = {
id: result.id,
time: result.endTime - startTime,
status: result.statusCode,
size: bodyData ? bodyData.length : 0
};
if (result.charset) {
updateData.resCharset = result.charset;
}
if (fileName) {
updateData.resBodyDataId = fileName;
}
if (resBodyData !== undefined) {
updateData.resBodyData = resBodyData;
}
delete monitorList[result.id];
(0, _sendMsg.updateMonitor)(updateData);
}
}
};
// 动态添加到数组中,因为这些方法在用户调用 on事件后才能被调用
catproxy.__monitorBeforeReq = monitorBeforeReq;
catproxy.__monitorBeforeRes = monitorBeforeRes;
catproxy.__monitorAfterRes = monitorAfterRes;
// 管道调用
catproxy.onPipeRequest(function (result) {
// 后面判断带得协议不准确,但是仅仅是为了通过正则,测试,正则中并不关系,请求的类型是ws还是wss
if (result && result.id && config.get('monitor:monitorStatus') && !checkIsInnerServer('ws://' + result.host)) {
var addMontiorData = {
id: result.id,
name: (result.host || '').split(':')[0],
protocol: result.protocol,
method: 'CONNECT',
time: '-',
status: 200,
size: 0,
type: result.protocol === 'ws' || result.protocol === 'wss' ? 'ws' : 'other'
};
// 调用数据增加
(0, _sendMsg.addMonitor)(addMontiorData);
}
});
};
var _log = require('../log');
var _log2 = _interopRequireDefault(_log);
var _fsExtra = require('fs-extra');
var _fsExtra2 = _interopRequireDefault(_fsExtra);
var _fs = require('fs');
var _fs2 = _interopRequireDefault(_fs);
var _promise = require('promise');
var _promise2 = _interopRequireDefault(_promise);
var _merge = require('merge');
var _merge2 = _interopRequireDefault(_merge);
var _isbinaryfile = require('isbinaryfile');
var _isbinaryfile2 = _interopRequireDefault(_isbinaryfile);
var _crypto = require('crypto');
var _crypto2 = _interopRequireDefault(_crypto);
var _cacheFile = require('./cacheFile');
var _dataHelper = require('../dataHelper');
var _sendMsg = require('../ws/sendMsg');
var _tools = require('../tools');
var _config = require('../config/config');
var config = _interopRequireWildcard(_config);
var _defCfg = require('../config/defCfg');
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; } }
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
// 当前监控数据-- 记录文件的url和 resBodyData的文件生成的md5值
var monitorList = {};
var resBodyName = '_res_body_';
// 处理mulitpartData
/** 数据格式
* multipart/form-data; boundary=----WebKitFormBoundaryAxMpx9qwQiovE99R 659
content-- ------WebKitFormBoundaryAxMpx9qwQiovE99R
Content-Disposition: form-data; name="fileName"
说明.txt
------WebKitFormBoundaryAxMpx9qwQiovE99R
Content-Disposition: form-data; name="gameId"
2010110218YX22859517
------WebKitFormBoundaryAxMpx9qwQiovE99R
Content-Disposition: form-data; name="formatType"
1
------WebKitFormBoundaryAxMpx9qwQiovE99R
Content-Disposition: form-data; name="period"
61202
------WebKitFormBoundaryAxMpx9qwQiovE99R
Content-Disposition: form-data; name="uploadFile"; filename="说明.txt"
Content-Type: text/plain
xbmcRemote Զ�̿��� kodi������
homido ����ͷ������
------WebKitFormBoundaryAxMpx9qwQiovE99R--
*/
var detailMultipartData = function detailMultipartData(contentType, bodyData) {
contentType = contentType || '';
var key = contentType.toLowerCase().split('boundary=');
if (key && key.length > 0) {
var reg = /Content-Disposition\s*:\s*form-data;.+;\s*filename=.*/gi;
var isContentType = /^Content-Type.*/i;
key = key[1];
var data = bodyData.toString().split('\n');
var newData = [];
var l = data.length;
var s = null;
var j = null;
if (l) {
for (var i = 0; i < l; i++) {
var current = data[i] || '';
if (reg.test(current)) {
s = true;
}
if (s) {
if (!j) {
newData.push(current);
}
if (isContentType.test(current)) {
j = true;
}
if (current.indexOf(key) > -1) {
j = null;
s = null;
newData.push(current);
}
} else {
newData.push(current);
}
}
}
return newData.join('\n');
}
};