dsh-mesh-access 1.0.1 → 1.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.
- package/CHANGELOG.md +16 -0
- package/README.en.md +6 -2
- package/README.md +31 -2
- package/lib/client.js +1 -1
- package/lib/index.js +10 -1
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# 更新日志
|
|
2
2
|
|
|
3
|
+
## 1.0.3 — 静态资源长缓存(给慢链路减负)
|
|
4
|
+
|
|
5
|
+
上游返回的 `/assets/*.js|css` **没有** `cache-control`,也没有 `etag` / `last-modified`,浏览器无法判断新鲜度,重载时只能整套重新下载(一套 1.5–3 MB)。在组网这种 250 KB/s、往返 500 ms 的链路上,一次重连就等于重传一遍,越重连越慢、越慢越容易再断。
|
|
6
|
+
|
|
7
|
+
- 反代对 `/assets/<带哈希>.(js|css|woff2|png|svg|webp)` 补上 `cache-control: public, max-age=31536000, immutable`;
|
|
8
|
+
- 文件名本身带内容哈希,所以长缓存是安全的(换版本 = 换文件名)。
|
|
9
|
+
|
|
10
|
+
## 1.0.2 — 把卖点改成「手机远程控制」
|
|
11
|
+
|
|
12
|
+
功能没变,只是把话说对:这东西最主要的用法是**用手机远程控制电脑上的 DSH**(同一个实例、同一份会话),
|
|
13
|
+
「笔记本 / NAS / 电视盒子也能开」降级成附加卖点。
|
|
14
|
+
|
|
15
|
+
- README 中英开头改成手机优先;
|
|
16
|
+
- npm 描述、市场条目中英描述同步;
|
|
17
|
+
- 面板副标题改成「用手机远程控制:手机浏览器打开就是你在电脑上用的那个 DSH」。
|
|
18
|
+
|
|
3
19
|
## 1.0.1 — 修「一直重新连接中」
|
|
4
20
|
|
|
5
21
|
`Origin` 没有跟着 `Host` 一起改写,DSH 的 WebSocket 升级被自己的同源校验挡成 **403**,
|
package/README.en.md
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
# dsh-mesh-access
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
**Control your DSH from your phone.** Open the address in a phone browser and you get the very
|
|
4
|
+
same UI you are using on the desktop — same instance, same session list, same context. No SSH,
|
|
5
|
+
no second `dsh`, no router to touch.
|
|
6
|
+
|
|
7
|
+
Under the hood it mounts the running DeepSeek Harness web UI onto a mesh/VPN interface, from
|
|
8
|
+
inside the server process.
|
|
5
9
|
|
|
6
10
|
[English](#what-it-does) | [中文](README.md)
|
|
7
11
|
|
package/README.md
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
# dsh-mesh-access
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
**用手机远程控制电脑上的 DSH。** 手机浏览器打开,就是你在电脑上正在用的那个界面 ——
|
|
4
|
+
同一个实例、同一份会话、同一份上下文,不需要 SSH,不需要第二个 `dsh`,也不用碰路由器。
|
|
5
|
+
|
|
6
|
+
底层做法是把正在运行的 DeepSeek Harness 网页界面挂到组网网卡上,在服务进程内部完成。
|
|
5
7
|
|
|
6
8
|
[中文](#它做什么) | [English](README.en.md)
|
|
7
9
|
|
|
@@ -130,3 +132,30 @@ curl -s http://127.0.0.1:3080/api/dsh-mesh-access/status
|
|
|
130
132
|
## 许可
|
|
131
133
|
|
|
132
134
|
MIT。
|
|
135
|
+
|
|
136
|
+
## 常见问题
|
|
137
|
+
|
|
138
|
+
**页面能打开、侧边栏也有,但底部一直「重新连接中…」,工作区列表空着**
|
|
139
|
+
|
|
140
|
+
这是 1.0.0 的 bug,升级到 **1.0.1** 即可。原因:反代把 `Host` 改写成上游(`127.0.0.1:3080`)却没改 `Origin`,DSH 对 WebSocket 升级做同源校验,浏览器带着 `Origin: http://<组网IP>:<端口>` 过来,两边不一致 → 上游直接 `403 Forbidden`。于是普通 HTTP 全通(页面能开、API 能查),实时通道一次都没握上手,浏览器每几秒重试一次,看起来就像“网络一直断”。
|
|
141
|
+
|
|
142
|
+
自查一行就够:
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
curl -s -o /dev/null -w '%{http_code}\n' --http1.1 \
|
|
146
|
+
-H 'Connection: Upgrade' -H 'Upgrade: websocket' \
|
|
147
|
+
-H 'Sec-WebSocket-Version: 13' -H 'Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==' \
|
|
148
|
+
-H "Origin: http://<组网IP>:<端口>" \
|
|
149
|
+
-b <你浏览器的 cookie> \
|
|
150
|
+
http://<组网IP>:<端口>/api/remote.mux
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
`101` 是正常,`403` 就是中了这个 bug。
|
|
154
|
+
|
|
155
|
+
**改了端口或组网 IP,面板上的地址还能用吗**
|
|
156
|
+
|
|
157
|
+
不能。反代一开出来,监听地址和上游端口就固定了;「访问地址」里的 token 也是按当时的地址签的。换了就点「关闭」→「在组网地址上开端口」,重新复制地址。
|
|
158
|
+
|
|
159
|
+
**组网里的设备打开地址却超时**
|
|
160
|
+
|
|
161
|
+
先确认那台设备能路由到组网 IP(`ping <组网IP>`),再确认本机防火墙放行该端口。Linux 上 `firewall-cmd --zone=<组网域> --list-ports`,Windows 上查该端口的入站规则。
|
package/lib/client.js
CHANGED
|
@@ -140,7 +140,7 @@ window.__ModuleLoader__.load({
|
|
|
140
140
|
'div',
|
|
141
141
|
{ style: S.wrap },
|
|
142
142
|
h('div', { style: S.h1 }, '组网访问'),
|
|
143
|
-
h('div', { style: S.sub }, '
|
|
143
|
+
h('div', { style: S.sub }, '用手机远程控制:手机浏览器打开就是你在电脑上用的那个 DSH——同一实例、同一份会话,不用第二个实例,不用 SSH。'),
|
|
144
144
|
|
|
145
145
|
h(
|
|
146
146
|
Card, { title: '当前状态' },
|
package/lib/index.js
CHANGED
|
@@ -88,6 +88,9 @@ function createProxy({ listenAddress, listenPort, upstream, upstreamPort }) {
|
|
|
88
88
|
// 上游地址,就必须把 Origin 一起改写成上游的 origin;否则浏览器的 WebSocket 升级
|
|
89
89
|
// 永远 403,界面上表现成「一直重新连接中」。
|
|
90
90
|
const upstreamOrigin = `http://${target}`
|
|
91
|
+
// 带内容哈希的静态资源(/assets/index-BXV-oxvX.js 这种)
|
|
92
|
+
const CACHEABLE = /\/assets\/[^?]+\.(?:js|css|woff2?|png|svg|webp)$/
|
|
93
|
+
|
|
91
94
|
const rewrite = (headers) => {
|
|
92
95
|
const h = { ...headers }
|
|
93
96
|
const incomingHost = headers.host ?? ''
|
|
@@ -102,7 +105,13 @@ function createProxy({ listenAddress, listenPort, upstream, upstreamPort }) {
|
|
|
102
105
|
const up = http.request(
|
|
103
106
|
{ host: upstream, port: upstreamPort, method: req.method, path: req.url, headers: rewrite(req.headers) },
|
|
104
107
|
(r) => {
|
|
105
|
-
|
|
108
|
+
const headers = { ...r.headers }
|
|
109
|
+
// 前端资源文件名带内容哈希,可以放心长缓存。上游没给 cache-control / etag,
|
|
110
|
+
// 浏览器就只能每次重新下载(一套 1.5–3 MB),在组网这种慢链路上等于每次重连都重传一遍。
|
|
111
|
+
if (r.statusCode === 200 && CACHEABLE.test(req.url || '')) {
|
|
112
|
+
headers['cache-control'] = 'public, max-age=31536000, immutable'
|
|
113
|
+
}
|
|
114
|
+
res.writeHead(r.statusCode ?? 502, headers)
|
|
106
115
|
r.pipe(res)
|
|
107
116
|
},
|
|
108
117
|
)
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-mesh-access",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "1.0.3",
|
|
4
|
+
"description": "Control your DSH from your phone: opens a port on the mesh/VPN interface from inside the running server process, so a phone browser gets the same instance and the same session list — no SSH, no second dsh. Also reachable from another PC, a GUI NAS, or a TV box.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|
|
7
7
|
"exports": {
|