Skip to content
dsh.fish
Bundle

dsh-web-fetch-proxy

Proxy-egress WebFetchProvider for ctx.web: routes web_fetch through one explicit HTTP(S) proxy (undici ProxyAgent) instead of local DNS pinning, for fake-ip/TUN DNS environments. No core patches.

Source
shaomingbo
License
MIT
Updated
Updated 8 hours ago

Readme

# dsh-web-fetch-proxy

为 DSH `ctx.web` 增加一个**代理出网**的 `web_fetch` provider(id `http-proxy`):
所有请求经一个显式配置的 HTTP(S) 代理(undici `ProxyAgent`)发出,由代理负责
域名解析与出网。用于本机代理采用 **fake-ip/TUN DNS** 的环境——内置本地 provider
在连接前校验「公网单播 IP」,而 fake-ip 会把所有域名解析为 `198.18.0.0/15`
保留段,导致任意网页都报 `resolves to a non-public IP address`。本插件不改
DSH 核心,纯注册表扩展。

## 安装

```bash
npx --yes github:shaomingbo/dsh-web-fetch-proxy#v0.1.2
```

无参数等同 `install`,默认 profile 为 `web`;另提供幂等的 `install`、只读
`status`、`uninstall` 与 `--profile <name>`、`--source link:<本地路径>`、`--help`。
安装器要求 PATH 中存在 **`dsh` 0.1.2-alpha.3 或 0.1.5-rc.1**(仅接受这两个
精确版本,`dsh --version` 逐字核验,不兼容即失败并给出定位办法)与 pnpm,
所有依赖操作经官方 `dsh plugin --profile <name> add ... --ignore-scripts` 完成,
不手改 manifest、不回退;安装器不管理 DSH 进程生命周期——Bundle 集合变化后
手动重启对应 profile,Web 端强刷新现有 GUI。安装器兼容范围:上列两个精确 CLI
版本,各自经一次性 DSH_HOME 中的真实 launcher 走完官方 absent→install→
reinstall→status→uninstall→repeated-uninstall 闭环(见
`test/installer.test.mjs`);其他宿主版本未知,安装器会拒绝。

本地开发可用 `--source link:<checkout>`;`link:` 验收不能替代正式 tag 的
安装闭环。换装边界:本插件无 HMR 承诺,候选变更需重启并强刷新。

发布固定 tag 之前,可先用 lab 候选 tgz 经官方 CLI 安装(见 CHANGELOG)。

## 配置与接线(仅 profile patch 层,零核心改动)

```yaml
# 1) 插件条目(其 cordis.patch.yml 已 insert;这里补 config)
- id: web-fetch-proxy
  config:
    proxyUrl: http://127.0.0.1:7890
    # 可选,与内置 provider 同默认值:
    # maxResponseBytes: 5000000
    # maxBodyChars: 100000
    # timeoutMs: 30000
    # maxRedirects: 5
    # userAgent: deepseek-harness/0.0.1 (+https://github.com/deepseek-ai)

# 2) 把 web seam 的 fetch provider 指到本插件
#    注意:entry patch 的 config 是整项替换,必须保留原有字段。
- id: web
  config:
    searchProvider: deepseek-official
    fetchProvider: http-proxy
```

`proxyUrl` 必填且在加载时校验(仅 http/https、不得内嵌凭据),配置缺失或非法
**fail loud**;不做隐藏 env 兜底。回退:删除上面两段 patch 即恢复内置 provider。

## 安全语义(与内置 provider 的差异,需明读)

- **出网与 SSRF 边界**:内置 provider 解析域名并要求全部地址为公网单播,再把
  连接钉死到已验证地址;本 provider **不做本地 DNS 校验**,解析完全交给所配置
  的可信代理。代理即信任边界:给什么代理地址,就信任该代理的解析与路由。
- **匿名性保留**:不带 cookie、不带环境凭据、URL 不得内嵌凭据(与内置一致);
  `User-Agent` 为显式产品标识,不伪装浏览器。
- **重定向**:仅跟随同源重定向(与内置一致,预算内);跨源重定向拒绝并提示直接
  请求目标 URL。
- **限额**:与内置 provider 相同的默认值——5 MiB 字节上限(超限截断,
  `Content-Length` 超限直接拒绝)、100k 字符截断、30s 超时、5 跳重定向。

## 错误码

普通 `ProxyFetchError`(带 `code`),词表与 `ctx.web` seam 一致:
`WEB_INVALID_URL`、`WEB_BLOCKED_URL`、`WEB_REDIRECT_BLOCKED`、
`WEB_UNSUPPORTED_CONTENT_TYPE`、`WEB_FETCH_TOO_LARGE`、`WEB_FETCH_TIMEOUT`、
`WEB_ABORTED`、`WEB_PROVIDER_ERROR`。工具端以 `isError` 结果呈现,不中断会话。

## 验证矩阵(本候选,lab 实测)

- 单测:`node --test test/`(本地 fixture:URL 校验、限额、content-type、
  charset、同源/跨源重定向、hop 上限、超时、插件注册与 agent 释放)。
- 真实出网:`develop dsh-web-fetch-proxy smoke:proxy` — 经
  `127.0.0.1:7890` 抓取 `registry.npmjs.org` 与 `example.com`,并验证死代理
  fail-closed。
- 组合与启动:lab `install test` → `dump test`(组合含 `fetchProvider:
  http-proxy`)→ `serve test` 真实加载。
- 0.1.5-rc.1 适配:工具入口 pipeline 测试直接只读加载隔离 0.1.5-rc.1 前缀的
  公开包——真实 `ToolRuntime`/`WebRuntime`、发布版 `web_fetch`、默认
  `http` provider 与本插件并存,错选/漏配 `fetchProvider` 走默认 provider 的
  真实网络边界(loopback 拒绝)与 seam 的歧义拒绝;安装器对 0.1.5-rc.1
  launcher 跑同样的官方 CLI 闭环。

## 已知限制

- 代理本身必须可信:代理可观察并篡改全部请求与响应,本插件不做端到端校验。
- `dump-config`/启动 smoke 与 GUI 验证过的宿主组合:CLI `0.1.2-alpha.3`,
  Web/Base `0.1.2-rc.1`,Node 24.18.0。0.1.5-rc.1 上未做 dump-config/启动
  smoke/GUI 验收,已验证范围限于安装器官方 CLI 闭环与工具入口 pipeline 测试;
  其他宿主版本未验证,未知。
- 未承诺 HMR;更换候选后需重启对应 profile 并强刷新 GUI。

Install

dsh plugin --profile web add github:shaomingbo/dsh-web-fetch-proxy

Profile: web

  • This source has no pinned commit, so a later push upstream changes what installs. Prefer pinning a commit.
Source