5.8 KiB
description, kind
| description | kind |
|---|---|
| 面向用户与维护者的浏览器-宿主线层说明:共享 API 客户端、带重连的事件流投递、/api HTTP 桥与浏览器信任栅栏,用于组合或排查连接。 | package-reference |
@deepseek-ai/dsh-client-connection
English | 中文
概述
协议与连接世代层:Client 插件挂载 ctx.connection,包含共享 API 客户端、当前页面的 loopback 状态、按 generation 生效的可观察 hostDescription、通用 RPC carrier,以及单一 generation source 与连接循环的注册面。每个 generation 只在 source 已就绪且 host.describe 成功后发布 hostDescription 并调用 onConnected;source 结束、失败、被撤回或显式 stop 都会清空该值,再由 ConnectionController 退避重连。
目录
使用本包
浏览器通过 HTTP POST 执行 API Proxy 一元调用与通用 Remote 一元调用;API Gateway 自己拥有 /api/remote.mux WebSocket 及其逻辑流。进程内组合通过 connection.rpc.open 提供等价的 Remote 流,不打开 WebSocket。Host half 拥有唯一 /api route、Fetch bridge、浏览器认证与 Host/Origin 校验;Typert Gateway 先认领自己的 Remote endpoint,未认领的请求再回退 API Proxy。Loopback hostname 判定只供浏览器侧当前页面状态使用,留在包内。
浏览器认证与请求信任
每个 Host RPC 方法和 WebSocket stream 都要求同一个浏览器会话,不存在按方法区分的 loopback 层。每个进程生成一个随机启动令牌。dsh-web-app 打印并打开带 ?token=... 的普通根 URL;frontend-static 把根路径和 index 请求交给 ctx.connection.authorizeIndex,后者只在 GET / 接受该令牌,写入绑定 authority 的签名 cookie,再重定向到干净的 /。缺失、过期、畸形或 authority 不匹配的 cookie 会在 RPC 分发前得到 401。静态资源保持公开。HTTP 载体不在根路径交换之外接受 query token,也不接受 Authorization header token。
cookie 签名密钥是 ctx.credentials 中由 client-connection/browser-session 拥有的 grant 记录。本地提供方把它持久化到 $DSH_HOME/.credentials.yaml;BrowserAuth 在 Connection 激活期间加载或创建该记录,并把密钥留在内存中,因此请求认证同步执行。删除或替换该记录会在下一次 Connection 激活时生效。cookie 携带绝对签发与过期区间,cookieMaxAgeDays 默认设为 30 天,并在确定性名称与签名 payload 中同时绑定规范化 hostname 和 port。它是 host-only、Path=/、HttpOnly、SameSite=Strict;随附服务器使用 loopback HTTP,因此刻意不设置 Secure。
认证之前,每个请求仍经过 src/api-request-trust.ts。其 Host 必须是 loopback,或与 trustedHosts 条目匹配:带端口的 host:port 精确匹配,不带端口的条目匹配任意端口,两侧均经 WHATWG 归一化。若附带 Origin,它必须等于该 Host;sec-fetch-site: cross-site 一律拒绝。畸形配置 authority 会让插件加载失败。这些检查防御 DNS rebinding 与跨站浏览器请求,绝不建立身份。Host/Origin 校验失败返回 403;Host 可信但未认证的请求返回 401。dsh web --host 0.0.0.0 仍不受支持。决策记录:浏览器请求信任与浏览器令牌认证。
Connection generation
API Gateway Client 把内部 $events logical stream 注册为唯一 generation source,与有无 $on 订阅无关。Host 在 API Remotes source factory 同步挂好所有增量 listener 后,先发送唯一 { type: 'ready' } 项,再发送事件。ConnectionController 并行等待该 ready 与 host.describe;只有两者都成功才允许 onConnected 启动 baseline 读取,因此 baseline 不会跑在增量 listener 前面。
$events 结束、返回 Remote stream error、收到非 ready 首项或畸形事件项,都会使当前 generation 失效。Controller 立即撤回 hostDescription、发布 reconnecting,并在退避后重建 $events 与 host.describe 握手。Gateway mux 自己负责重建底层 WebSocket;Connection 世代负责重建 logical stream 与 baseline 起点。
模型体验
无。协议消费层只在浏览器与主机之间搬运已经组合好的消息;这里没有任何内容进入模型请求。
KV Cache 影响
无;该包既不组装也不发送提供方请求。
已知限制与暂缓事项
/api桥把每个请求体整体缓冲在内存里:maxRequestBodyBytes(默认 300 MiB,按默认 200 MiB 图片总量上限经 base64 膨胀加信封余量得出)因此同时是单请求的驻留内存上界;要降低它而不缩小图片限额,需要流式请求体路径。- 浏览器 cookie 不带
Secure:随附载体是 loopback HTTP;若部署经明文网络暴露同一 authority,bearer cookie 可能在传输中泄露。 - 没有 logout 操作:清除浏览器 cookie 会结束单个浏览器会话;删除 owner 凭据记录并重启
dsh会撤销全部会话。
开发备注
维护者工作上下文——点击展开
无。