dsh-code-server-app 0.2.0 → 0.2.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.en.md +7 -2
- package/README.md +6 -2
- package/lib/launcher.mjs +56 -0
- package/package.json +1 -1
- package/vendor/VENDOR.json +1 -1
package/README.en.md
CHANGED
|
@@ -40,6 +40,11 @@ A static profile plugin (npm package with host + client bundle) that ships the *
|
|
|
40
40
|
**WebSockets** cannot be routed because `registerUpgrade` matches exact paths while `/proxy/:port` carries the port in
|
|
41
41
|
the path (HTTP forwarding works; use `loopback` when you need WS forwarding).
|
|
42
42
|
|
|
43
|
+
- In `loopback` mode every upgrade passes a **code-server-equivalent Origin check** (since 0.2.1): when an `Origin`
|
|
44
|
+
header is present its host must equal `Host` (honouring `Forwarded: host=` / `X-Forwarded-Host`, like code-server),
|
|
45
|
+
otherwise the handshake gets `403`; non-browser requests without `Origin` are allowed. Without that check any local
|
|
46
|
+
browser page could complete a handshake against `ws://127.0.0.1:<port>/stable-<commit>` and drive the IDE.
|
|
47
|
+
|
|
43
48
|
|
|
44
49
|
- **Floating ball** (bottom-right, official code-server icon, above the composer): click to **expand the floating window and light it up** (blue glow), click again to **collapse**; **drag to any position** (remembered across refreshes; no accidental click after drag);
|
|
45
50
|
no sidebar button, no window control button group (the ball is the only entry/toggle); the ball carries a status dot (green = running / amber = starting / red = error);
|
|
@@ -121,9 +126,9 @@ pnpm run promote -- <version>
|
|
|
121
126
|
|
|
122
127
|
```powershell
|
|
123
128
|
# no postinstall in the package → no pnpm approve-builds / allowBuilds; one command installs everything
|
|
124
|
-
dsh plugin --profile web add dsh-code-server-app@0.2.
|
|
129
|
+
dsh plugin --profile web add dsh-code-server-app@0.2.1
|
|
125
130
|
# a local tarball works the same way:
|
|
126
|
-
dsh plugin --profile web add C:\Users\User\Desktop\dsh-code-server-app\dsh-code-server-app-0.2.
|
|
131
|
+
dsh plugin --profile web add C:\Users\User\Desktop\dsh-code-server-app\dsh-code-server-app-0.2.1.tgz
|
|
127
132
|
```
|
|
128
133
|
|
|
129
134
|
Ready to use immediately — **no second step, no "Install environment", no install-guide modal**.
|
package/README.md
CHANGED
|
@@ -53,6 +53,10 @@
|
|
|
53
53
|
2. 转发端口(Ports 面板)的 **WebSocket** 无法用精确升级路由覆盖(端口号在路径里)→ 该功能在 `dsh` 模式下不可用;
|
|
54
54
|
HTTP 转发端口正常;需要端口转发 WS 时请用 `loopback` 模式。
|
|
55
55
|
|
|
56
|
+
- `loopback` 模式下 upgrade 会做 **code-server 同款 Origin 校验**(0.2.1 起):带 `Origin` 时其 host 必须等于 `Host`
|
|
57
|
+
(含 `Forwarded: host=` / `X-Forwarded-Host` 的反代语义),否则回 `403`;缺 `Origin` 的非浏览器请求放行。
|
|
58
|
+
没有这道检查时,本机任意浏览器页面都能对 `ws://127.0.0.1:<port>/stable-<commit>` 完成握手并驱动 IDE。
|
|
59
|
+
|
|
56
60
|
## 悬浮球 / 浮窗(仅旧版 DSH 回退路径)
|
|
57
61
|
|
|
58
62
|
- **右下角悬浮球**(code-server 官方图标,输入框上方):点击**展开浮窗并亮起**(蓝色光环),再点击**收起并复原**;
|
|
@@ -136,9 +140,9 @@ pnpm run promote -- <version>
|
|
|
136
140
|
|
|
137
141
|
```powershell
|
|
138
142
|
# 包内无 postinstall → 无需 pnpm approve-builds / allowBuilds;一条命令装完
|
|
139
|
-
dsh plugin --profile web add dsh-code-server-app@0.2.
|
|
143
|
+
dsh plugin --profile web add dsh-code-server-app@0.2.1
|
|
140
144
|
# 本地 tarball 同理:
|
|
141
|
-
dsh plugin --profile web add C:\Users\User\Desktop\dsh-code-server-app\dsh-code-server-app-0.2.
|
|
145
|
+
dsh plugin --profile web add C:\Users\User\Desktop\dsh-code-server-app\dsh-code-server-app-0.2.1.tgz
|
|
142
146
|
```
|
|
143
147
|
|
|
144
148
|
装完即用,**没有第二步、没有「安装环境」、不弹安装指引**。主包约 **110KB**(插件自身代码 + launcher),
|
package/lib/launcher.mjs
CHANGED
|
@@ -207,6 +207,56 @@ function handleProxyUpgrade(req, socket, head, target) {
|
|
|
207
207
|
socket.on('close', () => upstream.destroy());
|
|
208
208
|
}
|
|
209
209
|
|
|
210
|
+
// ---------------------------------------------------------------- 跨源防护(等价 code-server 的 ensureOrigin)
|
|
211
|
+
|
|
212
|
+
/** 取请求 Host:优先 `Forwarded: host=`、其次 `X-Forwarded-Host`(取第一个)、最后 `Host`。
|
|
213
|
+
* trim + 小写,与 code-server 的 getHost() 同语义(反向代理未透传 Host 时返回 undefined)。 */
|
|
214
|
+
function getHostHeader(req) {
|
|
215
|
+
const first = (name) => {
|
|
216
|
+
const value = req.headers[name];
|
|
217
|
+
return Array.isArray(value) ? value[0] : value;
|
|
218
|
+
};
|
|
219
|
+
const forwarded = first('forwarded');
|
|
220
|
+
if (forwarded !== undefined && forwarded !== '') {
|
|
221
|
+
for (const part of forwarded.split(/[;,]/)) {
|
|
222
|
+
const eq = part.indexOf('=');
|
|
223
|
+
if (eq < 0) continue;
|
|
224
|
+
const key = part.slice(0, eq).trim().toLowerCase();
|
|
225
|
+
const value = part.slice(eq + 1).trim();
|
|
226
|
+
if (key === 'host' && value !== '') return value.toLowerCase();
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
const xHost = first('x-forwarded-host');
|
|
230
|
+
if (xHost !== undefined && xHost !== '') {
|
|
231
|
+
const head = xHost.split(',')[0];
|
|
232
|
+
if (head !== undefined && head.trim() !== '') return head.trim().toLowerCase();
|
|
233
|
+
}
|
|
234
|
+
const host = first('host');
|
|
235
|
+
return host !== undefined && host !== '' ? host.trim().toLowerCase() : undefined;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/** code-server `authenticateOrigin()` 的等价物:带 Origin 的请求(浏览器)其 host 必须等于 Host;
|
|
239
|
+
* 缺 Origin(非浏览器,如本地工具/测试)放行。code-server 另外支持 `--trusted-origins` /
|
|
240
|
+
* `--proxy-domain` 通配,本插件没有这两个概念,故不实现。
|
|
241
|
+
* 为什么必须有:VS Code 的 handleUpgrade 不校验来源,而 IDE 是 auth=none —— 缺了这道检查,
|
|
242
|
+
* 本机任意浏览器页面都能开 ws://127.0.0.1:<port>/stable-<commit> 直接驱动 IDE。
|
|
243
|
+
* (dsh 模式下请求来自 DSH 自己的路由并已过 requestRejection,Origin/Host 天然一致。) */
|
|
244
|
+
function originAllowed(req) {
|
|
245
|
+
const raw = req.headers.origin;
|
|
246
|
+
const originRaw = Array.isArray(raw) ? raw[0] : raw;
|
|
247
|
+
if (originRaw === undefined || originRaw === '') return true;
|
|
248
|
+
let origin;
|
|
249
|
+
try {
|
|
250
|
+
origin = new URL(originRaw).host.trim().toLowerCase();
|
|
251
|
+
} catch {
|
|
252
|
+
return false;
|
|
253
|
+
}
|
|
254
|
+
if (origin === '') return false;
|
|
255
|
+
const host = getHostHeader(req);
|
|
256
|
+
if (host === undefined) return false;
|
|
257
|
+
return host === origin;
|
|
258
|
+
}
|
|
259
|
+
|
|
210
260
|
// ---------------------------------------------------------------- HTTP / WS 分发
|
|
211
261
|
|
|
212
262
|
const server = createHttpServer((req, res) => {
|
|
@@ -243,6 +293,12 @@ server.on('upgrade', (req, socket, head) => {
|
|
|
243
293
|
const url = req.url ?? '/';
|
|
244
294
|
recentUpgrades.push(url);
|
|
245
295
|
if (recentUpgrades.length > 10) recentUpgrades.shift();
|
|
296
|
+
// 跨源防护(与 code-server 一致:只卡 upgrade,HTTP 侧 VS Code 仅接受 GET 且状态变更都走 WS)
|
|
297
|
+
if (!originAllowed(req)) {
|
|
298
|
+
log(`拒绝跨源 WebSocket:origin=${req.headers.origin} host=${req.headers.host ?? '-'} url=${url}`);
|
|
299
|
+
socket.end('HTTP/1.1 403 Forbidden\r\nConnection: close\r\nContent-Length: 0\r\n\r\n');
|
|
300
|
+
return;
|
|
301
|
+
}
|
|
246
302
|
if (!args.disableProxy) {
|
|
247
303
|
const target = proxyTarget(url);
|
|
248
304
|
if (target !== null) { handleProxyUpgrade(req, socket, head, target); return; }
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-code-server-app",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "VS Code (from a code-server release) inside DSH Web and Desktop: right-sidebar tab with a floating-ball fallback, driven by the plugin's own launcher over the in-process VS Code server (lib/launcher.mjs). Two serving modes: loopback port (default) or same-origin mount on DSH's own webServer (/code-server, protected by ctx.connection.requestRejection). No code-server Node layer, no argon2, no C++ toolchain.",
|
|
5
5
|
"homepage": "https://github.com/jinsiyu/dsh-code-server-app",
|
|
6
6
|
"repository": {
|
package/vendor/VENDOR.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"vscodeVersion": "1.136.1",
|
|
4
4
|
"productPath": "stable-8d5f383f301ca20681f5b6606b8207d9dc87bdd8",
|
|
5
5
|
"layout": "vscode-only",
|
|
6
|
-
"preparedAt": "2026-09-
|
|
6
|
+
"preparedAt": "2026-09-10T09:02:13.757Z",
|
|
7
7
|
"source": "registry",
|
|
8
8
|
"node": "v24.13.1",
|
|
9
9
|
"platform": "win32",
|