UNPKG

zan-proxy

Version:
273 lines 10.8 kB
"use strict"; var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const es6_promisify_1 = require("es6-promisify"); const events_1 = __importDefault(require("events")); const fs_1 = __importDefault(require("fs")); const jsonfile_1 = __importDefault(require("jsonfile")); const lodash_1 = require("lodash"); const node_fetch_1 = __importDefault(require("node-fetch")); const path_1 = __importDefault(require("path")); const typedi_1 = require("typedi"); const appInfo_1 = require("./appInfo"); const ipReg = /((?:(?:25[0-5]|2[0-4]\d|[01]?\d?\d)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d?\d))/; const jsonWriteFile = es6_promisify_1.promisify(jsonfile_1.default.writeFile); const fsUnlink = es6_promisify_1.promisify(fs_1.default.unlink); const fsExists = (p) => new Promise(resolve => { fs_1.default.exists(p, exists => { resolve(exists); }); }); /** * Created by tsxuehu on 8/3/17. */ let HostService = class HostService extends events_1.default { constructor(appInfoService) { super(); // userId -> { filename -> content} this.userHostFilesMap = {}; // 缓存 // userId, {globHostMap, hostMap} this.inUsingHostsMapCache = {}; const proxyDataDir = appInfoService.getProxyDataDir(); this.hostSaveDir = path_1.default.join(proxyDataDir, 'host'); const contentMap = fs_1.default .readdirSync(this.hostSaveDir) .filter(name => name.endsWith('.json')) .reduce((prev, curr) => { try { prev[curr] = jsonfile_1.default.readFileSync(path_1.default.join(this.hostSaveDir, curr)); } catch (e) { // ignore } return prev; }, {}); lodash_1.forEach(contentMap, (content, fileName) => { const hostName = content.name; const userId = fileName.substr(0, this._getUserIdLength(fileName, hostName)); this.userHostFilesMap[userId] = this.userHostFilesMap[userId] || {}; this.userHostFilesMap[userId][hostName] = content; }); } resolveHost(userId, hostname) { return __awaiter(this, void 0, void 0, function* () { if (!hostname) { return hostname; } if (ipReg.test(hostname)) { return hostname; } let ip; const inUsingHosts = this.getInUsingHosts(userId); ip = inUsingHosts.hostMap[hostname]; if (ip) { return ip; } // 配置 *开头的host 计算属性globHostMap已经将*去除 ip = lodash_1.find(inUsingHosts.globHostMap, (_, host) => { return hostname.endsWith(host); }); if (ip) { return ip; } return hostname; }); } /** * 获取用户的host文件列表 * @param userId * @returns {Array} */ getHostFileList(userId) { const fileList = []; lodash_1.forEach(this.userHostFilesMap[userId], content => { fileList.push({ checked: content.checked, description: content.description, meta: content.meta, name: content.name, }); }); return fileList; } /** * 创建host文件 * @param userId * @param name * @param description * @returns {boolean} */ createHostFile(userId, name, description) { return __awaiter(this, void 0, void 0, function* () { if (this.userHostFilesMap[userId] && this.userHostFilesMap[userId][name]) { // 文件已经存在不让创建 return false; } const content = { checked: false, content: {}, description, meta: { local: true, }, name, }; this.userHostFilesMap[userId] = this.userHostFilesMap[userId] || {}; this.userHostFilesMap[userId][name] = content; const hostfileName = this._getHostFilePath(userId, name); yield jsonWriteFile(hostfileName, content, { encoding: 'utf-8' }); this.emit('data-change', userId, this.getHostFileList(userId)); this.emit('host-saved', userId, name, content); return true; }); } deleteHostFile(userId, name) { return __awaiter(this, void 0, void 0, function* () { delete this.userHostFilesMap[userId][name]; delete this.inUsingHostsMapCache[userId]; /** * 删除文件 */ const filePath = this._getHostFilePath(userId, name); const exists = yield fsExists(filePath); if (exists) { yield fsUnlink(filePath); } this.emit('data-change', userId, this.getHostFileList(userId)); this.emit('host-deleted', userId, name); }); } toggleUseHost(userId, filename) { return __awaiter(this, void 0, void 0, function* () { const toSaveFileName = []; lodash_1.forEach(this.userHostFilesMap[userId], (content, name) => { if (content.name === filename) { content.checked = !content.checked; toSaveFileName.push(name); } }); // 保存文件 for (const name of toSaveFileName) { const hostfileName = this._getHostFilePath(userId, name); const content = this.userHostFilesMap[userId][name]; yield jsonWriteFile(hostfileName, content, { encoding: 'utf-8' }); } delete this.inUsingHostsMapCache[userId]; this.emit('data-change', userId, this.getHostFileList(userId)); }); } getHostFile(userId, name) { if (!this.userHostFilesMap[userId]) { return {}; } return this.userHostFilesMap[userId][name]; } saveHostFile(userId, name, content) { return __awaiter(this, void 0, void 0, function* () { if (!this.userHostFilesMap[userId]) { this.userHostFilesMap[userId] = {}; } this.userHostFilesMap[userId][name] = content; // 如果正在使用,则删除 if (content.checked) { delete this.inUsingHostsMapCache[userId]; } const hostfileName = this._getHostFilePath(userId, name); yield jsonWriteFile(hostfileName, content, { encoding: 'utf-8' }); this.emit('host-saved', userId, name, content); this.emit('data-change', userId, this.getHostFileList(userId)); }); } importRemoteHostFile(userId, url) { return __awaiter(this, void 0, void 0, function* () { const resp = yield node_fetch_1.default(url); const f = yield resp.json(); f.meta = { local: false, url, }; if (!f.content) { f.content = {}; } if (!f.name) { f.name = url.split('/').slice(-1)[0] || url; } if (this.getHostFile(userId, f.name) && this.getHostFile(userId, f.name).checked) { f.checked = true; } else { f.checked = false; } return yield this.saveHostFile(userId, f.name, f); }); } _getHostFilePath(userId, hostName) { const fileName = `${userId}_${hostName}.json`; const filePath = path_1.default.join(this.hostSaveDir, fileName); return filePath; } _getUserIdLength(ruleFileName, hostName) { return ruleFileName.length - hostName.length - 6; } /** * 获取用户生效的host * @param userId * @returns {*} */ getInUsingHosts(userId) { let hosts = this.inUsingHostsMapCache[userId]; if (!hosts) { // 读文件加载host const hostMap = {}; const globHostMap = {}; const userHostFile = this.userHostFilesMap[userId] || {}; Object.keys(userHostFile).forEach(name => { const file = this.userHostFilesMap[userId][name]; if (!file.checked) { return; } lodash_1.forEach(file.content, (ip, host) => { if (host.startsWith('*')) { globHostMap[host.substr(1, host.length)] = ip; } else { hostMap[host] = ip; } }); }); hosts = { globHostMap, hostMap, }; this.inUsingHostsMapCache[userId] = hosts; } return hosts; } }; HostService = __decorate([ typedi_1.Service(), __metadata("design:paramtypes", [appInfo_1.AppInfoService]) ], HostService); exports.HostService = HostService; //# sourceMappingURL=host.js.map