dsh-bridge-gateway 0.1.1 → 0.1.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 +13 -0
- package/client/client.js +45 -10
- package/client/index.js +45 -10
- package/lib/index.js +96 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,19 @@
|
|
|
2
2
|
|
|
3
3
|
本项目 `dsh-bridge-gateway` 是基于 [dsh-bridge](https://github.com/wenbin-wb/dsh-bridge) 的移植增强分支,在保留原版能力之外,重点新增「公网直连网关」。
|
|
4
4
|
|
|
5
|
+
## [0.1.3] - 待发布
|
|
6
|
+
|
|
7
|
+
### 修复
|
|
8
|
+
- 修复移动端对话时底部输入框横向超出屏幕右缘的问题:约束输入卡片与编辑器最大宽度不超视口,长内容自动折行。
|
|
9
|
+
|
|
10
|
+
## [0.1.2] - 待发布
|
|
11
|
+
|
|
12
|
+
### 新增
|
|
13
|
+
- 公网直连网关新增插件 host 反向代理:`/points-checkin/*` 路径转发到本机 points-checkin bridge,使积分签到插件在公网 HTTPS 网关页面下同步可用。
|
|
14
|
+
|
|
15
|
+
### 修复
|
|
16
|
+
- 修复移动端模型/权限选择下拉在底部输入栏被挤出视口、仅剩右下角横条的问题:改为固定在输入栏上方的底部浮层。
|
|
17
|
+
|
|
5
18
|
## [0.1.1] - 待发布
|
|
6
19
|
|
|
7
20
|
### 修复
|
package/client/client.js
CHANGED
|
@@ -3902,6 +3902,27 @@ function injectMobileStyles() {
|
|
|
3902
3902
|
background: var(--dsw-alias-bg-layer-2, #f4f4f7) !important;
|
|
3903
3903
|
}
|
|
3904
3904
|
|
|
3905
|
+
/* \u8F93\u5165\u6846\u6A2A\u5411\u4E0D\u6EA2\u51FA\uFF1A\u5361\u7247\u53CA\u5176\u7F29\u5BB9\u5668\u6700\u5927\u5BBD\u5EA6\u4E0D\u8D85\u8FC7\u89C6\u53E3\uFF0C\u5185\u90E8\u7F16\u8F91\u5668\u53EF\u6536\u7F29\u3001\u957F\u5185\u5BB9\u81EA\u52A8\u6298\u884C */
|
|
3906
|
+
div[class*="uV2eYG_scrollBody"] {
|
|
3907
|
+
max-width: 100vw !important;
|
|
3908
|
+
overflow-x: hidden !important;
|
|
3909
|
+
}
|
|
3910
|
+
div[class*="uV2eYG_card"] {
|
|
3911
|
+
width: 100% !important;
|
|
3912
|
+
max-width: 100% !important;
|
|
3913
|
+
min-width: 0 !important;
|
|
3914
|
+
box-sizing: border-box !important;
|
|
3915
|
+
}
|
|
3916
|
+
div[class*="uV2eYG_card"] div,
|
|
3917
|
+
div[class*="uV2eYG_card"] textarea,
|
|
3918
|
+
div[class*="uV2eYG_card"] [contenteditable="true"] {
|
|
3919
|
+
max-width: 100% !important;
|
|
3920
|
+
min-width: 0 !important;
|
|
3921
|
+
overflow-wrap: anywhere !important;
|
|
3922
|
+
word-break: break-word !important;
|
|
3923
|
+
box-sizing: border-box !important;
|
|
3924
|
+
}
|
|
3925
|
+
|
|
3905
3926
|
/* \u8F93\u5165\u6846\u5E95\u90E8\u5DE5\u5177\u680F\uFF1A\u5F39\u6027\u81EA\u9002\u5E94\uFF0C\u5F7B\u5E95\u675C\u7EDD\u6743\u9650\u9009\u62E9\u5668(Full access)\u4E0E\u6A21\u578B\u9009\u62E9\u5668\u91CD\u53E0\u78B0\u649E */
|
|
3906
3927
|
div[class*="uV2eYG_row"] {
|
|
3907
3928
|
display: flex !important;
|
|
@@ -3963,7 +3984,7 @@ function injectMobileStyles() {
|
|
|
3963
3984
|
min-width: 0 !important;
|
|
3964
3985
|
}
|
|
3965
3986
|
|
|
3966
|
-
/* \u79FB\u52A8\u7AEF\uFF1A\u6A21\u578B/\u6743\u9650\u9009\u62E9\u5F39\u5C42\
|
|
3987
|
+
/* \u79FB\u52A8\u7AEF\uFF1A\u6A21\u578B/\u6743\u9650\u9009\u62E9\u5F39\u5C42\u56FA\u5B9A\u4E3A\u8F93\u5165\u680F\u4E0A\u65B9\u7684\u5E95\u90E8\u6D6E\u5C42\uFF0C\u4FDD\u8BC1\u5B8C\u6574\u53EF\u89C1\uFF08\u4FEE\u590D\u771F\u673A\u4E0B\u62C9\u53EA\u5269\u53F3\u4E0B\u89D2\u6A2A\u6761\u3001\u5185\u5BB9\u88AB\u6324\u51FA\u89C6\u53E3\uFF09 */
|
|
3967
3988
|
div[class*="_7KE1Ra_root"] > div[class*="dropdown"],
|
|
3968
3989
|
div[class*="_7KE1Ra_root"] > div[class*="listbox"],
|
|
3969
3990
|
div[class*="_7KE1Ra_root"] > div[class*="popup"],
|
|
@@ -3973,15 +3994,20 @@ function injectMobileStyles() {
|
|
|
3973
3994
|
div[class*="Sh0Q9G_root"] > div[class*="listbox"],
|
|
3974
3995
|
div[class*="Sh0Q9G_root"] > div[class*="popup"],
|
|
3975
3996
|
div[class*="Sh0Q9G_root"] > div[class*="menu"] {
|
|
3997
|
+
position: fixed !important;
|
|
3998
|
+
left: 8px !important;
|
|
3999
|
+
right: 8px !important;
|
|
4000
|
+
top: auto !important;
|
|
4001
|
+
bottom: calc(64px + var(--dsh-mobile-safe-bottom)) !important;
|
|
4002
|
+
width: auto !important;
|
|
3976
4003
|
min-width: 0 !important;
|
|
3977
4004
|
max-width: calc(100vw - 16px) !important;
|
|
3978
|
-
|
|
3979
|
-
max-height: 55vh !important;
|
|
4005
|
+
max-height: 48vh !important;
|
|
3980
4006
|
overflow-x: auto !important;
|
|
3981
4007
|
overflow-y: auto !important;
|
|
3982
|
-
|
|
3983
|
-
|
|
3984
|
-
|
|
4008
|
+
z-index: 10005 !important;
|
|
4009
|
+
transform: none !important;
|
|
4010
|
+
margin: 0 !important;
|
|
3985
4011
|
box-sizing: border-box !important;
|
|
3986
4012
|
-webkit-overflow-scrolling: touch !important;
|
|
3987
4013
|
}
|
|
@@ -4233,7 +4259,7 @@ function injectMobileStyles() {
|
|
|
4233
4259
|
pointer-events: auto !important;
|
|
4234
4260
|
}
|
|
4235
4261
|
|
|
4236
|
-
/* \u515C\u5E95\uFF1APortal \u6E32\u67D3\u5230 overlayAnchor \u91CC\u7684\u6A21\u578B/\u6743\u9650\u9009\u62E9\u5F39\u5C42\u4E5F\
|
|
4262
|
+
/* \u515C\u5E95\uFF1APortal \u6E32\u67D3\u5230 overlayAnchor \u91CC\u7684\u6A21\u578B/\u6743\u9650\u9009\u62E9\u5F39\u5C42\u4E5F\u56FA\u5B9A\u4E3A\u5E95\u90E8\u6D6E\u5C42\uFF0C\u675C\u7EDD\u6574\u4F53\u8DD1\u51FA\u89C6\u53E3\u53EA\u5269\u6A2A\u6761 */
|
|
4237
4263
|
div[class*="uV2eYG_overlayAnchor"] > div[class*="dropdown"],
|
|
4238
4264
|
div[class*="uV2eYG_overlayAnchor"] > div[class*="popup"],
|
|
4239
4265
|
div[class*="uV2eYG_overlayAnchor"] > div[class*="menu"],
|
|
@@ -4241,13 +4267,22 @@ function injectMobileStyles() {
|
|
|
4241
4267
|
div[class*="uV2eYG_overlayAnchor"] > div[role="listbox"],
|
|
4242
4268
|
div[class*="overlayLayer"] > div[class*="dropdown"],
|
|
4243
4269
|
div[class*="overlayLayer"] > div[class*="popup"] {
|
|
4244
|
-
|
|
4270
|
+
position: fixed !important;
|
|
4271
|
+
left: 8px !important;
|
|
4272
|
+
right: 8px !important;
|
|
4273
|
+
top: auto !important;
|
|
4274
|
+
bottom: calc(64px + var(--dsh-mobile-safe-bottom)) !important;
|
|
4275
|
+
width: auto !important;
|
|
4245
4276
|
min-width: 0 !important;
|
|
4246
|
-
max-
|
|
4277
|
+
max-width: calc(100vw - 16px) !important;
|
|
4278
|
+
max-height: 50vh !important;
|
|
4247
4279
|
overflow-x: auto !important;
|
|
4248
4280
|
overflow-y: auto !important;
|
|
4281
|
+
z-index: 10005 !important;
|
|
4282
|
+
transform: none !important;
|
|
4283
|
+
margin: 0 !important;
|
|
4249
4284
|
box-sizing: border-box !important;
|
|
4250
|
-
transform-origin: left
|
|
4285
|
+
transform-origin: left bottom !important;
|
|
4251
4286
|
}
|
|
4252
4287
|
}
|
|
4253
4288
|
|
package/client/index.js
CHANGED
|
@@ -3500,6 +3500,27 @@ function injectMobileStyles() {
|
|
|
3500
3500
|
background: var(--dsw-alias-bg-layer-2, #f4f4f7) !important;
|
|
3501
3501
|
}
|
|
3502
3502
|
|
|
3503
|
+
/* 输入框横向不溢出:卡片及其缩容器最大宽度不超过视口,内部编辑器可收缩、长内容自动折行 */
|
|
3504
|
+
div[class*="uV2eYG_scrollBody"] {
|
|
3505
|
+
max-width: 100vw !important;
|
|
3506
|
+
overflow-x: hidden !important;
|
|
3507
|
+
}
|
|
3508
|
+
div[class*="uV2eYG_card"] {
|
|
3509
|
+
width: 100% !important;
|
|
3510
|
+
max-width: 100% !important;
|
|
3511
|
+
min-width: 0 !important;
|
|
3512
|
+
box-sizing: border-box !important;
|
|
3513
|
+
}
|
|
3514
|
+
div[class*="uV2eYG_card"] div,
|
|
3515
|
+
div[class*="uV2eYG_card"] textarea,
|
|
3516
|
+
div[class*="uV2eYG_card"] [contenteditable="true"] {
|
|
3517
|
+
max-width: 100% !important;
|
|
3518
|
+
min-width: 0 !important;
|
|
3519
|
+
overflow-wrap: anywhere !important;
|
|
3520
|
+
word-break: break-word !important;
|
|
3521
|
+
box-sizing: border-box !important;
|
|
3522
|
+
}
|
|
3523
|
+
|
|
3503
3524
|
/* 输入框底部工具栏:弹性自适应,彻底杜绝权限选择器(Full access)与模型选择器重叠碰撞 */
|
|
3504
3525
|
div[class*="uV2eYG_row"] {
|
|
3505
3526
|
display: flex !important;
|
|
@@ -3561,7 +3582,7 @@ function injectMobileStyles() {
|
|
|
3561
3582
|
min-width: 0 !important;
|
|
3562
3583
|
}
|
|
3563
3584
|
|
|
3564
|
-
/*
|
|
3585
|
+
/* 移动端:模型/权限选择弹层固定为输入栏上方的底部浮层,保证完整可见(修复真机下拉只剩右下角横条、内容被挤出视口) */
|
|
3565
3586
|
div[class*="_7KE1Ra_root"] > div[class*="dropdown"],
|
|
3566
3587
|
div[class*="_7KE1Ra_root"] > div[class*="listbox"],
|
|
3567
3588
|
div[class*="_7KE1Ra_root"] > div[class*="popup"],
|
|
@@ -3571,15 +3592,20 @@ function injectMobileStyles() {
|
|
|
3571
3592
|
div[class*="Sh0Q9G_root"] > div[class*="listbox"],
|
|
3572
3593
|
div[class*="Sh0Q9G_root"] > div[class*="popup"],
|
|
3573
3594
|
div[class*="Sh0Q9G_root"] > div[class*="menu"] {
|
|
3595
|
+
position: fixed !important;
|
|
3596
|
+
left: 8px !important;
|
|
3597
|
+
right: 8px !important;
|
|
3598
|
+
top: auto !important;
|
|
3599
|
+
bottom: calc(64px + var(--dsh-mobile-safe-bottom)) !important;
|
|
3600
|
+
width: auto !important;
|
|
3574
3601
|
min-width: 0 !important;
|
|
3575
3602
|
max-width: calc(100vw - 16px) !important;
|
|
3576
|
-
|
|
3577
|
-
max-height: 55vh !important;
|
|
3603
|
+
max-height: 48vh !important;
|
|
3578
3604
|
overflow-x: auto !important;
|
|
3579
3605
|
overflow-y: auto !important;
|
|
3580
|
-
|
|
3581
|
-
|
|
3582
|
-
|
|
3606
|
+
z-index: 10005 !important;
|
|
3607
|
+
transform: none !important;
|
|
3608
|
+
margin: 0 !important;
|
|
3583
3609
|
box-sizing: border-box !important;
|
|
3584
3610
|
-webkit-overflow-scrolling: touch !important;
|
|
3585
3611
|
}
|
|
@@ -3831,7 +3857,7 @@ function injectMobileStyles() {
|
|
|
3831
3857
|
pointer-events: auto !important;
|
|
3832
3858
|
}
|
|
3833
3859
|
|
|
3834
|
-
/* 兜底:Portal 渲染到 overlayAnchor
|
|
3860
|
+
/* 兜底:Portal 渲染到 overlayAnchor 里的模型/权限选择弹层也固定为底部浮层,杜绝整体跑出视口只剩横条 */
|
|
3835
3861
|
div[class*="uV2eYG_overlayAnchor"] > div[class*="dropdown"],
|
|
3836
3862
|
div[class*="uV2eYG_overlayAnchor"] > div[class*="popup"],
|
|
3837
3863
|
div[class*="uV2eYG_overlayAnchor"] > div[class*="menu"],
|
|
@@ -3839,13 +3865,22 @@ function injectMobileStyles() {
|
|
|
3839
3865
|
div[class*="uV2eYG_overlayAnchor"] > div[role="listbox"],
|
|
3840
3866
|
div[class*="overlayLayer"] > div[class*="dropdown"],
|
|
3841
3867
|
div[class*="overlayLayer"] > div[class*="popup"] {
|
|
3842
|
-
|
|
3868
|
+
position: fixed !important;
|
|
3869
|
+
left: 8px !important;
|
|
3870
|
+
right: 8px !important;
|
|
3871
|
+
top: auto !important;
|
|
3872
|
+
bottom: calc(64px + var(--dsh-mobile-safe-bottom)) !important;
|
|
3873
|
+
width: auto !important;
|
|
3843
3874
|
min-width: 0 !important;
|
|
3844
|
-
max-
|
|
3875
|
+
max-width: calc(100vw - 16px) !important;
|
|
3876
|
+
max-height: 50vh !important;
|
|
3845
3877
|
overflow-x: auto !important;
|
|
3846
3878
|
overflow-y: auto !important;
|
|
3879
|
+
z-index: 10005 !important;
|
|
3880
|
+
transform: none !important;
|
|
3881
|
+
margin: 0 !important;
|
|
3847
3882
|
box-sizing: border-box !important;
|
|
3848
|
-
transform-origin: left
|
|
3883
|
+
transform-origin: left bottom !important;
|
|
3849
3884
|
}
|
|
3850
3885
|
}
|
|
3851
3886
|
|
package/lib/index.js
CHANGED
|
@@ -223,6 +223,9 @@ function getDshLoopbackCookie(targetPort) {
|
|
|
223
223
|
}
|
|
224
224
|
}
|
|
225
225
|
|
|
226
|
+
/** points-checkin 本机 host bridge 的候选端口(与其 client 端探测顺序一致) */
|
|
227
|
+
const POINTS_CHECKIN_PORTS = [27182, 27183, 27184, 27185, 27186, 27187, 27188, 27189, 27190, 27191];
|
|
228
|
+
|
|
226
229
|
/** 把请求头中的 Host 和 Origin 改写成 loopback,让 DSH 的安全栅栏放行 */
|
|
227
230
|
function loopbackHeaders(headers, targetPort) {
|
|
228
231
|
const authority = `127.0.0.1:${targetPort}`;
|
|
@@ -260,14 +263,16 @@ class ProxyServer {
|
|
|
260
263
|
* @param {object} [opts.logger]
|
|
261
264
|
* @param {{ key: string|Buffer, cert: string|Buffer }} [opts.tls] 若提供则启用 HTTPS(公网直连网关)
|
|
262
265
|
* @param {string} [opts.tag] 日志标签(如 '网关')
|
|
266
|
+
* @param {Array<{prefix:string,targetPort:number,stripPrefix?:boolean}>} [opts.extraTargets] 额外的本机插件 host 反代目标(如 points-checkin 的本地 bridge),鉴权通过后按前缀转发
|
|
263
267
|
*/
|
|
264
|
-
constructor({ localPort, targetPort, authManager, logger, tls, tag = '' }) {
|
|
268
|
+
constructor({ localPort, targetPort, authManager, logger, tls, tag = '', extraTargets = [] }) {
|
|
265
269
|
this.localPort = localPort;
|
|
266
270
|
this.targetPort = targetPort;
|
|
267
271
|
this.authManager = authManager;
|
|
268
272
|
this.logger = logger;
|
|
269
273
|
this.tls = tls ?? null;
|
|
270
274
|
this.tag = tag ? `[${tag}] ` : '';
|
|
275
|
+
this.extraTargets = Array.isArray(extraTargets) ? extraTargets : [];
|
|
271
276
|
this.server = null;
|
|
272
277
|
this.clientSockets = new Set();
|
|
273
278
|
this.activeConnections = 0;
|
|
@@ -417,6 +422,55 @@ class ProxyServer {
|
|
|
417
422
|
}
|
|
418
423
|
}
|
|
419
424
|
|
|
425
|
+
// 4.3 认证通过:可选插件 host 反向代理(如 points-checkin 本地 bridge,供远程 HTTPS 网关的页面同源调用)
|
|
426
|
+
if (this.extraTargets && this.extraTargets.length) {
|
|
427
|
+
const extra = this.extraTargets.find(
|
|
428
|
+
(t) => pathname === t.prefix || pathname.startsWith(`${t.prefix}/`)
|
|
429
|
+
);
|
|
430
|
+
if (extra) {
|
|
431
|
+
const qIndex = (req.url || '').indexOf('?');
|
|
432
|
+
const qs = qIndex >= 0 ? (req.url || '').slice(qIndex) : '';
|
|
433
|
+
const upstreamPath = extra.stripPrefix
|
|
434
|
+
? (pathname.slice(extra.prefix.length) || '/') + qs
|
|
435
|
+
: req.url;
|
|
436
|
+
const headers = loopbackHeaders(req.headers, extra.targetPort);
|
|
437
|
+
const extraReq = httpRequest(
|
|
438
|
+
{
|
|
439
|
+
host: '127.0.0.1',
|
|
440
|
+
port: extra.targetPort,
|
|
441
|
+
method: req.method,
|
|
442
|
+
path: upstreamPath,
|
|
443
|
+
headers,
|
|
444
|
+
agent: false,
|
|
445
|
+
},
|
|
446
|
+
(extraRes) => {
|
|
447
|
+
const out = { ...extraRes.headers };
|
|
448
|
+
delete out['transfer-encoding'];
|
|
449
|
+
delete out['content-length'];
|
|
450
|
+
res.writeHead(extraRes.statusCode ?? 502, out);
|
|
451
|
+
extraRes.pipe(res);
|
|
452
|
+
res.on('close', () => extraRes.destroy());
|
|
453
|
+
extraRes.on('error', () => {
|
|
454
|
+
if (!res.writableEnded) res.destroy();
|
|
455
|
+
});
|
|
456
|
+
}
|
|
457
|
+
);
|
|
458
|
+
extraReq.on('error', (err) => {
|
|
459
|
+
this.logger.error('插件 host 代理请求失败(%s): %s', extra.prefix, err.message);
|
|
460
|
+
if (!res.headersSent) {
|
|
461
|
+
res.writeHead(502, { 'content-type': 'text/plain; charset=utf-8' });
|
|
462
|
+
res.end(
|
|
463
|
+
`dsh-bridge: 无法连接插件 host 服务 (127.0.0.1:${extra.targetPort}) — ${err.message}`
|
|
464
|
+
);
|
|
465
|
+
} else {
|
|
466
|
+
res.destroy();
|
|
467
|
+
}
|
|
468
|
+
});
|
|
469
|
+
req.pipe(extraReq);
|
|
470
|
+
return;
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
|
|
420
474
|
// 5. 认证通过:正常执行反向代理转发
|
|
421
475
|
const headers = loopbackHeaders(req.headers, this.targetPort);
|
|
422
476
|
const proxyReq = httpRequest(
|
|
@@ -577,14 +631,53 @@ class BridgeService {
|
|
|
577
631
|
return this.getStatus();
|
|
578
632
|
}
|
|
579
633
|
|
|
634
|
+
// 探测 points-checkin 本机 host bridge 端口(供网关反代 /points-checkin/*,实现远程 HTTPS 下积分签到可用)
|
|
635
|
+
async _resolvePointsCheckinPort() {
|
|
636
|
+
if (this._pcPortResolved) return this._pcPort ?? null;
|
|
637
|
+
this._pcPortResolved = true;
|
|
638
|
+
this._pcPort = null;
|
|
639
|
+
for (const port of POINTS_CHECKIN_PORTS) {
|
|
640
|
+
const ok = await new Promise((resolve) => {
|
|
641
|
+
const req = httpGet(
|
|
642
|
+
{ host: '127.0.0.1', port, path: '/ping', timeout: 500, headers: { 'User-Agent': 'dsh-bridge-gateway' } },
|
|
643
|
+
(res) => {
|
|
644
|
+
const chunks = [];
|
|
645
|
+
res.on('data', (c) => chunks.push(c));
|
|
646
|
+
res.on('end', () => {
|
|
647
|
+
try {
|
|
648
|
+
const body = JSON.parse(Buffer.concat(chunks).toString());
|
|
649
|
+
resolve(body?.ok === true && body.plugin === 'points-checkin');
|
|
650
|
+
} catch {
|
|
651
|
+
resolve(false);
|
|
652
|
+
}
|
|
653
|
+
});
|
|
654
|
+
}
|
|
655
|
+
);
|
|
656
|
+
req.on('error', () => resolve(false));
|
|
657
|
+
req.on('timeout', () => {
|
|
658
|
+
req.destroy();
|
|
659
|
+
resolve(false);
|
|
660
|
+
});
|
|
661
|
+
});
|
|
662
|
+
if (ok) {
|
|
663
|
+
this._pcPort = port;
|
|
664
|
+
this.logger?.info?.('已发现 points-checkin host bridge: 127.0.0.1:%d', port);
|
|
665
|
+
break;
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
return this._pcPort ?? null;
|
|
669
|
+
}
|
|
670
|
+
|
|
580
671
|
async startProxy() {
|
|
581
672
|
if (this.proxy) return this.proxy;
|
|
582
673
|
|
|
674
|
+
const pcPort = await this._resolvePointsCheckinPort();
|
|
583
675
|
this.proxy = new ProxyServer({
|
|
584
676
|
localPort: this.proxyPort,
|
|
585
677
|
targetPort: this.dshPort,
|
|
586
678
|
authManager: this.authManager,
|
|
587
679
|
logger: this.logger,
|
|
680
|
+
extraTargets: pcPort ? [{ prefix: '/points-checkin', targetPort: pcPort, stripPrefix: true }] : [],
|
|
588
681
|
});
|
|
589
682
|
|
|
590
683
|
await this.proxy.start();
|
|
@@ -886,6 +979,7 @@ class BridgeService {
|
|
|
886
979
|
}
|
|
887
980
|
|
|
888
981
|
const gatewayAuth = this._refreshGatewayAuth();
|
|
982
|
+
const pcPort = await this._resolvePointsCheckinPort();
|
|
889
983
|
this.gateway = new ProxyServer({
|
|
890
984
|
localPort: port,
|
|
891
985
|
targetPort: this.dshPort,
|
|
@@ -893,6 +987,7 @@ class BridgeService {
|
|
|
893
987
|
logger: this.logger,
|
|
894
988
|
tls: { key: tls.key, cert: tls.cert },
|
|
895
989
|
tag: '公网直连',
|
|
990
|
+
extraTargets: pcPort ? [{ prefix: '/points-checkin', targetPort: pcPort, stripPrefix: true }] : [],
|
|
896
991
|
});
|
|
897
992
|
|
|
898
993
|
await this.gateway.start();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-bridge-gateway",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "以 dsh-bridge 为根基、融合 remote-gateway 能力的 DSH 远程访问网关:局域网 / Cloudflare 隧道 / 自建隧道之外,新增「公网直连网关」(0.0.0.0 监听 + 自带 HTTPS 自签证书 + 强制登录门禁),解决移动端外网直连操控电脑。",
|
|
5
5
|
"releaseNotes": "【dsh-bridge-gateway】以 dsh-bridge 为根基、融合 remote-gateway 能力的 DSH 远程访问网关\n• ➕ 公网访问区:隧道 / 直连网关 二选一,网关全部配置项可在界面配置\n• ➕ 直连网关:0.0.0.0:<端口> 自带 HTTPS(自签证书) + 强制 public_only 门禁,复用 AuthManager,链路打通到 DSH loopback\n• 📱 修复移动端选择模型时界面溢出屏幕的问题\n• 默认不启用,安装后原有局域网/隧道/IM 行为完全不变",
|
|
6
6
|
"type": "module",
|