@cjwddz/mirror 1.1.0 → 1.2.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/README.md +89 -222
- package/dist/cli/client.d.ts +19 -0
- package/dist/cli/client.d.ts.map +1 -0
- package/dist/cli/client.js +107 -0
- package/dist/cli/client.js.map +1 -0
- package/dist/cli/index.d.ts +1 -1
- package/dist/cli/index.js +88 -51
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/server.d.ts +19 -0
- package/dist/cli/server.d.ts.map +1 -0
- package/dist/cli/server.js +82 -0
- package/dist/cli/server.js.map +1 -0
- package/dist/core/http-tunnel-client.d.ts +64 -0
- package/dist/core/http-tunnel-client.d.ts.map +1 -0
- package/dist/core/http-tunnel-client.js +315 -0
- package/dist/core/http-tunnel-client.js.map +1 -0
- package/dist/core/http-tunnel-protocol.d.ts +86 -0
- package/dist/core/http-tunnel-protocol.d.ts.map +1 -0
- package/dist/core/http-tunnel-protocol.js +29 -0
- package/dist/core/http-tunnel-protocol.js.map +1 -0
- package/dist/core/http-tunnel-server.d.ts +74 -0
- package/dist/core/http-tunnel-server.d.ts.map +1 -0
- package/dist/core/http-tunnel-server.js +317 -0
- package/dist/core/http-tunnel-server.js.map +1 -0
- package/dist/index.d.ts +4 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -8
- package/dist/index.js.map +1 -1
- package/package.json +12 -10
- package/dist/cli/exec.d.ts +0 -9
- package/dist/cli/exec.d.ts.map +0 -1
- package/dist/cli/exec.js +0 -32
- package/dist/cli/exec.js.map +0 -1
- package/dist/cli/host-impl.d.ts +0 -58
- package/dist/cli/host-impl.d.ts.map +0 -1
- package/dist/cli/host-impl.js +0 -547
- package/dist/cli/host-impl.js.map +0 -1
- package/dist/cli/host.d.ts +0 -9
- package/dist/cli/host.d.ts.map +0 -1
- package/dist/cli/host.js +0 -57
- package/dist/cli/host.js.map +0 -1
- package/dist/cli/link.d.ts +0 -10
- package/dist/cli/link.d.ts.map +0 -1
- package/dist/cli/link.js +0 -105
- package/dist/cli/link.js.map +0 -1
- package/dist/cli/logs.d.ts +0 -8
- package/dist/cli/logs.d.ts.map +0 -1
- package/dist/cli/logs.js +0 -48
- package/dist/cli/logs.js.map +0 -1
- package/dist/cli/shell.d.ts +0 -6
- package/dist/cli/shell.d.ts.map +0 -1
- package/dist/cli/shell.js +0 -53
- package/dist/cli/shell.js.map +0 -1
- package/dist/cli/status.d.ts +0 -6
- package/dist/cli/status.d.ts.map +0 -1
- package/dist/cli/status.js +0 -33
- package/dist/cli/status.js.map +0 -1
- package/dist/cli/stop.d.ts +0 -6
- package/dist/cli/stop.d.ts.map +0 -1
- package/dist/cli/stop.js +0 -18
- package/dist/cli/stop.js.map +0 -1
- package/dist/cli/ui/MirrorUI.d.ts +0 -22
- package/dist/cli/ui/MirrorUI.d.ts.map +0 -1
- package/dist/cli/ui/MirrorUI.js +0 -71
- package/dist/cli/ui/MirrorUI.js.map +0 -1
- package/dist/cli/ui/interactive-terminal.d.ts +0 -3
- package/dist/cli/ui/interactive-terminal.d.ts.map +0 -1
- package/dist/cli/ui/interactive-terminal.js +0 -150
- package/dist/cli/ui/interactive-terminal.js.map +0 -1
- package/dist/cli/watch.d.ts +0 -6
- package/dist/cli/watch.d.ts.map +0 -1
- package/dist/cli/watch.js +0 -29
- package/dist/cli/watch.js.map +0 -1
- package/dist/core/daemon.d.ts +0 -154
- package/dist/core/daemon.d.ts.map +0 -1
- package/dist/core/daemon.js +0 -590
- package/dist/core/daemon.js.map +0 -1
- package/dist/core/process-manager.d.ts +0 -19
- package/dist/core/process-manager.d.ts.map +0 -1
- package/dist/core/process-manager.js +0 -76
- package/dist/core/process-manager.js.map +0 -1
- package/dist/transport/pty.d.ts +0 -7
- package/dist/transport/pty.d.ts.map +0 -1
- package/dist/transport/pty.js +0 -26
- package/dist/transport/pty.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,15 +1,14 @@
|
|
|
1
|
-
# Mirror ——
|
|
1
|
+
# Mirror —— HTTP 隧道工具
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
HTTP 隧道工具,将本地服务暴露到公网,无需公网 IP 或配置路由器。
|
|
4
4
|
|
|
5
5
|
## 功能特性
|
|
6
6
|
|
|
7
|
-
- ✅
|
|
8
|
-
- ✅
|
|
9
|
-
- ✅
|
|
10
|
-
- ✅
|
|
11
|
-
- ✅
|
|
12
|
-
- ✅ 一次性 workspace,完全可丢弃
|
|
7
|
+
- ✅ 将本地 HTTP 服务暴露到公网
|
|
8
|
+
- ✅ WebSocket 隧道,低延迟高性能
|
|
9
|
+
- ✅ 支持自定义端口和认证令牌
|
|
10
|
+
- ✅ 自动重连机制
|
|
11
|
+
- ✅ 支持并发请求
|
|
13
12
|
|
|
14
13
|
## 安装
|
|
15
14
|
|
|
@@ -19,128 +18,92 @@ npm install -g @cjwddz/mirror
|
|
|
19
18
|
|
|
20
19
|
## 使用方法
|
|
21
20
|
|
|
22
|
-
### 1.
|
|
21
|
+
### 1. 启动服务端(公网服务器)
|
|
23
22
|
|
|
24
|
-
|
|
25
|
-
mirror host --port 7331
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
或者指定 token:
|
|
23
|
+
在有公网 IP 的服务器上运行:
|
|
29
24
|
|
|
30
25
|
```bash
|
|
31
|
-
mirror
|
|
26
|
+
mirror server --port 80 --tunnel-port 7332
|
|
32
27
|
```
|
|
33
28
|
|
|
34
29
|
可选参数:
|
|
35
30
|
|
|
36
|
-
- `--port <port>`:
|
|
37
|
-
- `--
|
|
38
|
-
- `--
|
|
39
|
-
- `--token <token>`:
|
|
40
|
-
|
|
41
|
-
启动后会显示连接地址:
|
|
42
|
-
|
|
43
|
-
```
|
|
44
|
-
Mirror host started
|
|
45
|
-
Listening on :7331
|
|
46
|
-
|
|
47
|
-
Connect using:
|
|
48
|
-
mirror link 192.168.1.100:7331?token=KJ82mZpX...
|
|
49
|
-
```
|
|
31
|
+
- `--port <port>`: HTTP 服务端口(默认: 80)
|
|
32
|
+
- `--tunnel-port <port>`: WebSocket 隧道端口(默认: 7332)
|
|
33
|
+
- `--host <host>`: 监听地址(默认: 0.0.0.0)
|
|
34
|
+
- `--token <token>`: 认证令牌(可选,建议设置)
|
|
35
|
+
- `--timeout <ms>`: 请求超时时间(毫秒,默认: 30000)
|
|
50
36
|
|
|
51
|
-
### 2.
|
|
37
|
+
### 2. 启动客户端(本地开发机)
|
|
52
38
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
**使用 IP 和端口连接:**
|
|
39
|
+
在本地开发机上运行:
|
|
56
40
|
|
|
57
41
|
```bash
|
|
58
|
-
mirror
|
|
42
|
+
mirror client ws://your-server.com:7332 http://localhost:3000
|
|
59
43
|
```
|
|
60
44
|
|
|
61
|
-
|
|
45
|
+
参数说明:
|
|
62
46
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
mirror link ws://mirror.example.com?token=KJ82mZpX...
|
|
47
|
+
- `serverUrl`: 服务端 WebSocket 地址,格式: `ws://host[:port]`
|
|
48
|
+
- `targetUrl`: 本地服务地址,格式: `http://localhost:port`
|
|
66
49
|
|
|
67
|
-
|
|
68
|
-
mirror link wss://mirror.example.com?token=KJ82mZpX...
|
|
69
|
-
```
|
|
70
|
-
|
|
71
|
-
**URL 格式说明:**
|
|
72
|
-
|
|
73
|
-
- 格式:`[ws://|wss://]host[:port]?token=xxx`
|
|
74
|
-
- `ws://` 或 `wss://` 协议前缀可选(默认 `ws://`)
|
|
75
|
-
- `port` 可选,如果使用反向代理可以不指定端口
|
|
76
|
-
- `token` 必需,用于身份验证
|
|
77
|
-
|
|
78
|
-
连接成功后:
|
|
79
|
-
|
|
80
|
-
1. 自动进行全量文件同步
|
|
81
|
-
2. 启动文件监听(增量同步)
|
|
82
|
-
3. 进入交互式终端
|
|
83
|
-
|
|
84
|
-
在交互式终端中输入命令,命令会在远程服务器的工作空间中执行。
|
|
85
|
-
|
|
86
|
-
输入 `exit` 或 `quit` 退出。
|
|
87
|
-
|
|
88
|
-
## 工作原理
|
|
89
|
-
|
|
90
|
-
### 状态机(v0.1.0 简化版)
|
|
50
|
+
可选参数:
|
|
91
51
|
|
|
92
|
-
|
|
52
|
+
- `--token <token>`: 认证令牌(与服务端设置的一致)
|
|
53
|
+
- `--reconnect-interval <ms>`: 重连间隔(毫秒,默认: 5000)
|
|
54
|
+
- `--max-retries <number>`: 最大重试次数(默认: 10)
|
|
93
55
|
|
|
94
|
-
|
|
95
|
-
- `SYNCING`: 初始全量文件同步中
|
|
96
|
-
- `READY`: 就绪状态(可执行命令,可同步文件)
|
|
56
|
+
### 3. 访问服务
|
|
97
57
|
|
|
98
|
-
|
|
58
|
+
客户端连接成功后,访问服务端地址即可访问本地服务:
|
|
99
59
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
-
|
|
60
|
+
```bash
|
|
61
|
+
# 例如,本地运行了一个服务在 localhost:3000
|
|
62
|
+
# 服务端地址是 your-server.com
|
|
63
|
+
# 现在可以通过 http://your-server.com 访问本地服务
|
|
64
|
+
```
|
|
103
65
|
|
|
104
|
-
|
|
66
|
+
## 使用示例
|
|
105
67
|
|
|
106
|
-
|
|
107
|
-
- 由 client 生成
|
|
108
|
-
- exec 时必须声明 version
|
|
109
|
-
- host 仅在 `exec.version === currentVersion` 时允许执行
|
|
68
|
+
### 基本用法
|
|
110
69
|
|
|
111
|
-
|
|
70
|
+
```bash
|
|
71
|
+
# 服务端(服务器)
|
|
72
|
+
mirror server --port 80 --tunnel-port 7332
|
|
112
73
|
|
|
113
|
-
|
|
114
|
-
-
|
|
115
|
-
|
|
116
|
-
- 使用原子写入保证文件一致性
|
|
117
|
-
- 不再使用 pending 队列机制
|
|
74
|
+
# 客户端(本地)
|
|
75
|
+
mirror client ws://your-server.com:7332 http://localhost:3000
|
|
76
|
+
```
|
|
118
77
|
|
|
119
|
-
|
|
78
|
+
### 使用认证令牌
|
|
120
79
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
-
|
|
80
|
+
```bash
|
|
81
|
+
# 服务端
|
|
82
|
+
mirror server --port 80 --tunnel-port 7332 --token my-secret-token
|
|
124
83
|
|
|
125
|
-
|
|
84
|
+
# 客户端
|
|
85
|
+
mirror client ws://your-server.com:7332 http://localhost:3000 --token my-secret-token
|
|
86
|
+
```
|
|
126
87
|
|
|
127
|
-
|
|
128
|
-
- 命令执行在独立的进程组中
|
|
129
|
-
- 断开连接时自动清理所有进程
|
|
88
|
+
### 自定义端口
|
|
130
89
|
|
|
131
|
-
|
|
90
|
+
```bash
|
|
91
|
+
# 服务端监听 8080 端口,隧道端口 7332
|
|
92
|
+
mirror server --port 8080 --tunnel-port 7332
|
|
132
93
|
|
|
133
|
-
|
|
94
|
+
# 客户端连接到 7332 端口
|
|
95
|
+
mirror client ws://your-server.com:7332 http://localhost:3000
|
|
96
|
+
```
|
|
134
97
|
|
|
135
|
-
###
|
|
98
|
+
### 使用 Nginx 反向代理
|
|
136
99
|
|
|
137
100
|
```nginx
|
|
138
101
|
server {
|
|
139
102
|
listen 80;
|
|
140
|
-
server_name
|
|
103
|
+
server_name tunnel.example.com;
|
|
141
104
|
|
|
142
105
|
location / {
|
|
143
|
-
proxy_pass http://127.0.0.1:
|
|
106
|
+
proxy_pass http://127.0.0.1:80;
|
|
144
107
|
proxy_http_version 1.1;
|
|
145
108
|
|
|
146
109
|
# WebSocket 升级
|
|
@@ -158,169 +121,73 @@ server {
|
|
|
158
121
|
proxy_send_timeout 7d;
|
|
159
122
|
proxy_read_timeout 7d;
|
|
160
123
|
}
|
|
161
|
-
}
|
|
162
|
-
```
|
|
163
|
-
|
|
164
|
-
### HTTPS 配置(推荐)
|
|
165
|
-
|
|
166
|
-
```nginx
|
|
167
|
-
server {
|
|
168
|
-
listen 443 ssl http2;
|
|
169
|
-
server_name mirror.example.com;
|
|
170
|
-
|
|
171
|
-
# SSL 证书配置
|
|
172
|
-
ssl_certificate /path/to/cert.pem;
|
|
173
|
-
ssl_certificate_key /path/to/key.pem;
|
|
174
|
-
|
|
175
|
-
# SSL 优化
|
|
176
|
-
ssl_protocols TLSv1.2 TLSv1.3;
|
|
177
|
-
ssl_ciphers HIGH:!aNULL:!MD5;
|
|
178
|
-
ssl_prefer_server_ciphers on;
|
|
179
124
|
|
|
180
|
-
location / {
|
|
181
|
-
proxy_pass http://127.0.0.1:
|
|
125
|
+
location /tunnel {
|
|
126
|
+
proxy_pass http://127.0.0.1:7332;
|
|
182
127
|
proxy_http_version 1.1;
|
|
183
128
|
|
|
184
|
-
# WebSocket 升级
|
|
185
129
|
proxy_set_header Upgrade $http_upgrade;
|
|
186
130
|
proxy_set_header Connection "upgrade";
|
|
187
131
|
|
|
188
|
-
# 传递原始信息
|
|
189
132
|
proxy_set_header Host $host;
|
|
190
133
|
proxy_set_header X-Real-IP $remote_addr;
|
|
191
134
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
192
|
-
proxy_set_header X-Forwarded-Proto $scheme;
|
|
193
135
|
|
|
194
|
-
# 超时设置(WebSocket 连接可能需要长时间保持)
|
|
195
136
|
proxy_connect_timeout 7d;
|
|
196
137
|
proxy_send_timeout 7d;
|
|
197
138
|
proxy_read_timeout 7d;
|
|
198
139
|
}
|
|
199
140
|
}
|
|
200
|
-
|
|
201
|
-
# HTTP 重定向到 HTTPS
|
|
202
|
-
server {
|
|
203
|
-
listen 80;
|
|
204
|
-
server_name mirror.example.com;
|
|
205
|
-
return 301 https://$server_name$request_uri;
|
|
206
|
-
}
|
|
207
141
|
```
|
|
208
142
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
1. **WebSocket 升级**:`proxy_set_header Upgrade` 和 `Connection "upgrade"` 是必需的,用于将 HTTP 连接升级为 WebSocket
|
|
212
|
-
2. **超时设置**:WebSocket 连接可能需要长时间保持,建议设置较长的超时时间(如 7 天)
|
|
213
|
-
3. **端口映射**:将 `127.0.0.1:7331` 替换为实际的 mirror host 服务地址和端口
|
|
214
|
-
4. **SSL 证书**:使用 HTTPS 时,需要配置有效的 SSL 证书
|
|
215
|
-
|
|
216
|
-
配置完成后,客户端可以使用以下方式连接:
|
|
143
|
+
客户端连接时使用域名:
|
|
217
144
|
|
|
218
145
|
```bash
|
|
219
|
-
|
|
220
|
-
mirror link wss://mirror.example.com?token=KJ82mZpX...
|
|
221
|
-
|
|
222
|
-
# HTTP (不推荐,仅用于测试)
|
|
223
|
-
mirror link ws://mirror.example.com?token=KJ82mZpX...
|
|
146
|
+
mirror client ws://tunnel.example.com/tunnel http://localhost:3000
|
|
224
147
|
```
|
|
225
148
|
|
|
226
|
-
##
|
|
227
|
-
|
|
228
|
-
### 502 Bad Gateway 错误
|
|
229
|
-
|
|
230
|
-
如果连接时遇到 502 错误,通常表示 Nginx 无法连接到后端 mirror host 服务。请检查:
|
|
231
|
-
|
|
232
|
-
1. **mirror host 服务是否运行**:
|
|
233
|
-
|
|
234
|
-
```bash
|
|
235
|
-
# 在服务器上检查
|
|
236
|
-
ps aux | grep mirror
|
|
237
|
-
netstat -tlnp | grep 7331
|
|
238
|
-
```
|
|
239
|
-
|
|
240
|
-
2. **Nginx 配置中的 proxy_pass 地址是否正确**:
|
|
241
|
-
|
|
242
|
-
```nginx
|
|
243
|
-
proxy_pass http://127.0.0.1:7331; # 确保端口和地址正确
|
|
244
|
-
```
|
|
245
|
-
|
|
246
|
-
3. **查看 Nginx 错误日志**:
|
|
247
|
-
```bash
|
|
248
|
-
tail -f /var/log/nginx/error.log
|
|
249
|
-
```
|
|
250
|
-
|
|
251
|
-
更多详细的排查步骤请参考 [TROUBLESHOOTING.md](./TROUBLESHOOTING.md)
|
|
252
|
-
|
|
253
|
-
### 协议选择
|
|
254
|
-
|
|
255
|
-
- 如果域名配置了 HTTPS,**必须使用 `wss://` 协议**
|
|
256
|
-
- 如果域名只配置了 HTTP,使用 `ws://` 协议
|
|
257
|
-
- 使用 IP 地址连接时,根据实际情况选择协议
|
|
149
|
+
## 工作原理
|
|
258
150
|
|
|
259
|
-
|
|
151
|
+
Mirror 通过 WebSocket 建立隧道,将客户端和服务端连接起来:
|
|
260
152
|
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
153
|
+
1. **服务端**:监听 HTTP 端口,接收外部请求
|
|
154
|
+
2. **客户端**:连接到服务端 WebSocket 隧道
|
|
155
|
+
3. **请求转发**:服务端将 HTTP 请求通过隧道转发给客户端
|
|
156
|
+
4. **响应返回**:客户端将请求转发给本地服务,获取响应后返回给服务端
|
|
157
|
+
5. **外部访问**:用户访问服务端地址,实际访问的是本地服务
|
|
264
158
|
|
|
265
|
-
# HTTP 域名(不推荐)
|
|
266
|
-
mirror link ws://mirror.example.com?token=xxx
|
|
267
159
|
```
|
|
268
|
-
|
|
269
|
-
## 新特性
|
|
270
|
-
|
|
271
|
-
### 🎯 实时文件同步(v0.1.0)
|
|
272
|
-
|
|
273
|
-
文件变更实时同步到远程,无论是否有命令在执行:
|
|
274
|
-
|
|
275
|
-
```bash
|
|
276
|
-
> npm run start
|
|
277
|
-
Server listening on port 3000
|
|
278
|
-
[同步] 同步中: src/index.ts (update) ← 实时同步,不干扰命令输出
|
|
279
|
-
[同步] ✓ 已同步: src/index.ts ← 2秒后自动清除
|
|
160
|
+
用户 → 服务端 (HTTP) → WebSocket 隧道 → 客户端 → 本地服务
|
|
280
161
|
```
|
|
281
162
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
- ✅ 不再有 pending 队列,文件立即同步
|
|
285
|
-
- ✅ 长时间运行的命令不会阻塞文件同步
|
|
286
|
-
- ✅ 开发体验更流畅,类似本地开发
|
|
287
|
-
|
|
288
|
-
### 🎯 改进的 Ctrl+C 退出逻辑
|
|
163
|
+
## 注意事项
|
|
289
164
|
|
|
290
|
-
-
|
|
291
|
-
-
|
|
292
|
-
-
|
|
165
|
+
- ⚠️ 服务端需要有公网 IP 或可访问的网络地址
|
|
166
|
+
- ⚠️ 使用认证令牌可以提高安全性
|
|
167
|
+
- ⚠️ 建议使用 Nginx 等 Web 服务器做反向代理
|
|
168
|
+
- ⚠️ 确保防火墙开放相应端口
|
|
169
|
+
- ℹ️ 仅用于开发和测试,不建议在生产环境中使用
|
|
293
170
|
|
|
294
|
-
|
|
295
|
-
> npm run start
|
|
296
|
-
Server listening...
|
|
297
|
-
^C (发送中断信号到远程进程,再次按 Ctrl+C 退出 mirror)
|
|
298
|
-
Server shutting down...
|
|
299
|
-
> _ # 命令中断,mirror 继续运行
|
|
300
|
-
|
|
301
|
-
# 如需退出 mirror,再按一次 Ctrl+C
|
|
302
|
-
```
|
|
171
|
+
## 故障排查
|
|
303
172
|
|
|
304
|
-
###
|
|
173
|
+
### 无法连接
|
|
305
174
|
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
175
|
+
1. 检查服务端是否正常运行
|
|
176
|
+
2. 检查防火墙是否开放端口
|
|
177
|
+
3. 检查 WebSocket 隧道端口是否正确
|
|
178
|
+
4. 检查认证令牌是否匹配
|
|
309
179
|
|
|
310
|
-
|
|
180
|
+
### 请求超时
|
|
311
181
|
|
|
312
|
-
|
|
313
|
-
|
|
182
|
+
1. 检查本地服务是否正常运行
|
|
183
|
+
2. 增加 `--timeout` 参数值
|
|
184
|
+
3. 检查网络连接是否稳定
|
|
314
185
|
|
|
315
|
-
|
|
186
|
+
### 频繁断线
|
|
316
187
|
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
- ⚠️ 不支持恢复,需要重新连接
|
|
321
|
-
- ⚠️ 使用域名连接时,确保使用正确的协议(HTTPS 使用 wss://,HTTP 使用 ws://)
|
|
322
|
-
- ⚠️ 使用反向代理时,确保 Nginx 配置了正确的 WebSocket 升级头
|
|
323
|
-
- ℹ️ 新特性需要客户端和服务端版本匹配才能使用
|
|
188
|
+
1. 检查网络稳定性
|
|
189
|
+
2. 调整 `--reconnect-interval` 参数
|
|
190
|
+
3. 检查服务端资源使用情况
|
|
324
191
|
|
|
325
192
|
## 开发
|
|
326
193
|
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mirror HTTP Tunnel Client CLI 命令
|
|
3
|
+
* 连接到服务端,将 HTTP 请求转发到本地服务
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* 客户端配置选项
|
|
7
|
+
*/
|
|
8
|
+
export interface ClientOptions {
|
|
9
|
+
serverUrl: string;
|
|
10
|
+
targetUrl: string;
|
|
11
|
+
token?: string;
|
|
12
|
+
reconnectInterval: number;
|
|
13
|
+
maxRetries: number;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* 启动 HTTP 隧道客户端
|
|
17
|
+
*/
|
|
18
|
+
export declare function clientCommand(options: ClientOptions): Promise<void>;
|
|
19
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/cli/client.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iBAAiB,EAAE,MAAM,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAqHzE"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mirror HTTP Tunnel Client CLI 命令
|
|
3
|
+
* 连接到服务端,将 HTTP 请求转发到本地服务
|
|
4
|
+
*/
|
|
5
|
+
import { WebSocket } from 'ws';
|
|
6
|
+
import { HttpTunnelClient } from '../core/http-tunnel-client.js';
|
|
7
|
+
/**
|
|
8
|
+
* 启动 HTTP 隧道客户端
|
|
9
|
+
*/
|
|
10
|
+
export async function clientCommand(options) {
|
|
11
|
+
const { serverUrl, targetUrl, token, reconnectInterval, maxRetries } = options;
|
|
12
|
+
console.log('Mirror HTTP Tunnel Client');
|
|
13
|
+
console.log('=========================\n');
|
|
14
|
+
console.log(`[*] Server URL: ${serverUrl}`);
|
|
15
|
+
console.log(`[*] Target URL: ${targetUrl}`);
|
|
16
|
+
if (token) {
|
|
17
|
+
console.log(`[*] Authentication token: ${token}`);
|
|
18
|
+
}
|
|
19
|
+
console.log();
|
|
20
|
+
let tunnelWs = null;
|
|
21
|
+
let tunnelClient = null;
|
|
22
|
+
let retryCount = 0;
|
|
23
|
+
/**
|
|
24
|
+
* 连接到服务器
|
|
25
|
+
*/
|
|
26
|
+
const connect = () => {
|
|
27
|
+
// 构建 WebSocket URL(添加 token)
|
|
28
|
+
let wsUrl = serverUrl;
|
|
29
|
+
if (token) {
|
|
30
|
+
const urlObj = new URL(wsUrl);
|
|
31
|
+
if (!urlObj.searchParams.has('token')) {
|
|
32
|
+
const separator = wsUrl.includes('?') ? '&' : '?';
|
|
33
|
+
wsUrl = `${wsUrl}${separator}token=${token}`;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
console.log(`[*] Connecting to server (attempt ${retryCount + 1}/${maxRetries})...`);
|
|
37
|
+
tunnelWs = new WebSocket(wsUrl);
|
|
38
|
+
tunnelWs.on('open', () => {
|
|
39
|
+
console.log('[✓] WebSocket connected\n');
|
|
40
|
+
retryCount = 0; // 重置重试计数器
|
|
41
|
+
// 等待欢迎消息后再创建 HTTP 隧道客户端
|
|
42
|
+
});
|
|
43
|
+
tunnelWs.on('message', (data) => {
|
|
44
|
+
try {
|
|
45
|
+
const message = JSON.parse(data.toString());
|
|
46
|
+
// 处理欢迎消息
|
|
47
|
+
if (message.type === 'WELCOME') {
|
|
48
|
+
console.log(`[✓] ${message.message}`);
|
|
49
|
+
console.log(`[*] Server version: ${message.serverVersion}`);
|
|
50
|
+
console.log('[*] HTTP tunnel is now active\n');
|
|
51
|
+
// 收到欢迎消息后,创建 HTTP 隧道客户端
|
|
52
|
+
if (!tunnelClient && tunnelWs) {
|
|
53
|
+
tunnelClient = new HttpTunnelClient({
|
|
54
|
+
targetUrl,
|
|
55
|
+
tunnelWs,
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
catch (error) {
|
|
61
|
+
// 忽略解析错误
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
tunnelWs.on('close', (code, reason) => {
|
|
65
|
+
const reasonStr = reason ? reason.toString() : 'Unknown reason';
|
|
66
|
+
console.log(`[!] Disconnected from server: ${reasonStr} (code: ${code})\n`);
|
|
67
|
+
if (tunnelClient) {
|
|
68
|
+
tunnelClient.close();
|
|
69
|
+
tunnelClient = null;
|
|
70
|
+
}
|
|
71
|
+
// 尝试重新连接
|
|
72
|
+
if (retryCount < maxRetries) {
|
|
73
|
+
retryCount++;
|
|
74
|
+
console.log(`[*] Reconnecting in ${reconnectInterval / 1000} seconds...`);
|
|
75
|
+
setTimeout(connect, reconnectInterval);
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
console.log('[!] Max retry attempts reached. Giving up.');
|
|
79
|
+
process.exit(1);
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
tunnelWs.on('error', (error) => {
|
|
83
|
+
console.error('[!] Connection error:', error.message);
|
|
84
|
+
// 不要退出,让 close 事件处理重连
|
|
85
|
+
});
|
|
86
|
+
};
|
|
87
|
+
// 初始连接
|
|
88
|
+
connect();
|
|
89
|
+
// 处理进程退出
|
|
90
|
+
const cleanup = () => {
|
|
91
|
+
console.log('\n[*] Shutting down...');
|
|
92
|
+
if (tunnelClient) {
|
|
93
|
+
tunnelClient.close();
|
|
94
|
+
tunnelClient = null;
|
|
95
|
+
}
|
|
96
|
+
if (tunnelWs) {
|
|
97
|
+
tunnelWs.close();
|
|
98
|
+
tunnelWs = null;
|
|
99
|
+
}
|
|
100
|
+
process.exit(0);
|
|
101
|
+
};
|
|
102
|
+
process.on('SIGINT', cleanup);
|
|
103
|
+
process.on('SIGTERM', cleanup);
|
|
104
|
+
// 防止进程退出
|
|
105
|
+
await new Promise(() => { });
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/cli/client.ts"],"names":[],"mappings":"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"}
|