@jachy/multiport-proxy 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,148 @@
1
+ # Multiport Proxy
2
+
3
+ 一个功能强大的多端口代理服务,支持动态配置和实时日志查看。
4
+
5
+ ## Features
6
+
7
+ - 🚀 **Web 配置界面** - 启动时自动打开 Web UI,轻松配置代理规则
8
+ - 🔀 **多端口代理** - 支持配置多个本地端口到目标服务的映射
9
+ - ⚙️ **灵活配置** - 支持 CORS、超时、重试等可选配置
10
+ - 📊 **实时日志** - 在 Web 界面查看实时请求/响应日志,无需本地持久化
11
+ - 💾 **配置保存** - 配置自动保存,重启后自动加载
12
+ - 🎯 **零配置启动** - 开箱即用,无需复杂配置
13
+
14
+ ## 快速开始
15
+
16
+ ### 使用 npx(推荐)
17
+
18
+ 无需安装,直接运行:
19
+
20
+ ```bash
21
+ npx @jachy/multiport-proxy
22
+ ```
23
+
24
+ ### 全局安装
25
+
26
+ ```bash
27
+ npm install -g @jachy/multiport-proxy
28
+ multiport-proxy
29
+ ```
30
+
31
+ ### 本地开发
32
+
33
+ ```bash
34
+ # 克隆项目
35
+ git clone <your-repo-url>
36
+ cd multiport-proxy
37
+
38
+ # 安装依赖
39
+ pnpm install
40
+
41
+ # 开发模式
42
+ pnpm run dev
43
+
44
+ # 构建
45
+ pnpm run build
46
+
47
+ # 运行构建后的版本
48
+ pnpm start
49
+ ```
50
+
51
+ ## 项目架构
52
+
53
+ ```
54
+ multiport-proxy/
55
+ ├── src/
56
+ │ ├── server/
57
+ │ │ ├── proxy-server.ts # 代理服务核心逻辑
58
+ │ │ ├── config-manager.ts # 配置管理模块
59
+ │ │ └── logger.ts # 日志管理模块
60
+ │ ├── web/
61
+ │ │ ├── api-routes.ts # Web API 路由(配置/日志)
62
+ │ │ ├── ui/
63
+ │ │ │ ├── index.html # Web 配置界面
64
+ │ │ │ ├── style.css # 样式表
65
+ │ │ │ └── app.js # 前端逻辑
66
+ │ │ └── middleware.ts # Web 中间件
67
+ │ └── index.ts # 应用入口
68
+ ├── data/
69
+ │ └── config.json # 配置持久化文件
70
+ ├── package.json
71
+ └── tsconfig.json
72
+ ```
73
+
74
+ ## 核心流程
75
+
76
+ 1. **启动**:应用启动时加载配置,初始化代理服务器和 Web 服务器
77
+ 2. **Web UI**:自动打开浏览器访问配置页面 (localhost:8888)
78
+ 3. **配置**:用户通过 Web UI 添加/编辑/删除代理规则
79
+ 4. **代理**:根据配置将请求转发到目标服务
80
+ 5. **日志**:实时在 Web UI 显示请求日志,支持滚动查看
81
+
82
+ ## 使用流程
83
+
84
+ ### 启动项目
85
+ ```bash
86
+ pnpm run dev
87
+ ```
88
+
89
+ ### 打开配置页面
90
+ 自动打开 http://localhost:8888
91
+
92
+ ### 配置代理规则
93
+ 1. 输入本地监听端口
94
+ 2. 输入目标服务地址(如 http://localhost:3000)
95
+ 3. 可选配置 CORS、超时等
96
+ 4. 点击"保存"
97
+
98
+ ### 查看日志
99
+ - 实时显示所有代理请求
100
+ - 支持滚动查看历史日志
101
+ - 按端口/状态码筛选
102
+
103
+ ## API 接口
104
+
105
+ ### 获取配置
106
+ - `GET /api/config` - 获取所有代理规则
107
+
108
+ ### 保存配置
109
+ - `POST /api/config` - 保存代理规则
110
+
111
+ ### 获取日志
112
+ - `GET /api/logs` - 获取实时日志(支持分页/筛选)
113
+
114
+ ### 清空日志
115
+ - `DELETE /api/logs` - 清空所有日志
116
+
117
+ ## 配置文件格式
118
+
119
+ ```json
120
+ {
121
+ "rules": [
122
+ {
123
+ "id": "rule-1",
124
+ "localPort": 3000,
125
+ "targetUrl": "http://api.example.com",
126
+ "cors": {
127
+ "enabled": true,
128
+ "origins": ["*"]
129
+ },
130
+ "timeout": 30000,
131
+ "retries": 0,
132
+ "enabled": true
133
+ }
134
+ ]
135
+ }
136
+ ```
137
+
138
+ ## 开发要求
139
+
140
+ - Node.js >= 16
141
+ - TypeScript
142
+ - Express.js (Web 服务器)
143
+ - http-proxy (代理库)
144
+ - React/Vue/Vanilla JS (前端)
145
+
146
+ ## 许可证
147
+
148
+ ISC
package/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
package/dist/cli.js ADDED
@@ -0,0 +1,89 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
4
+ if (k2 === undefined) k2 = k;
5
+ var desc = Object.getOwnPropertyDescriptor(m, k);
6
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
7
+ desc = { enumerable: true, get: function() { return m[k]; } };
8
+ }
9
+ Object.defineProperty(o, k2, desc);
10
+ }) : (function(o, m, k, k2) {
11
+ if (k2 === undefined) k2 = k;
12
+ o[k2] = m[k];
13
+ }));
14
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
15
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
16
+ }) : function(o, v) {
17
+ o["default"] = v;
18
+ });
19
+ var __importStar = (this && this.__importStar) || (function () {
20
+ var ownKeys = function(o) {
21
+ ownKeys = Object.getOwnPropertyNames || function (o) {
22
+ var ar = [];
23
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
24
+ return ar;
25
+ };
26
+ return ownKeys(o);
27
+ };
28
+ return function (mod) {
29
+ if (mod && mod.__esModule) return mod;
30
+ var result = {};
31
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
32
+ __setModuleDefault(result, mod);
33
+ return result;
34
+ };
35
+ })();
36
+ var __importDefault = (this && this.__importDefault) || function (mod) {
37
+ return (mod && mod.__esModule) ? mod : { "default": mod };
38
+ };
39
+ Object.defineProperty(exports, "__esModule", { value: true });
40
+ const express_1 = __importDefault(require("express"));
41
+ const path_1 = __importDefault(require("path"));
42
+ const config_manager_1 = require("./server/config-manager");
43
+ const logger_1 = require("./server/logger");
44
+ const proxy_server_1 = require("./server/proxy-server");
45
+ const api_routes_1 = require("./web/api-routes");
46
+ const WEB_PORT = 8888;
47
+ async function main() {
48
+ console.log('🚀 Multiport Proxy Starting...\n');
49
+ // 初始化管理模块
50
+ const configManager = new config_manager_1.ConfigManager();
51
+ const logger = new logger_1.Logger();
52
+ const proxyServer = new proxy_server_1.ProxyServer(configManager, logger);
53
+ // 启动代理服务
54
+ proxyServer.startProxies();
55
+ // 创建 Web 服务器
56
+ const app = (0, express_1.default)();
57
+ app.use(express_1.default.json());
58
+ // 静态文件服务
59
+ const uiDir = path_1.default.join(__dirname, 'web', 'ui');
60
+ app.use(express_1.default.static(uiDir));
61
+ // API 路由
62
+ app.use('/api', (0, api_routes_1.createApiRouter)(configManager, logger, proxyServer));
63
+ // 根路径返回 HTML
64
+ app.get('/', (req, res) => {
65
+ res.sendFile(path_1.default.join(uiDir, 'index.html'));
66
+ });
67
+ // 启动 Web 服务器
68
+ app.listen(WEB_PORT, async () => {
69
+ console.log(`✓ Web UI running on http://localhost:${WEB_PORT}`);
70
+ console.log(`✓ Running ports: ${proxyServer.getRunningPorts().join(', ') || 'none'}\n`);
71
+ // 自动打开浏览器
72
+ try {
73
+ const open = (await Promise.resolve().then(() => __importStar(require('open')))).default;
74
+ await open(`http://localhost:${WEB_PORT}`);
75
+ console.log('✓ Browser opened automatically\n');
76
+ }
77
+ catch (error) {
78
+ console.log(`Please open http://localhost:${WEB_PORT} in your browser\n`);
79
+ }
80
+ });
81
+ // 优雅关闭
82
+ process.on('SIGINT', () => {
83
+ console.log('\n\n🛑 Shutting down...');
84
+ proxyServer.stopAllProxies();
85
+ process.exit(0);
86
+ });
87
+ }
88
+ main().catch(console.error);
89
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEA,sDAA8B;AAC9B,gDAAwB;AACxB,4DAAwD;AACxD,4CAAyC;AACzC,wDAAoD;AACpD,iDAAmD;AAEnD,MAAM,QAAQ,GAAG,IAAI,CAAC;AAEtB,KAAK,UAAU,IAAI;IACjB,OAAO,CAAC,GAAG,CAAC,kCAAkC,CAAC,CAAC;IAEhD,UAAU;IACV,MAAM,aAAa,GAAG,IAAI,8BAAa,EAAE,CAAC;IAC1C,MAAM,MAAM,GAAG,IAAI,eAAM,EAAE,CAAC;IAC5B,MAAM,WAAW,GAAG,IAAI,0BAAW,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;IAE3D,SAAS;IACT,WAAW,CAAC,YAAY,EAAE,CAAC;IAE3B,aAAa;IACb,MAAM,GAAG,GAAG,IAAA,iBAAO,GAAE,CAAC;IAEtB,GAAG,CAAC,GAAG,CAAC,iBAAO,CAAC,IAAI,EAAE,CAAC,CAAC;IAExB,SAAS;IACT,MAAM,KAAK,GAAG,cAAI,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;IAChD,GAAG,CAAC,GAAG,CAAC,iBAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IAE/B,SAAS;IACT,GAAG,CAAC,GAAG,CAAC,MAAM,EAAE,IAAA,4BAAe,EAAC,aAAa,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC;IAErE,aAAa;IACb,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;QACxB,GAAG,CAAC,QAAQ,CAAC,cAAI,CAAC,IAAI,CAAC,KAAK,EAAE,YAAY,CAAC,CAAC,CAAC;IAC/C,CAAC,CAAC,CAAC;IAEH,aAAa;IACb,GAAG,CAAC,MAAM,CAAC,QAAQ,EAAE,KAAK,IAAI,EAAE;QAC9B,OAAO,CAAC,GAAG,CAAC,wCAAwC,QAAQ,EAAE,CAAC,CAAC;QAChE,OAAO,CAAC,GAAG,CAAC,oBAAoB,WAAW,CAAC,eAAe,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,MAAM,IAAI,CAAC,CAAC;QAExF,UAAU;QACV,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,CAAC,wDAAa,MAAM,GAAC,CAAC,CAAC,OAAO,CAAC;YAC5C,MAAM,IAAI,CAAC,oBAAoB,QAAQ,EAAE,CAAC,CAAC;YAC3C,OAAO,CAAC,GAAG,CAAC,kCAAkC,CAAC,CAAC;QAClD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,GAAG,CAAC,gCAAgC,QAAQ,oBAAoB,CAAC,CAAC;QAC5E,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,OAAO;IACP,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE;QACxB,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;QACvC,WAAW,CAAC,cAAc,EAAE,CAAC;QAC7B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;AACL,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,88 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ const express_1 = __importDefault(require("express"));
40
+ const path_1 = __importDefault(require("path"));
41
+ const config_manager_1 = require("./server/config-manager");
42
+ const logger_1 = require("./server/logger");
43
+ const proxy_server_1 = require("./server/proxy-server");
44
+ const api_routes_1 = require("./web/api-routes");
45
+ const WEB_PORT = 8888;
46
+ async function main() {
47
+ console.log('🚀 Multiport Proxy Starting...\n');
48
+ // 初始化管理模块
49
+ const configManager = new config_manager_1.ConfigManager();
50
+ const logger = new logger_1.Logger();
51
+ const proxyServer = new proxy_server_1.ProxyServer(configManager, logger);
52
+ // 启动代理服务
53
+ proxyServer.startProxies();
54
+ // 创建 Web 服务器
55
+ const app = (0, express_1.default)();
56
+ app.use(express_1.default.json());
57
+ // 静态文件服务
58
+ const uiDir = path_1.default.join(__dirname, 'web', 'ui');
59
+ app.use(express_1.default.static(uiDir));
60
+ // API 路由
61
+ app.use('/api', (0, api_routes_1.createApiRouter)(configManager, logger, proxyServer));
62
+ // 根路径返回 HTML
63
+ app.get('/', (req, res) => {
64
+ res.sendFile(path_1.default.join(uiDir, 'index.html'));
65
+ });
66
+ // 启动 Web 服务器
67
+ app.listen(WEB_PORT, async () => {
68
+ console.log(`✓ Web UI running on http://localhost:${WEB_PORT}`);
69
+ console.log(`✓ Running ports: ${proxyServer.getRunningPorts().join(', ') || 'none'}\n`);
70
+ // 自动打开浏览器
71
+ try {
72
+ const open = (await Promise.resolve().then(() => __importStar(require('open')))).default;
73
+ await open(`http://localhost:${WEB_PORT}`);
74
+ console.log('✓ Browser opened automatically\n');
75
+ }
76
+ catch (error) {
77
+ console.log(`Please open http://localhost:${WEB_PORT} in your browser\n`);
78
+ }
79
+ });
80
+ // 优雅关闭
81
+ process.on('SIGINT', () => {
82
+ console.log('\n\n🛑 Shutting down...');
83
+ proxyServer.stopAllProxies();
84
+ process.exit(0);
85
+ });
86
+ }
87
+ main().catch(console.error);
88
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,sDAA8B;AAC9B,gDAAwB;AACxB,4DAAwD;AACxD,4CAAyC;AACzC,wDAAoD;AACpD,iDAAmD;AAEnD,MAAM,QAAQ,GAAG,IAAI,CAAC;AAEtB,KAAK,UAAU,IAAI;IACjB,OAAO,CAAC,GAAG,CAAC,kCAAkC,CAAC,CAAC;IAEhD,UAAU;IACV,MAAM,aAAa,GAAG,IAAI,8BAAa,EAAE,CAAC;IAC1C,MAAM,MAAM,GAAG,IAAI,eAAM,EAAE,CAAC;IAC5B,MAAM,WAAW,GAAG,IAAI,0BAAW,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;IAE3D,SAAS;IACT,WAAW,CAAC,YAAY,EAAE,CAAC;IAE3B,aAAa;IACb,MAAM,GAAG,GAAG,IAAA,iBAAO,GAAE,CAAC;IAEtB,GAAG,CAAC,GAAG,CAAC,iBAAO,CAAC,IAAI,EAAE,CAAC,CAAC;IAExB,SAAS;IACT,MAAM,KAAK,GAAG,cAAI,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;IAChD,GAAG,CAAC,GAAG,CAAC,iBAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IAE/B,SAAS;IACT,GAAG,CAAC,GAAG,CAAC,MAAM,EAAE,IAAA,4BAAe,EAAC,aAAa,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC;IAErE,aAAa;IACb,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;QACxB,GAAG,CAAC,QAAQ,CAAC,cAAI,CAAC,IAAI,CAAC,KAAK,EAAE,YAAY,CAAC,CAAC,CAAC;IAC/C,CAAC,CAAC,CAAC;IAEH,aAAa;IACb,GAAG,CAAC,MAAM,CAAC,QAAQ,EAAE,KAAK,IAAI,EAAE;QAC9B,OAAO,CAAC,GAAG,CAAC,wCAAwC,QAAQ,EAAE,CAAC,CAAC;QAChE,OAAO,CAAC,GAAG,CAAC,oBAAoB,WAAW,CAAC,eAAe,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,MAAM,IAAI,CAAC,CAAC;QAExF,UAAU;QACV,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,CAAC,wDAAa,MAAM,GAAC,CAAC,CAAC,OAAO,CAAC;YAC5C,MAAM,IAAI,CAAC,oBAAoB,QAAQ,EAAE,CAAC,CAAC;YAC3C,OAAO,CAAC,GAAG,CAAC,kCAAkC,CAAC,CAAC;QAClD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,GAAG,CAAC,gCAAgC,QAAQ,oBAAoB,CAAC,CAAC;QAC5E,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,OAAO;IACP,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE;QACxB,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;QACvC,WAAW,CAAC,cAAc,EAAE,CAAC;QAC7B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;AACL,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC"}
@@ -0,0 +1,28 @@
1
+ export interface ProxyRule {
2
+ id: string;
3
+ localPort: number;
4
+ targetUrl: string;
5
+ cors?: {
6
+ enabled: boolean;
7
+ origins?: string[];
8
+ };
9
+ timeout?: number;
10
+ retries?: number;
11
+ enabled: boolean;
12
+ }
13
+ export interface Config {
14
+ rules: ProxyRule[];
15
+ }
16
+ export declare class ConfigManager {
17
+ private config;
18
+ constructor();
19
+ private loadConfig;
20
+ saveConfig(): void;
21
+ getConfig(): Config;
22
+ getRules(): ProxyRule[];
23
+ addRule(rule: ProxyRule): void;
24
+ updateRule(id: string, updates: Partial<ProxyRule>): void;
25
+ deleteRule(id: string): void;
26
+ setRules(rules: ProxyRule[]): void;
27
+ }
28
+ //# sourceMappingURL=config-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-manager.d.ts","sourceRoot":"","sources":["../../src/server/config-manager.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE;QACL,OAAO,EAAE,OAAO,CAAC;QACjB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;KACpB,CAAC;IACF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,MAAM;IACrB,KAAK,EAAE,SAAS,EAAE,CAAC;CACpB;AAID,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAS;;IAMvB,OAAO,CAAC,UAAU;IAalB,UAAU,IAAI,IAAI;IAQlB,SAAS,IAAI,MAAM;IAInB,QAAQ,IAAI,SAAS,EAAE;IAIvB,OAAO,CAAC,IAAI,EAAE,SAAS,GAAG,IAAI;IAK9B,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,SAAS,CAAC,GAAG,IAAI;IAQzD,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAK5B,QAAQ,CAAC,KAAK,EAAE,SAAS,EAAE,GAAG,IAAI;CAInC"}
@@ -0,0 +1,90 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.ConfigManager = void 0;
37
+ const fs = __importStar(require("fs"));
38
+ const path = __importStar(require("path"));
39
+ const CONFIG_PATH = path.join(process.cwd(), 'data', 'config.json');
40
+ class ConfigManager {
41
+ constructor() {
42
+ this.config = this.loadConfig();
43
+ }
44
+ loadConfig() {
45
+ try {
46
+ if (fs.existsSync(CONFIG_PATH)) {
47
+ const data = fs.readFileSync(CONFIG_PATH, 'utf-8');
48
+ return JSON.parse(data);
49
+ }
50
+ }
51
+ catch (error) {
52
+ console.warn('Failed to load config, using defaults:', error);
53
+ }
54
+ return { rules: [] };
55
+ }
56
+ saveConfig() {
57
+ const dataDir = path.dirname(CONFIG_PATH);
58
+ if (!fs.existsSync(dataDir)) {
59
+ fs.mkdirSync(dataDir, { recursive: true });
60
+ }
61
+ fs.writeFileSync(CONFIG_PATH, JSON.stringify(this.config, null, 2), 'utf-8');
62
+ }
63
+ getConfig() {
64
+ return this.config;
65
+ }
66
+ getRules() {
67
+ return this.config.rules;
68
+ }
69
+ addRule(rule) {
70
+ this.config.rules.push(rule);
71
+ this.saveConfig();
72
+ }
73
+ updateRule(id, updates) {
74
+ const index = this.config.rules.findIndex(r => r.id === id);
75
+ if (index !== -1) {
76
+ this.config.rules[index] = { ...this.config.rules[index], ...updates };
77
+ this.saveConfig();
78
+ }
79
+ }
80
+ deleteRule(id) {
81
+ this.config.rules = this.config.rules.filter(r => r.id !== id);
82
+ this.saveConfig();
83
+ }
84
+ setRules(rules) {
85
+ this.config.rules = rules;
86
+ this.saveConfig();
87
+ }
88
+ }
89
+ exports.ConfigManager = ConfigManager;
90
+ //# sourceMappingURL=config-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-manager.js","sourceRoot":"","sources":["../../src/server/config-manager.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,uCAAyB;AACzB,2CAA6B;AAmB7B,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,aAAa,CAAC,CAAC;AAEpE,MAAa,aAAa;IAGxB;QACE,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC;IAClC,CAAC;IAEO,UAAU;QAChB,IAAI,CAAC;YACH,IAAI,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;gBAC/B,MAAM,IAAI,GAAG,EAAE,CAAC,YAAY,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;gBACnD,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAC1B,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,IAAI,CAAC,wCAAwC,EAAE,KAAK,CAAC,CAAC;QAChE,CAAC;QAED,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;IACvB,CAAC;IAED,UAAU;QACR,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;QAC1C,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;YAC5B,EAAE,CAAC,SAAS,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC7C,CAAC;QACD,EAAE,CAAC,aAAa,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;IAC/E,CAAC;IAED,SAAS;QACP,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;IAED,QAAQ;QACN,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC;IAC3B,CAAC;IAED,OAAO,CAAC,IAAe;QACrB,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC7B,IAAI,CAAC,UAAU,EAAE,CAAC;IACpB,CAAC;IAED,UAAU,CAAC,EAAU,EAAE,OAA2B;QAChD,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;QAC5D,IAAI,KAAK,KAAK,CAAC,CAAC,EAAE,CAAC;YACjB,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,GAAG,OAAO,EAAE,CAAC;YACvE,IAAI,CAAC,UAAU,EAAE,CAAC;QACpB,CAAC;IACH,CAAC;IAED,UAAU,CAAC,EAAU;QACnB,IAAI,CAAC,MAAM,CAAC,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;QAC/D,IAAI,CAAC,UAAU,EAAE,CAAC;IACpB,CAAC;IAED,QAAQ,CAAC,KAAkB;QACzB,IAAI,CAAC,MAAM,CAAC,KAAK,GAAG,KAAK,CAAC;QAC1B,IAAI,CAAC,UAAU,EAAE,CAAC;IACpB,CAAC;CACF;AA1DD,sCA0DC"}
@@ -0,0 +1,27 @@
1
+ export interface LogEntry {
2
+ id: string;
3
+ timestamp: number;
4
+ localPort: number;
5
+ method: string;
6
+ path: string;
7
+ statusCode?: number;
8
+ duration: number;
9
+ targetUrl: string;
10
+ error?: string;
11
+ }
12
+ export declare class Logger {
13
+ private logs;
14
+ private maxLogs;
15
+ addLog(entry: Omit<LogEntry, 'id'>): LogEntry;
16
+ getLogs(limit?: number, offset?: number): LogEntry[];
17
+ getLogsByPort(port: number, limit?: number): LogEntry[];
18
+ getLogsByStatusCode(statusCode: number, limit?: number): LogEntry[];
19
+ clearLogs(): void;
20
+ getAllLogs(): LogEntry[];
21
+ getStats(): {
22
+ totalLogs: number;
23
+ errorCount: number;
24
+ averageDuration: number;
25
+ };
26
+ }
27
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/server/logger.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,qBAAa,MAAM;IACjB,OAAO,CAAC,IAAI,CAAkB;IAC9B,OAAO,CAAC,OAAO,CAAO;IAEtB,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,GAAG,QAAQ;IAgB7C,OAAO,CAAC,KAAK,GAAE,MAAY,EAAE,MAAM,GAAE,MAAU,GAAG,QAAQ,EAAE;IAI5D,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,GAAE,MAAY,GAAG,QAAQ,EAAE;IAI5D,mBAAmB,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,GAAE,MAAY,GAAG,QAAQ,EAAE;IAIxE,SAAS,IAAI,IAAI;IAIjB,UAAU,IAAI,QAAQ,EAAE;IAIxB,QAAQ;;;;;CAST"}
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Logger = void 0;
4
+ class Logger {
5
+ constructor() {
6
+ this.logs = [];
7
+ this.maxLogs = 500;
8
+ }
9
+ addLog(entry) {
10
+ const logEntry = {
11
+ id: Math.random().toString(36).slice(2),
12
+ ...entry,
13
+ };
14
+ this.logs.unshift(logEntry);
15
+ // 保持日志数量在限制内
16
+ if (this.logs.length > this.maxLogs) {
17
+ this.logs = this.logs.slice(0, this.maxLogs);
18
+ }
19
+ return logEntry;
20
+ }
21
+ getLogs(limit = 100, offset = 0) {
22
+ return this.logs.slice(offset, offset + limit);
23
+ }
24
+ getLogsByPort(port, limit = 100) {
25
+ return this.logs.filter(log => log.localPort === port).slice(0, limit);
26
+ }
27
+ getLogsByStatusCode(statusCode, limit = 100) {
28
+ return this.logs.filter(log => log.statusCode === statusCode).slice(0, limit);
29
+ }
30
+ clearLogs() {
31
+ this.logs = [];
32
+ }
33
+ getAllLogs() {
34
+ return this.logs;
35
+ }
36
+ getStats() {
37
+ return {
38
+ totalLogs: this.logs.length,
39
+ errorCount: this.logs.filter(l => l.error).length,
40
+ averageDuration: this.logs.length > 0
41
+ ? Math.round(this.logs.reduce((sum, log) => sum + log.duration, 0) / this.logs.length)
42
+ : 0,
43
+ };
44
+ }
45
+ }
46
+ exports.Logger = Logger;
47
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/server/logger.ts"],"names":[],"mappings":";;;AAYA,MAAa,MAAM;IAAnB;QACU,SAAI,GAAe,EAAE,CAAC;QACtB,YAAO,GAAG,GAAG,CAAC;IA+CxB,CAAC;IA7CC,MAAM,CAAC,KAA2B;QAChC,MAAM,QAAQ,GAAa;YACzB,EAAE,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;YACvC,GAAG,KAAK;SACT,CAAC;QAEF,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QAE5B,aAAa;QACb,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC;YACpC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;QAC/C,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,OAAO,CAAC,QAAgB,GAAG,EAAE,SAAiB,CAAC;QAC7C,OAAO,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,KAAK,CAAC,CAAC;IACjD,CAAC;IAED,aAAa,CAAC,IAAY,EAAE,QAAgB,GAAG;QAC7C,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,SAAS,KAAK,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;IACzE,CAAC;IAED,mBAAmB,CAAC,UAAkB,EAAE,QAAgB,GAAG;QACzD,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,UAAU,KAAK,UAAU,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;IAChF,CAAC;IAED,SAAS;QACP,IAAI,CAAC,IAAI,GAAG,EAAE,CAAC;IACjB,CAAC;IAED,UAAU;QACR,OAAO,IAAI,CAAC,IAAI,CAAC;IACnB,CAAC;IAED,QAAQ;QACN,OAAO;YACL,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM;YAC3B,UAAU,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM;YACjD,eAAe,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC;gBACnC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC,GAAG,GAAG,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC;gBACtF,CAAC,CAAC,CAAC;SACN,CAAC;IACJ,CAAC;CACF;AAjDD,wBAiDC"}
@@ -0,0 +1,15 @@
1
+ import { ConfigManager } from './config-manager';
2
+ import { Logger } from './logger';
3
+ export declare class ProxyServer {
4
+ private servers;
5
+ private configManager;
6
+ private logger;
7
+ constructor(configManager: ConfigManager, logger: Logger);
8
+ startProxies(): void;
9
+ private startProxy;
10
+ stopProxy(port: number): void;
11
+ stopAllProxies(): void;
12
+ updateProxies(): void;
13
+ getRunningPorts(): number[];
14
+ }
15
+ //# sourceMappingURL=proxy-server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"proxy-server.d.ts","sourceRoot":"","sources":["../../src/server/proxy-server.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAa,MAAM,kBAAkB,CAAC;AAC5D,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAElC,qBAAa,WAAW;IACtB,OAAO,CAAC,OAAO,CAAuC;IACtD,OAAO,CAAC,aAAa,CAAgB;IACrC,OAAO,CAAC,MAAM,CAAS;gBAEX,aAAa,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM;IAKxD,YAAY,IAAI,IAAI;IAQpB,OAAO,CAAC,UAAU;IAuHlB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAS7B,cAAc,IAAI,IAAI;IAMtB,aAAa,IAAI,IAAI;IAKrB,eAAe,IAAI,MAAM,EAAE;CAG5B"}
@@ -0,0 +1,178 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.ProxyServer = void 0;
40
+ const http = __importStar(require("http"));
41
+ const http_proxy_1 = __importDefault(require("http-proxy"));
42
+ class ProxyServer {
43
+ constructor(configManager, logger) {
44
+ this.servers = new Map();
45
+ this.configManager = configManager;
46
+ this.logger = logger;
47
+ }
48
+ startProxies() {
49
+ const rules = this.configManager.getRules().filter(r => r.enabled);
50
+ for (const rule of rules) {
51
+ this.startProxy(rule);
52
+ }
53
+ }
54
+ startProxy(rule) {
55
+ if (this.servers.has(rule.localPort)) {
56
+ this.stopProxy(rule.localPort);
57
+ }
58
+ const proxy = http_proxy_1.default.createProxyServer({
59
+ target: rule.targetUrl,
60
+ timeout: rule.timeout || 30000,
61
+ changeOrigin: true,
62
+ secure: false, // 允许自签名证书
63
+ followRedirects: true,
64
+ autoRewrite: true,
65
+ });
66
+ const server = http.createServer((req, res) => {
67
+ const startTime = Date.now();
68
+ // 处理 CORS
69
+ if (rule.cors?.enabled) {
70
+ const origins = rule.cors.origins || ['*'];
71
+ const origin = req.headers.origin || '*';
72
+ if (origins.includes('*') || origins.includes(origin)) {
73
+ res.setHeader('Access-Control-Allow-Origin', origin);
74
+ res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, PATCH, OPTIONS');
75
+ res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization, *');
76
+ res.setHeader('Access-Control-Allow-Credentials', 'true');
77
+ }
78
+ }
79
+ // 处理 OPTIONS 请求
80
+ if (req.method === 'OPTIONS') {
81
+ res.writeHead(200);
82
+ res.end();
83
+ return;
84
+ }
85
+ // 代理请求
86
+ let retryCount = 0;
87
+ const maxRetries = rule.retries || 0;
88
+ const handleRequest = () => {
89
+ proxy.web(req, res);
90
+ };
91
+ // 错误处理
92
+ proxy.on('error', (error) => {
93
+ const duration = Date.now() - startTime;
94
+ if (retryCount < maxRetries) {
95
+ retryCount++;
96
+ console.log(`Retry ${retryCount}/${maxRetries} for ${rule.localPort}`);
97
+ handleRequest();
98
+ return;
99
+ }
100
+ // 详细的错误日志
101
+ console.error(`[${rule.localPort}] Proxy error:`, error.message);
102
+ console.error(`[${rule.localPort}] Request: ${req.method} ${req.url}`);
103
+ console.error(`[${rule.localPort}] Target: ${rule.targetUrl}`);
104
+ this.logger.addLog({
105
+ timestamp: Date.now(),
106
+ localPort: rule.localPort,
107
+ method: req.method || 'GET',
108
+ path: req.url || '/',
109
+ duration,
110
+ targetUrl: rule.targetUrl,
111
+ error: error.message,
112
+ });
113
+ if (!res.headersSent) {
114
+ res.writeHead(502, { 'Content-Type': 'application/json' });
115
+ res.end(JSON.stringify({
116
+ error: 'Bad Gateway',
117
+ message: error.message,
118
+ target: rule.targetUrl,
119
+ path: req.url,
120
+ }));
121
+ }
122
+ });
123
+ // 监听代理响应
124
+ proxy.once('proxyRes', (proxyRes) => {
125
+ const duration = Date.now() - startTime;
126
+ this.logger.addLog({
127
+ timestamp: Date.now(),
128
+ localPort: rule.localPort,
129
+ method: req.method || 'GET',
130
+ path: req.url || '/',
131
+ statusCode: proxyRes.statusCode,
132
+ duration,
133
+ targetUrl: rule.targetUrl,
134
+ });
135
+ });
136
+ handleRequest();
137
+ });
138
+ try {
139
+ server.listen(rule.localPort, () => {
140
+ console.log(`✓ Proxy running: localhost:${rule.localPort} -> ${rule.targetUrl}`);
141
+ });
142
+ server.on('error', (error) => {
143
+ if (error.code === 'EADDRINUSE') {
144
+ console.error(`✗ Port ${rule.localPort} is already in use`);
145
+ }
146
+ else {
147
+ console.error(`✗ Error on port ${rule.localPort}:`, error.message);
148
+ }
149
+ });
150
+ this.servers.set(rule.localPort, server);
151
+ }
152
+ catch (error) {
153
+ console.error(`Failed to start proxy on port ${rule.localPort}:`, error);
154
+ }
155
+ }
156
+ stopProxy(port) {
157
+ const server = this.servers.get(port);
158
+ if (server) {
159
+ server.close();
160
+ this.servers.delete(port);
161
+ console.log(`✓ Proxy stopped on port ${port}`);
162
+ }
163
+ }
164
+ stopAllProxies() {
165
+ for (const port of this.servers.keys()) {
166
+ this.stopProxy(port);
167
+ }
168
+ }
169
+ updateProxies() {
170
+ this.stopAllProxies();
171
+ this.startProxies();
172
+ }
173
+ getRunningPorts() {
174
+ return Array.from(this.servers.keys());
175
+ }
176
+ }
177
+ exports.ProxyServer = ProxyServer;
178
+ //# sourceMappingURL=proxy-server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"proxy-server.js","sourceRoot":"","sources":["../../src/server/proxy-server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import { Router } from 'express';
2
+ import { ConfigManager } from '../server/config-manager';
3
+ import { Logger } from '../server/logger';
4
+ import { ProxyServer } from '../server/proxy-server';
5
+ export declare function createApiRouter(configManager: ConfigManager, logger: Logger, proxyServer: ProxyServer): Router;
6
+ //# sourceMappingURL=api-routes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-routes.d.ts","sourceRoot":"","sources":["../../src/web/api-routes.ts"],"names":[],"mappings":"AAAA,OAAgB,EAAE,MAAM,EAAqB,MAAM,SAAS,CAAC;AAC7D,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAErD,wBAAgB,eAAe,CAC7B,aAAa,EAAE,aAAa,EAC5B,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,WAAW,GACvB,MAAM,CAkHR"}
@@ -0,0 +1,112 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.createApiRouter = createApiRouter;
7
+ const express_1 = __importDefault(require("express"));
8
+ function createApiRouter(configManager, logger, proxyServer) {
9
+ const router = express_1.default.Router();
10
+ // 获取所有配置
11
+ router.get('/config', (req, res) => {
12
+ res.json(configManager.getConfig());
13
+ });
14
+ // 保存配置
15
+ router.post('/config', (req, res) => {
16
+ try {
17
+ const { rules } = req.body;
18
+ if (!Array.isArray(rules)) {
19
+ return res.status(400).json({ error: 'Invalid rules format' });
20
+ }
21
+ configManager.setRules(rules);
22
+ proxyServer.updateProxies();
23
+ res.json({ success: true, message: 'Config saved' });
24
+ }
25
+ catch (error) {
26
+ res.status(500).json({ error: error.message });
27
+ }
28
+ });
29
+ // 添加规则
30
+ router.post('/config/rules', (req, res) => {
31
+ try {
32
+ const rule = req.body;
33
+ if (!rule.id) {
34
+ rule.id = Math.random().toString(36).slice(2);
35
+ }
36
+ rule.enabled = rule.enabled !== false;
37
+ configManager.addRule(rule);
38
+ proxyServer.updateProxies();
39
+ res.json({ success: true, rule });
40
+ }
41
+ catch (error) {
42
+ res.status(500).json({ error: error.message });
43
+ }
44
+ });
45
+ // 更新规则
46
+ router.put('/config/rules/:id', (req, res) => {
47
+ try {
48
+ const { id } = req.params;
49
+ const updates = req.body;
50
+ configManager.updateRule(id, updates);
51
+ proxyServer.updateProxies();
52
+ res.json({ success: true, message: 'Rule updated' });
53
+ }
54
+ catch (error) {
55
+ res.status(500).json({ error: error.message });
56
+ }
57
+ });
58
+ // 删除规则
59
+ router.delete('/config/rules/:id', (req, res) => {
60
+ try {
61
+ const { id } = req.params;
62
+ configManager.deleteRule(id);
63
+ proxyServer.updateProxies();
64
+ res.json({ success: true, message: 'Rule deleted' });
65
+ }
66
+ catch (error) {
67
+ res.status(500).json({ error: error.message });
68
+ }
69
+ });
70
+ // 获取日志
71
+ router.get('/logs', (req, res) => {
72
+ try {
73
+ const { limit = '100', offset = '0', port, statusCode } = req.query;
74
+ let logs;
75
+ if (port) {
76
+ logs = logger.getLogsByPort(parseInt(port), parseInt(limit));
77
+ }
78
+ else if (statusCode) {
79
+ logs = logger.getLogsByStatusCode(parseInt(statusCode), parseInt(limit));
80
+ }
81
+ else {
82
+ logs = logger.getLogs(parseInt(limit), parseInt(offset));
83
+ }
84
+ res.json({
85
+ logs,
86
+ stats: logger.getStats(),
87
+ });
88
+ }
89
+ catch (error) {
90
+ res.status(500).json({ error: error.message });
91
+ }
92
+ });
93
+ // 清空日志
94
+ router.delete('/logs', (req, res) => {
95
+ try {
96
+ logger.clearLogs();
97
+ res.json({ success: true, message: 'Logs cleared' });
98
+ }
99
+ catch (error) {
100
+ res.status(500).json({ error: error.message });
101
+ }
102
+ });
103
+ // 获取运行状态
104
+ router.get('/status', (req, res) => {
105
+ res.json({
106
+ runningPorts: proxyServer.getRunningPorts(),
107
+ stats: logger.getStats(),
108
+ });
109
+ });
110
+ return router;
111
+ }
112
+ //# sourceMappingURL=api-routes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-routes.js","sourceRoot":"","sources":["../../src/web/api-routes.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,48 @@
1
+ {
2
+ "name": "@jachy/multiport-proxy",
3
+ "version": "0.0.1",
4
+ "description": "A multi-port proxy server with web UI configuration",
5
+ "main": "dist/index.js",
6
+ "bin": {
7
+ "multiport-proxy": "dist/cli.js"
8
+ },
9
+ "private": false,
10
+ "files": [
11
+ "dist",
12
+ "README.md"
13
+ ],
14
+ "scripts": {
15
+ "dev": "ts-node src/cli.ts",
16
+ "build": "tsc && chmod +x dist/cli.js",
17
+ "start": "node dist/cli.js",
18
+ "prepublishOnly": "pnpm run build",
19
+ "test": "echo \"Error: no test specified\" && exit 1"
20
+ },
21
+ "keywords": ["proxy", "multiport", "http", "cli", "reverse-proxy", "port-forwarding", "web-ui"],
22
+ "author": "Jachy",
23
+ "license": "ISC",
24
+ "repository": {
25
+ "type": "git",
26
+ "url": "git+https://github.com/Mammoth777/multiport-proxy.git"
27
+ },
28
+ "bugs": {
29
+ "url": "https://github.com/Mammoth777/multiport-proxy/issues"
30
+ },
31
+ "homepage": "https://github.com/Mammoth777/multiport-proxy#readme",
32
+ "engines": {
33
+ "node": ">=16.0.0"
34
+ },
35
+ "packageManager": "pnpm@10.17.0",
36
+ "dependencies": {
37
+ "express": "^4.18.2",
38
+ "http-proxy": "^1.18.1",
39
+ "open": "^10.0.0"
40
+ },
41
+ "devDependencies": {
42
+ "@types/express": "^4.17.21",
43
+ "@types/http-proxy": "^1.17.14",
44
+ "@types/node": "^20.10.0",
45
+ "typescript": "^5.3.3",
46
+ "ts-node": "^10.9.2"
47
+ }
48
+ }