@jachy/multiport-proxy 0.0.2 → 0.0.3
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.
|
@@ -1 +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;
|
|
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;AAG7D,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAkDrD,wBAAgB,eAAe,CAC7B,aAAa,EAAE,aAAa,EAC5B,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,WAAW,GACvB,MAAM,CA0IR"}
|
package/dist/web/api-routes.js
CHANGED
|
@@ -5,6 +5,51 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.createApiRouter = createApiRouter;
|
|
7
7
|
const express_1 = __importDefault(require("express"));
|
|
8
|
+
const child_process_1 = require("child_process");
|
|
9
|
+
// 检查端口是否被占用
|
|
10
|
+
function checkPortAvailable(port) {
|
|
11
|
+
const isWindows = process.platform === 'win32';
|
|
12
|
+
try {
|
|
13
|
+
let command;
|
|
14
|
+
let output;
|
|
15
|
+
if (isWindows) {
|
|
16
|
+
// Windows 使用 netstat
|
|
17
|
+
command = `netstat -ano | findstr :${port}`;
|
|
18
|
+
output = (0, child_process_1.execSync)(command, { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] }).toString();
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
// macOS 和 Linux 使用 lsof
|
|
22
|
+
command = `lsof -i :${port}`;
|
|
23
|
+
output = (0, child_process_1.execSync)(command, { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] }).toString();
|
|
24
|
+
}
|
|
25
|
+
if (output.trim()) {
|
|
26
|
+
const lines = output.trim().split('\n');
|
|
27
|
+
const details = lines.slice(1).map(line => line.trim()).join('\n');
|
|
28
|
+
return {
|
|
29
|
+
available: false,
|
|
30
|
+
details: `端口 ${port} 已被占用\n\n程序信息:\n${details}`,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
return {
|
|
34
|
+
available: true,
|
|
35
|
+
details: `端口 ${port} 可用`,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
// 命令执行失败可能表示端口未被占用
|
|
40
|
+
if (error.status === 1 || error.code === 1) {
|
|
41
|
+
return {
|
|
42
|
+
available: true,
|
|
43
|
+
details: `端口 ${port} 可用`,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
// 其他错误
|
|
47
|
+
return {
|
|
48
|
+
available: false,
|
|
49
|
+
details: `端口 ${port} 检查失败: ${error.message}`,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
}
|
|
8
53
|
function createApiRouter(configManager, logger, proxyServer) {
|
|
9
54
|
const router = express_1.default.Router();
|
|
10
55
|
// 获取所有配置
|
|
@@ -27,13 +72,21 @@ function createApiRouter(configManager, logger, proxyServer) {
|
|
|
27
72
|
}
|
|
28
73
|
});
|
|
29
74
|
// 添加规则
|
|
30
|
-
router.post('/config/rules', (req, res) => {
|
|
75
|
+
router.post('/config/rules', async (req, res) => {
|
|
31
76
|
try {
|
|
32
77
|
const rule = req.body;
|
|
33
78
|
if (!rule.id) {
|
|
34
79
|
rule.id = Math.random().toString(36).slice(2);
|
|
35
80
|
}
|
|
36
81
|
rule.enabled = rule.enabled !== false;
|
|
82
|
+
// 检查端口是否被占用
|
|
83
|
+
const portCheck = checkPortAvailable(rule.localPort);
|
|
84
|
+
if (!portCheck.available) {
|
|
85
|
+
return res.status(400).json({
|
|
86
|
+
error: 'Port unavailable',
|
|
87
|
+
details: portCheck.details,
|
|
88
|
+
});
|
|
89
|
+
}
|
|
37
90
|
configManager.addRule(rule);
|
|
38
91
|
proxyServer.updateProxies();
|
|
39
92
|
res.json({ success: true, rule });
|
|
@@ -43,10 +96,23 @@ function createApiRouter(configManager, logger, proxyServer) {
|
|
|
43
96
|
}
|
|
44
97
|
});
|
|
45
98
|
// 更新规则
|
|
46
|
-
router.put('/config/rules/:id', (req, res) => {
|
|
99
|
+
router.put('/config/rules/:id', async (req, res) => {
|
|
47
100
|
try {
|
|
48
101
|
const { id } = req.params;
|
|
49
102
|
const updates = req.body;
|
|
103
|
+
// 获取旧规则
|
|
104
|
+
const oldRule = configManager.getConfig().rules.find(r => r.id === id);
|
|
105
|
+
const portChanged = oldRule && oldRule.localPort !== updates.localPort;
|
|
106
|
+
// 如果端口改变了,需要检查新端口是否可用
|
|
107
|
+
if (portChanged) {
|
|
108
|
+
const portCheck = checkPortAvailable(updates.localPort);
|
|
109
|
+
if (!portCheck.available) {
|
|
110
|
+
return res.status(400).json({
|
|
111
|
+
error: 'Port unavailable',
|
|
112
|
+
details: portCheck.details,
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
}
|
|
50
116
|
configManager.updateRule(id, updates);
|
|
51
117
|
proxyServer.updateProxies();
|
|
52
118
|
res.json({ success: true, message: 'Rule updated' });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api-routes.js","sourceRoot":"","sources":["../../src/web/api-routes.ts"],"names":[],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"api-routes.js","sourceRoot":"","sources":["../../src/web/api-routes.ts"],"names":[],"mappings":"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"}
|
package/dist/web/ui/app.js
CHANGED
|
@@ -59,8 +59,9 @@ function showAddRuleForm() {
|
|
|
59
59
|
document.getElementById('ruleTimeout').value = '30000';
|
|
60
60
|
document.getElementById('ruleRetries').value = '0';
|
|
61
61
|
document.getElementById('ruleEnabled').checked = true;
|
|
62
|
-
document.getElementById('ruleCorsEnabled').checked =
|
|
63
|
-
document.getElementById('corsOrigins')
|
|
62
|
+
document.getElementById('ruleCorsEnabled').checked = true;
|
|
63
|
+
const corsOrigins = document.getElementById('corsOrigins');
|
|
64
|
+
corsOrigins.style.display = 'block';
|
|
64
65
|
document.getElementById('ruleModal').classList.add('show');
|
|
65
66
|
}
|
|
66
67
|
|
|
@@ -120,7 +121,8 @@ async function saveRule(e) {
|
|
|
120
121
|
});
|
|
121
122
|
|
|
122
123
|
if (!response.ok) {
|
|
123
|
-
|
|
124
|
+
const errorData = await response.json();
|
|
125
|
+
throw new Error(errorData.details || errorData.error || 'Failed to update rule');
|
|
124
126
|
}
|
|
125
127
|
} else {
|
|
126
128
|
// 新增规则
|
|
@@ -131,7 +133,8 @@ async function saveRule(e) {
|
|
|
131
133
|
});
|
|
132
134
|
|
|
133
135
|
if (!response.ok) {
|
|
134
|
-
|
|
136
|
+
const errorData = await response.json();
|
|
137
|
+
throw new Error(errorData.details || errorData.error || 'Failed to add rule');
|
|
135
138
|
}
|
|
136
139
|
}
|
|
137
140
|
|
package/dist/web/ui/index.html
CHANGED
|
@@ -100,7 +100,7 @@
|
|
|
100
100
|
|
|
101
101
|
<div class="form-group" id="corsOrigins" style="display: none;">
|
|
102
102
|
<label for="ruleCorsOrigins">CORS 来源 (逗号分隔)</label>
|
|
103
|
-
<input type="text" id="ruleCorsOrigins" placeholder="* 或 http://localhost:3000, http://localhost:3001">
|
|
103
|
+
<input type="text" id="ruleCorsOrigins" value="*" placeholder="* 或 http://localhost:3000, http://localhost:3001">
|
|
104
104
|
</div>
|
|
105
105
|
|
|
106
106
|
<div class="form-group">
|