@chenpu17/tcpmapping 2.1.0 → 2.4.0
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/CHANGELOG.md +92 -0
- package/README.md +78 -8
- package/bin/tcpmapping.js +363 -173
- package/docs/API.md +532 -0
- package/docs/screenshots/dashboard-en-dark.webp +0 -0
- package/docs/screenshots/dashboard-mobile-zh.webp +0 -0
- package/docs/screenshots/dashboard-zh-light.webp +0 -0
- package/docs/screenshots/login-zh-light.webp +0 -0
- package/docs//345/212/237/350/203/275/346/200/273/347/273/223.md +200 -0
- package/docs//345/256/211/345/205/250/351/205/215/347/275/256/350/257/264/346/230/216.md +154 -0
- package/package.json +6 -4
- package/public/common.js +411 -0
- package/public/dashboard.html +1624 -437
- package/public/login.html +430 -107
- package/server.js +1219 -464
- package/setup-password.js +173 -59
package/docs/API.md
ADDED
|
@@ -0,0 +1,532 @@
|
|
|
1
|
+
# API 接口文档
|
|
2
|
+
|
|
3
|
+
## 概述
|
|
4
|
+
|
|
5
|
+
TCP转发服务器提供RESTful API接口,用于管理端口映射、监控连接状态和系统管理。
|
|
6
|
+
|
|
7
|
+
- **Base URL**: `http://localhost:9999`
|
|
8
|
+
- **认证方式**: Session Cookie
|
|
9
|
+
- **数据格式**: JSON
|
|
10
|
+
- **提示语言**: 可选请求头 `X-Language: zh-CN | en-US`,未提供时根据 `Accept-Language` 自动选择;影响响应中的 `message` 字段。
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## 公开接口(无需认证)
|
|
15
|
+
|
|
16
|
+
### 健康检查
|
|
17
|
+
|
|
18
|
+
检查服务器运行状态,用于监控和负载均衡。
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
GET /api/health
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
**响应示例**:
|
|
25
|
+
```json
|
|
26
|
+
{
|
|
27
|
+
"status": "ok",
|
|
28
|
+
"version": "2.4.0",
|
|
29
|
+
"timestamp": "2025-12-08T08:30:00.000Z",
|
|
30
|
+
"uptime": 3600,
|
|
31
|
+
"activeMappings": 3,
|
|
32
|
+
"activeConnections": 5
|
|
33
|
+
}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## 认证接口
|
|
39
|
+
|
|
40
|
+
### 登录
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
POST /api/login
|
|
44
|
+
Content-Type: application/json
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
**请求参数**:
|
|
48
|
+
| 参数 | 类型 | 必填 | 说明 |
|
|
49
|
+
|------|------|------|------|
|
|
50
|
+
| username | string | 是 | 用户名 |
|
|
51
|
+
| password | string | 是 | 密码 |
|
|
52
|
+
|
|
53
|
+
**请求示例**:
|
|
54
|
+
```json
|
|
55
|
+
{
|
|
56
|
+
"username": "admin",
|
|
57
|
+
"password": "YourPassword123"
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
**响应示例**:
|
|
62
|
+
```json
|
|
63
|
+
{
|
|
64
|
+
"success": true,
|
|
65
|
+
"message": "登录成功"
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
**错误响应**:
|
|
70
|
+
- `401`: 用户名或密码错误
|
|
71
|
+
- `429`: 登录尝试次数过多,账户已锁定
|
|
72
|
+
- `503`: 服务器尚未配置管理员密码(请运行 `tcpmapping setup-password`)
|
|
73
|
+
|
|
74
|
+
> 登录成功后会重新生成 Session ID。所有写操作(POST/PUT/DELETE)如果携带 `Origin` 请求头,其 Host 必须与当前服务一致,否则返回 `403`。
|
|
75
|
+
|
|
76
|
+
### 登出
|
|
77
|
+
|
|
78
|
+
```
|
|
79
|
+
POST /api/logout
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
**响应示例**:
|
|
83
|
+
```json
|
|
84
|
+
{
|
|
85
|
+
"success": true,
|
|
86
|
+
"message": "已登出"
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## 端口映射管理(需要认证)
|
|
93
|
+
|
|
94
|
+
### 获取映射列表
|
|
95
|
+
|
|
96
|
+
```
|
|
97
|
+
GET /api/mappings
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
**响应示例**:
|
|
101
|
+
```json
|
|
102
|
+
{
|
|
103
|
+
"success": true,
|
|
104
|
+
"data": [
|
|
105
|
+
{
|
|
106
|
+
"id": "miww2f23ponqwz",
|
|
107
|
+
"name": "Dify",
|
|
108
|
+
"listen": {
|
|
109
|
+
"host": "0.0.0.0",
|
|
110
|
+
"port": 5588
|
|
111
|
+
},
|
|
112
|
+
"target": {
|
|
113
|
+
"host": "113.45.34.202",
|
|
114
|
+
"port": 5588
|
|
115
|
+
},
|
|
116
|
+
"status": "running",
|
|
117
|
+
"connectionCount": 3,
|
|
118
|
+
"bytesReceived": 102400,
|
|
119
|
+
"bytesSent": 204800,
|
|
120
|
+
"totalConnections": 42,
|
|
121
|
+
"totalBytesReceived": 1048576,
|
|
122
|
+
"totalBytesSent": 2097152
|
|
123
|
+
}
|
|
124
|
+
]
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
**字段说明**:
|
|
129
|
+
| 字段 | 类型 | 说明 |
|
|
130
|
+
|------|------|------|
|
|
131
|
+
| id | string | 映射唯一标识符 |
|
|
132
|
+
| name | string | 映射名称 |
|
|
133
|
+
| listen.host | string | 监听主机地址 |
|
|
134
|
+
| listen.port | number | 监听端口 |
|
|
135
|
+
| target.host | string | 目标主机地址 |
|
|
136
|
+
| target.port | number | 目标端口 |
|
|
137
|
+
| status | string | 状态: running / stopped |
|
|
138
|
+
| connectionCount | number | 当前活跃连接数 |
|
|
139
|
+
| bytesReceived | number | 当前活跃连接的上行流量(字节) |
|
|
140
|
+
| bytesSent | number | 当前活跃连接的下行流量(字节) |
|
|
141
|
+
| totalConnections | number | 累计连接数(服务启动以来) |
|
|
142
|
+
| totalBytesReceived | number | 累计上行流量(字节) |
|
|
143
|
+
| totalBytesSent | number | 累计下行流量(字节) |
|
|
144
|
+
|
|
145
|
+
> 累计统计保存在内存中,服务重启后归零。
|
|
146
|
+
|
|
147
|
+
### 添加映射
|
|
148
|
+
|
|
149
|
+
```
|
|
150
|
+
POST /api/mappings
|
|
151
|
+
Content-Type: application/json
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
**请求参数**:
|
|
155
|
+
| 参数 | 类型 | 必填 | 说明 |
|
|
156
|
+
|------|------|------|------|
|
|
157
|
+
| name | string | 是 | 映射名称 |
|
|
158
|
+
| listen.host | string | 否 | 监听地址,默认 0.0.0.0 |
|
|
159
|
+
| listen.port | number | 是 | 监听端口 (1-65535) |
|
|
160
|
+
| target.host | string | 是 | 目标主机地址 |
|
|
161
|
+
| target.port | number | 是 | 目标端口 (1-65535) |
|
|
162
|
+
|
|
163
|
+
**请求示例**:
|
|
164
|
+
```json
|
|
165
|
+
{
|
|
166
|
+
"name": "Web服务",
|
|
167
|
+
"listen": {
|
|
168
|
+
"port": 8080
|
|
169
|
+
},
|
|
170
|
+
"target": {
|
|
171
|
+
"host": "192.168.1.100",
|
|
172
|
+
"port": 3000
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
**响应示例**:
|
|
178
|
+
```json
|
|
179
|
+
{
|
|
180
|
+
"success": true,
|
|
181
|
+
"message": "端口映射已启动",
|
|
182
|
+
"data": {
|
|
183
|
+
"id": "abc123xyz",
|
|
184
|
+
"name": "Web服务",
|
|
185
|
+
"listen": {
|
|
186
|
+
"host": "0.0.0.0",
|
|
187
|
+
"port": 8080
|
|
188
|
+
},
|
|
189
|
+
"target": {
|
|
190
|
+
"host": "192.168.1.100",
|
|
191
|
+
"port": 3000
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
**验证规则**:
|
|
198
|
+
- 映射名称不能为空,且不超过 100 个字符
|
|
199
|
+
- 端口必须在 1-65535 范围内
|
|
200
|
+
- 监听地址和目标主机必须是有效的 IP 地址或域名
|
|
201
|
+
- 监听地址 + 端口不能与已有映射重复
|
|
202
|
+
- 端口被占用时会返回 `400`,且不会写入配置
|
|
203
|
+
|
|
204
|
+
### 更新映射
|
|
205
|
+
|
|
206
|
+
```
|
|
207
|
+
PUT /api/mappings/:identifier
|
|
208
|
+
Content-Type: application/json
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
**路径参数**:
|
|
212
|
+
- `identifier`: 映射ID或索引
|
|
213
|
+
|
|
214
|
+
**请求示例**:
|
|
215
|
+
```json
|
|
216
|
+
{
|
|
217
|
+
"name": "新名称",
|
|
218
|
+
"target": {
|
|
219
|
+
"host": "192.168.1.200",
|
|
220
|
+
"port": 3001
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
**响应示例**:
|
|
226
|
+
```json
|
|
227
|
+
{
|
|
228
|
+
"success": true,
|
|
229
|
+
"message": "端口映射已更新",
|
|
230
|
+
"data": {
|
|
231
|
+
"id": "abc123xyz",
|
|
232
|
+
"name": "新名称",
|
|
233
|
+
"listen": {
|
|
234
|
+
"host": "0.0.0.0",
|
|
235
|
+
"port": 8080
|
|
236
|
+
},
|
|
237
|
+
"target": {
|
|
238
|
+
"host": "192.168.1.200",
|
|
239
|
+
"port": 3001
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
> 只更新请求中提供的字段。若映射原本处于停止状态,更新后仍保持停止。
|
|
246
|
+
> 仅修改名称或目标地址时不会重启监听,已有连接不受影响(新连接使用新目标);修改监听地址或端口时会重新绑定,已有连接会被断开。
|
|
247
|
+
|
|
248
|
+
### 删除映射
|
|
249
|
+
|
|
250
|
+
```
|
|
251
|
+
DELETE /api/mappings/:identifier
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
**路径参数**:
|
|
255
|
+
- `identifier`: 映射ID或索引
|
|
256
|
+
|
|
257
|
+
**响应示例**:
|
|
258
|
+
```json
|
|
259
|
+
{
|
|
260
|
+
"success": true,
|
|
261
|
+
"message": "端口映射已删除"
|
|
262
|
+
}
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
### 启动映射
|
|
266
|
+
|
|
267
|
+
```
|
|
268
|
+
POST /api/mappings/:identifier/start
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
**响应示例**:
|
|
272
|
+
```json
|
|
273
|
+
{
|
|
274
|
+
"success": true,
|
|
275
|
+
"message": "端口映射已启动"
|
|
276
|
+
}
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
### 停止映射
|
|
280
|
+
|
|
281
|
+
```
|
|
282
|
+
POST /api/mappings/:identifier/stop
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
**响应示例**:
|
|
286
|
+
```json
|
|
287
|
+
{
|
|
288
|
+
"success": true,
|
|
289
|
+
"message": "端口映射已停止"
|
|
290
|
+
}
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
---
|
|
294
|
+
|
|
295
|
+
## 监控接口(需要认证)
|
|
296
|
+
|
|
297
|
+
### 获取连接状态
|
|
298
|
+
|
|
299
|
+
```
|
|
300
|
+
GET /api/connections
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
**响应示例**:
|
|
304
|
+
```json
|
|
305
|
+
{
|
|
306
|
+
"success": true,
|
|
307
|
+
"data": {
|
|
308
|
+
"total": 5,
|
|
309
|
+
"byPort": [
|
|
310
|
+
{
|
|
311
|
+
"host": "0.0.0.0",
|
|
312
|
+
"port": 5588,
|
|
313
|
+
"mappingName": "Dify",
|
|
314
|
+
"totalConnections": 3,
|
|
315
|
+
"connections": [
|
|
316
|
+
{
|
|
317
|
+
"id": "conn123",
|
|
318
|
+
"mappingName": "Dify",
|
|
319
|
+
"sourceHost": "0.0.0.0",
|
|
320
|
+
"sourcePort": 5588,
|
|
321
|
+
"listenAddress": "192.168.1.5:5588",
|
|
322
|
+
"clientAddress": "192.168.1.10:54321",
|
|
323
|
+
"targetAddress": "113.45.34.202:5588",
|
|
324
|
+
"startTime": "2025-12-08T08:00:00.000Z",
|
|
325
|
+
"lastActivity": 1733648400000,
|
|
326
|
+
"durationMs": 120000,
|
|
327
|
+
"bytesReceived": 10240,
|
|
328
|
+
"bytesSent": 20480,
|
|
329
|
+
"status": "connected"
|
|
330
|
+
}
|
|
331
|
+
]
|
|
332
|
+
}
|
|
333
|
+
]
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
**字段说明**:
|
|
339
|
+
| 字段 | 类型 | 说明 |
|
|
340
|
+
|------|------|------|
|
|
341
|
+
| listenAddress | string | 客户端实际连接到的本地地址(如配置为 `0.0.0.0`,这里显示真实网卡地址) |
|
|
342
|
+
| clientAddress | string | 客户端源地址(IP:端口) |
|
|
343
|
+
| targetAddress | string | 转发目的地址(IP:端口) |
|
|
344
|
+
| durationMs | number | 连接已持续时长(毫秒) |
|
|
345
|
+
|
|
346
|
+
### 获取最近连接记录
|
|
347
|
+
|
|
348
|
+
```
|
|
349
|
+
GET /api/connections/history?mappingId=<id>&limit=100
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
**查询参数**:
|
|
353
|
+
| 参数 | 类型 | 必填 | 说明 |
|
|
354
|
+
|------|------|------|------|
|
|
355
|
+
| mappingId | string | 否 | 只返回指定映射的记录 |
|
|
356
|
+
| limit | number | 否 | 返回条数,默认 50,最大 200 |
|
|
357
|
+
|
|
358
|
+
**响应示例**:
|
|
359
|
+
```json
|
|
360
|
+
{
|
|
361
|
+
"success": true,
|
|
362
|
+
"data": {
|
|
363
|
+
"total": 120,
|
|
364
|
+
"limit": 100,
|
|
365
|
+
"items": [
|
|
366
|
+
{
|
|
367
|
+
"id": "conn123",
|
|
368
|
+
"mappingId": "abc123xyz",
|
|
369
|
+
"mappingName": "Web服务",
|
|
370
|
+
"listenAddress": "192.168.1.5:5588",
|
|
371
|
+
"clientAddress": "192.168.1.10:54321",
|
|
372
|
+
"targetAddress": "113.45.34.202:5588",
|
|
373
|
+
"startTime": "2025-12-08T08:00:00.000Z",
|
|
374
|
+
"endTime": "2025-12-08T08:02:00.000Z",
|
|
375
|
+
"durationMs": 120000,
|
|
376
|
+
"bytesReceived": 10240,
|
|
377
|
+
"bytesSent": 20480,
|
|
378
|
+
"status": "connected",
|
|
379
|
+
"closeReason": "客户端关闭"
|
|
380
|
+
}
|
|
381
|
+
]
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
> 记录只在内存中保留最近 500 条已关闭连接,服务重启后清空;通过 CLI(`tcpmapping start`)启动时,连接关闭日志会同时写入日志文件。`status` 为 `connecting` 表示目标连接尚未建立即结束。
|
|
387
|
+
|
|
388
|
+
### 获取系统状态
|
|
389
|
+
|
|
390
|
+
```
|
|
391
|
+
GET /api/status
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
**响应示例**:
|
|
395
|
+
```json
|
|
396
|
+
{
|
|
397
|
+
"success": true,
|
|
398
|
+
"data": {
|
|
399
|
+
"version": "2.4.0",
|
|
400
|
+
"username": "admin",
|
|
401
|
+
"totalMappings": 3,
|
|
402
|
+
"activeMappings": 3,
|
|
403
|
+
"totalConnections": 5,
|
|
404
|
+
"uptime": 3600.5,
|
|
405
|
+
"memoryUsage": {
|
|
406
|
+
"rss": 51544064,
|
|
407
|
+
"heapTotal": 10272768,
|
|
408
|
+
"heapUsed": 8239376,
|
|
409
|
+
"external": 2104438,
|
|
410
|
+
"arrayBuffers": 18635
|
|
411
|
+
},
|
|
412
|
+
"resources": {
|
|
413
|
+
"cpuPercent": 1.25,
|
|
414
|
+
"cpuCount": 8,
|
|
415
|
+
"memory": {
|
|
416
|
+
"rss": 51544064,
|
|
417
|
+
"heapTotal": 10272768,
|
|
418
|
+
"heapUsed": 8239376,
|
|
419
|
+
"external": 2104438,
|
|
420
|
+
"arrayBuffers": 18635,
|
|
421
|
+
"systemTotal": 17179869184,
|
|
422
|
+
"systemFree": 4294967296
|
|
423
|
+
},
|
|
424
|
+
"traffic": {
|
|
425
|
+
"receivedPerSecond": 20480,
|
|
426
|
+
"sentPerSecond": 18240,
|
|
427
|
+
"totalReceived": 104857600,
|
|
428
|
+
"totalSent": 99614720
|
|
429
|
+
},
|
|
430
|
+
"sampledAt": "2025-12-08T08:30:00.000Z"
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
```
|
|
435
|
+
|
|
436
|
+
**`resources` 字段说明**:
|
|
437
|
+
|
|
438
|
+
| 字段 | 说明 |
|
|
439
|
+
|------|------|
|
|
440
|
+
| `cpuPercent` | 服务进程 CPU 使用率,已按核心数归一化到 0-100(占整机比例),每秒采样一次 |
|
|
441
|
+
| `cpuCount` | 可用 CPU 核心数 |
|
|
442
|
+
| `memory.rss` | 进程常驻内存(RSS) |
|
|
443
|
+
| `memory.heapUsed` / `heapTotal` | V8 堆已用 / 已申请内存 |
|
|
444
|
+
| `memory.systemTotal` / `systemFree` | 系统总内存 / 当前可用内存,用于计算进程占系统内存的比例 |
|
|
445
|
+
| `traffic.receivedPerSecond` | 实时上行速率(客户端 → 目标),字节/秒,按采样间隔计算 |
|
|
446
|
+
| `traffic.sentPerSecond` | 实时下行速率(目标 → 客户端),字节/秒 |
|
|
447
|
+
| `traffic.totalReceived` / `totalSent` | 进程启动以来的累计上下行流量,映射被删除后仍然保留 |
|
|
448
|
+
| `sampledAt` | 最近一次采样时间(ISO 8601) |
|
|
449
|
+
|
|
450
|
+
> 资源数据由进程内每秒采样器维护;`cpuPercent` 是整机占比(单核满载为 `100 / cpuCount`%),不是单核使用率。
|
|
451
|
+
|
|
452
|
+
---
|
|
453
|
+
|
|
454
|
+
## 错误响应
|
|
455
|
+
|
|
456
|
+
所有API在发生错误时返回统一格式:
|
|
457
|
+
|
|
458
|
+
```json
|
|
459
|
+
{
|
|
460
|
+
"success": false,
|
|
461
|
+
"message": "错误描述信息"
|
|
462
|
+
}
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
**HTTP状态码**:
|
|
466
|
+
| 状态码 | 说明 |
|
|
467
|
+
|--------|------|
|
|
468
|
+
| 200 | 成功 |
|
|
469
|
+
| 400 | 请求参数错误 / 端口被占用 / 配置保存失败 |
|
|
470
|
+
| 401 | 未认证 / 认证失败 |
|
|
471
|
+
| 403 | 跨站请求被拒绝 |
|
|
472
|
+
| 404 | 资源不存在 |
|
|
473
|
+
| 429 | 请求过于频繁 |
|
|
474
|
+
| 500 | 服务器内部错误 |
|
|
475
|
+
| 503 | 尚未配置管理员密码 |
|
|
476
|
+
|
|
477
|
+
---
|
|
478
|
+
|
|
479
|
+
## 使用示例
|
|
480
|
+
|
|
481
|
+
### cURL 示例
|
|
482
|
+
|
|
483
|
+
```bash
|
|
484
|
+
# 登录
|
|
485
|
+
curl -X POST http://localhost:9999/api/login \
|
|
486
|
+
-H "Content-Type: application/json" \
|
|
487
|
+
-d '{"username":"admin","password":"YourPassword"}' \
|
|
488
|
+
-c cookies.txt
|
|
489
|
+
|
|
490
|
+
# 获取映射列表
|
|
491
|
+
curl http://localhost:9999/api/mappings -b cookies.txt
|
|
492
|
+
|
|
493
|
+
# 添加映射
|
|
494
|
+
curl -X POST http://localhost:9999/api/mappings \
|
|
495
|
+
-H "Content-Type: application/json" \
|
|
496
|
+
-d '{"name":"测试","listen":{"port":8888},"target":{"host":"127.0.0.1","port":80}}' \
|
|
497
|
+
-b cookies.txt
|
|
498
|
+
|
|
499
|
+
# 停止映射
|
|
500
|
+
curl -X POST http://localhost:9999/api/mappings/0/stop -b cookies.txt
|
|
501
|
+
|
|
502
|
+
# 删除映射
|
|
503
|
+
curl -X DELETE http://localhost:9999/api/mappings/0 -b cookies.txt
|
|
504
|
+
|
|
505
|
+
# 健康检查
|
|
506
|
+
curl http://localhost:9999/api/health
|
|
507
|
+
```
|
|
508
|
+
|
|
509
|
+
### JavaScript 示例
|
|
510
|
+
|
|
511
|
+
```javascript
|
|
512
|
+
// 登录
|
|
513
|
+
const login = await fetch('/api/login', {
|
|
514
|
+
method: 'POST',
|
|
515
|
+
headers: { 'Content-Type': 'application/json' },
|
|
516
|
+
body: JSON.stringify({ username: 'admin', password: 'YourPassword' })
|
|
517
|
+
});
|
|
518
|
+
|
|
519
|
+
// 获取映射列表
|
|
520
|
+
const mappings = await fetch('/api/mappings').then(r => r.json());
|
|
521
|
+
|
|
522
|
+
// 添加映射
|
|
523
|
+
const newMapping = await fetch('/api/mappings', {
|
|
524
|
+
method: 'POST',
|
|
525
|
+
headers: { 'Content-Type': 'application/json' },
|
|
526
|
+
body: JSON.stringify({
|
|
527
|
+
name: '新映射',
|
|
528
|
+
listen: { port: 8888 },
|
|
529
|
+
target: { host: '127.0.0.1', port: 80 }
|
|
530
|
+
})
|
|
531
|
+
}).then(r => r.json());
|
|
532
|
+
```
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|