UNPKG

whistle

Version:

HTTP, HTTPS, Websocket debugging proxy

184 lines (160 loc) 4.29 kB
var util = require('../rules/util'); var TIMEOUT = 36000; var CLEAR_INTERVAL = 5000; var CACHE_TIME = CLEAR_INTERVAL * 2; var MAX_LENGTH = 512; var MIN_LENGTH = 412; var COUNT = 100; var count = 0; var ids = []; var data = {}; var proxy, binded, timeout, interval; function disable() { proxy.removeListener('request', handleRequest); ids = []; data = {}; interval && clearInterval(interval); interval = null; binded = false; } function enable() { !binded && proxy.on('request', handleRequest); binded = true; clearTimeout(timeout); timeout = setTimeout(disable, TIMEOUT); if (!interval) { interval = setInterval(clearCache, CLEAR_INTERVAL); } } /** * 如果超过最大缓存数,清理如下请求数据: * 1. 已经请求结束且结束时间超过10秒 * 2. 请求#1前面的未结束且未被ui读取过的请求 */ function clearCache() { var len = ids.length; if (len <= MAX_LENGTH) { return; } var index = -1; //已经完成,且缓存超过10s的最后一个请求 var now = Date.now(); var i, curData; for (i = len - 1; i >= 0; i--) { curData = data[ids[i]]; if (curData.endTime && now - curData.endTime > TIMEOUT) { index = i; break; } } if (index < 0) { return; } var _ids = []; ++index; for (i = 0; i < index; i++) { var id = ids[i]; curData = data[id]; if (curData.read && (!curData.endTime || now - curData.endTime < CACHE_TIME || now - curData.startTime < TIMEOUT)) { _ids.push(id); } else { delete data[id]; if (--len <= MIN_LENGTH) { _ids.push.apply(_ids, ids.slice(i + 1, index)); break; } } } ids = _ids.concat(ids.slice(index)); } function getIds(startTime, count, lastRowId) { var len = ids.length; if (!len) { return []; } var notStartTime = !startTime; 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; if (notStartTime && lastRowId) { lastRowId = (lastRowId + '').split('-'); lastRowId[0] = parseInt(lastRowId[0], 10) || 0; if (lastRowId[0] >= startTime[0]) { startTime[0] = lastRowId[0]; startTime[1] = parseInt(lastRowId[1], 10) || 0; } } if (compareId(ids[0], startTime)) { return ids.slice(0, count); } var end = len - 1; if (!end || !compareId(ids[end], startTime)) { return []; } 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]); } function getIndex(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); } 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; } } return result; } function handleRequest(req) { var curData = req.data; if (!util.filterUrl(curData.url)) { return; } var id = curData.id = curData.id || (curData.startTime + '-' + ++count); data[id] = curData; ids.indexOf(id) === -1 && ids.push(id); } module.exports = function init(_proxy) { proxy = _proxy; /** * options: { * startTime: timestamp || timestamp + '-' + count * count: 获取新数据的数量 * ids: 请未结束的id列表 * } * * @param options */ proxy.getData = function get(options) { enable(); options = options || {}; var data = {}; var newIds = options.startTime == -1 ? [] : getIds(options.startTime, options.count, options.lastRowId); 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 }; }; };