Skip to content

feat(drivers): 下载链接随附 UA / Referer,并让 123 默认走直链 - #120

Closed
wumingzhinu wants to merge 1 commit into
OpenListTeam:mainfrom
wumingzhinu:fix/download-link-headers
Closed

wumingzhinu wants to merge 1 commit into
OpenListTeam:mainfrom
wumingzhinu:fix/download-link-headers

Conversation

@wumingzhinu

@wumingzhinu wumingzhinu commented Oct 10, 2026 •

Copy link
Copy Markdown
Contributor

这是什么

行为移植 + 链路打通,不是故障修复。

我没有证据表明这些网盘的下载原先失败过 —— 没有这四个网盘的真实凭据,
也未实机比对过改动前后的结果。

本 PR 做三件事:把 YunX 的做法搬过来、
调整默认代理策略让客户端能自己多线程、以及打通一条原本不存在的取链路径。

如果你确实遇到下载失败,请另开 issue 贴上报错,单独排查。


为什么不能只靠服务端代理

原先是「Worker 替客户端搬字节」的形态。在 Cloudflare Workers 上这条路有固定代价:

  1. 客户端只能单线程下 —— Worker 是唯一出口,多线程分片无从谈起;
  2. Worker 吃满 CPU / 子请求预算;
  3. 受平台响应体上限约束,超限还得降级回 302。

参考 YunX:同一批直链在客户端可开 32~512 线程(迅雷锁 8)。
要吃到这个能力,就必须把直链连带 UA/Referer 交给客户端。


改动一:四个驱动的取链函数返回请求头

Promise<string> → Promise<{ url, headers }>,驱动赋给 raw_url_headers。

驱动 新增头 依据
115 User-Agent 同族 115open 同一约定(UA 绑进取链请求,注释:「115 防盗链校验通过率高」)
quark_uc_tv Referer + User-Agent 同族 quark 已返回 {url, headers}
123pan Referer + User-Agent YunX Pan123Api 对 CDN 直链注明需 Referer: https://yun.123pan.cn/
123_open Referer + User-Agent 同上,同一 CDN 体系

改动二:123pan / 123open 移出 DRIVER_PREFER_PROXY

这张表决定新建存储时 web_proxy 的默认值:命中即默认勾选,也就是默认由
Worker 代理字节 —— 客户端拿不到直链,多线程无从发生。

移出后默认改为 302 直链。依据是仓库自己的判定:
server/proxy_request.ts 的 PRIVATE_HEADER_NAMES 只有 authorization /
cookie,其注释明确写着 UA / Referer / Origin「浏览器可以自己提供」,
不构成必须服务端代理的理由。

只影响新建存储的默认值:已有存储有显式持久化的 web_proxy 字段,
effectiveWebProxy 优先读显式值,行为不变;管理员随时可以再勾回来。


改动三:/api/fs/link 接通 link() 并返回 headers

排查时发现 link() 是死代码:10 个驱动实现了它
(115_share、123_share、139、189pc、aliyundrive_share、dropbox、
mega、onedrive_sharelink、pikpak_share、wps),但下载链路里没有任何
地方调用。而 fs.ts 的 /link 端点只返回 {url},既不调 link() 也不回
headers。

后果:多线程下载器没有任何途径拿到驱动指定的精确头 —— 302 只能交给浏览器
自带的 UA/Referer,取不到驱动指定的值。这是「无法让客户端多线程」的根因之一。

改造 /api/fs/link:

  • 优先调用驱动 link(),成功则直接返回 {url, headers};
  • link() 不可用或失败时回退 driver.get() 的 raw_url + raw_url_headers;
  • linkOk 时跳过 driver.get(),省一次上游往返;
  • headers 为空时不出现该字段,保持向后兼容。

安全性:link() 返回的头可能含 Cookie / Authorization。该端点本就是
admin-only(上方 isAdmin 判定),受众正是「正在配置下载管理器的管理员」,
原样返回是恰当的。已加 fs_link.test.ts 守住权限门,防止回归成任意用户可取。


为什么 baidu_netdisk 没一起改

三条 download_api 路径都只带 UA,其中 official 要求恰为 pan.baidu.com。
百度是否校验 UA 具体值未知,若校验则 302 后新用户直接下载失败,
风险与 123(YunX 只强制 Referer)不对等。宜单独 PR,并需先确认。


已确认无需改动

115、115_share、115open、123_share、quark、quark_uc_tv、
baidu_photo、thunder、139、lanzou、uc 均不在两张代理表内,默认即 302。

quark_open 带的头是 Cookie(私有头),DRIVER_FORCE_PROXY 对它是
正确配置,客户端多线程对其结构性不可行,故不动。


影响面

  • getDownloadUrl / getDownloadLink 返回类型由字符串变为对象(签名变更),
    四个驱动内全部调用点已同步;这四个 util 没有被其它驱动引用。
  • internal/driver/proxy.ts 两张表的成员变化,proxy.test.ts 已同步。
  • fs.ts 的 /link 响应新增可选 headers 字段,缺省时不出现。

未验证

无真实凭据,未实机比对结果。不保证修复任何你遇到的问题。

@wumingzhinu
wumingzhinu force-pushed the fix/download-link-headers branch from 5909544 to 57fe1ce Compare October 10, 2026 15:15
@wumingzhinu wumingzhinu changed the title fix(drivers): 下载链接随附 UA / Referer,修复部分网盘下载失败 feat(drivers): 下载链接随附 UA / Referer(移植自 YunX,对齐同族驱动) Oct 10, 2026
@wumingzhinu
wumingzhinu force-pushed the fix/download-link-headers branch from 57fe1ce to cf411de Compare October 10, 2026 23:29
@wumingzhinu wumingzhinu changed the title feat(drivers): 下载链接随附 UA / Referer(移植自 YunX,对齐同族驱动) feat(drivers): 下载链接随附 UA / Referer,并让 123 默认走直链 Oct 10, 2026
## 动机

原先是「服务端替客户端搬字节」的形态:Worker 用 `raw_url_headers` 取回 CDN
内容再转发。在 Cloudflare Workers 上这条路有三个固定代价:

1. **客户端只能单线程下** —— Worker 是唯一出口,多线程分片无从谈起;
2. Worker 吃满 CPU / 子请求预算(代码里可见 SUBREQUEST_LIMIT 之类常量);
3. 受平台响应体上限约束,超限还得降级回 302。

参考 YunX:同一批直链在客户端可开 32~512 线程(迅雷锁 8)。
要吃到这个能力,就必须把直链连带 UA/Referer 交给客户端。

## 改动一:四个驱动的取链函数返回请求头

`Promise<string>` → `Promise<{ url, headers }>`,驱动赋给 `raw_url_headers`。

| 驱动 | 新增头 | 依据 |
| --- | --- | --- |
| 115 | User-Agent | 同族 115open 同一约定(UA 绑进取链请求) |
| quark_uc_tv | Referer + UA | 同族 quark 已返回 {url, headers} |
| 123pan | Referer + UA | YunX Pan123Api 注明 CDN 直链需 Referer |
| 123_open | Referer + UA | 同上,同一 CDN 体系 |

## 改动二:`123pan` / `123open` 移出 `DRIVER_PREFER_PROXY`

这张表决定**新建存储时 `web_proxy` 的默认值**:命中即默认勾选,即默认由
Worker 代理字节 —— 客户端拿不到直链,多线程无从发生。

移出后默认改为 302 直链。依据是仓库自己的判定:
`server/proxy_request.ts` 的 `PRIVATE_HEADER_NAMES` 只有 authorization /
cookie,其注释明确写着 UA / Referer / Origin「浏览器可以自己提供」,
**不构成必须服务端代理的理由**。

**只影响新建存储的默认值**:已有存储有显式持久化的 `web_proxy`,
`effectiveWebProxy` 优先读显式值,行为不变,管理员可随时勾回。

## 改动三:`/api/fs/link` 接通 `link()` 并返回 headers

排查时发现 **`link()` 是死代码**:10 个驱动实现了它
(115_share、123_share、139、189pc、aliyundrive_share、dropbox、mega、
onedrive_sharelink、pikpak_share、wps),但下载链路里没有任何地方调用。
而 `fs.ts` 的 `/link` 端点只返回 `{url}`,既不调 `link()` 也不回 headers。

后果:多线程下载器**没有任何途径**拿到驱动指定的精确头 —— 302 只能交给
浏览器自带的 UA/Referer,取不到驱动指定的值。这正是「无法让客户端多线程」的
根因之一。

改造 `/api/fs/link`:
- 优先调用驱动 `link()`,成功则直接返回 `{url, headers}`;
- `link()` 不可用或失败时回退 `driver.get()` 的 `raw_url` + `raw_url_headers`;
- `linkOk` 时**跳过** `driver.get()`,省一次上游往返(仓库在意子请求预算)。

安全性:`link()` 返回的头可能含 Cookie / Authorization。该端点本就是
admin-only(上方有 `isAdmin` 判定),受众正是「正在配置下载管理器的管理员」,
原样返回是恰当的。已加测试守住权限门,防止回归成任意用户可取。

## 为什么 `baidu_netdisk` 没一起改

三条 `download_api` 路径都只带 UA(`official` 要求恰为 `pan.baidu.com`)。
百度是否校验 UA 具体值未知,若校验则 302 后新用户直接下载失败,
风险与 123(YunX 只强制 Referer)不对等。宜单独 PR,并需先确认。

## 已确认无需改动

`115`、`115_share`、`115open`、`123_share`、`quark`、`quark_uc_tv`、
`baidu_photo`、`thunder`、`139`、`lanzou`、`uc` 均不在两张代理表内,
默认即 302。

`quark_open` 带的头是 `Cookie`(私有头),`DRIVER_FORCE_PROXY` 对它是
**正确配置**,客户端多线程对其结构性不可行,故不动。

## 未验证

无真实凭据,未实机比对 302 前后结果。**不保证修复任何具体故障。**

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@wumingzhinu
wumingzhinu force-pushed the fix/download-link-headers branch from cf411de to 4ed1b4b Compare October 10, 2026 23:54

@pikachuren pikachuren left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🙏 感谢贡献本 PR!以下是本次代码审查结果。


总体结论:✅ Approve ⭐⭐⭐⭐

当前 head:4ed1b4b480db40e1858e9b9211e9a8cc074e4137

三件事全部做到位:取链返回 UA/Referer、/api/fs/link 打通 headers 透传、123pan/123open 移出默认代理表。作者在 PR 描述和注释中明确说明了「行为移植自 YunX,未实机验证」,透明度很好。


逐模块核查

✅ 115 / 123pan / 123open / quark_uc_tv — 返回 {url, headers} 重构

  • 115:getDownloadUrl 追加 { "User-Agent": UA } 合理——115 的 downurl 接口本身就是按请求方 UA 签发的,与 115open/115_share 对齐。
  • 123pan/123open:pan123DownloadHeaders() 返回 Referer: https://yun.123pan.cn/ + UA。Referer 一致(123pan 内部跟随 302 时已用同域 Referer),本次只是让最终直链也带上该头。
  • quark_uc_tv:与同族 quark/util.ts 的 getDownloadUrl 对齐,quarkTvDownloadHeaders() 内联在文件底部,清晰。
  • 123pan getDownloadLink 的 fallback 逻辑:将 return downloadUrl 改为 finalUrl = downloadUrl,逻辑等价,无行为差异。

✅ proxy.ts — 将 123pan/123open 移出 DRIVER_PREFER_PROXY

注释解释了原因:直链只需 Referer + UA,浏览器/下载器可自供,服务端代理反而占用子请求预算并限制多线程分片。逻辑正确。

对现有用户的影响:DRIVER_PREFER_PROXY 只影响新建存储的默认值(web_proxy 字段),已存在的存储配置不会被修改,向后兼容。

✅ server/fs.ts — /api/fs/link 新增 link() 优先路径

  • admin-only 门控保持:if (!isAdmin(user)) return permissionDenied(c) 在 PR 变动前后均在(line 1284),正确——headers 中可能含 Cookie/Authorization,非管理员不得取得。
  • link() 可选扩展:用 (driver as any).link duck-typing 检查,失败时回退 driver.get() + raw_url_headers,再回退代理地址,三层降级合理。
  • raw_url_headers 字段:已在 internal/driver/base.ts:12 定义(raw_url_headers?: Record<string, string>),本 PR 只是补全了驱动侧的赋值,无类型破坏。

✅ fs_link.test.ts — 权限门回归测试

新增两个测试:

  • guest 调 /api/fs/link → 403(直链可能带私有头)
  • admin 不被门拦下,响应体含 url 字段,headers 缺省时不凭空出现

覆盖最关键的权限边界,方向正确。


P2 建议(非阻塞,供后续参考)

  1. pan123DownloadHeaders() 在 123_open/util.ts 与 123pan/util.ts 中完全重复(常量值相同,函数实现相同)。可以考虑提取到 src/backend/drivers/123_common/headers.ts 复用,消除两处同步维护的风险。当前不影响正确性,不要求本 PR 改动。

  2. User-Agent 是 Fetch API 的禁止请求头(Forbidden request header):若浏览器端 JS 直接使用 /api/fs/link 返回的 headers 去 fetch(url, { headers }),UA 会被静默忽略。但 /api/fs/link 是 admin-only 端点,主要受众是配置下载管理器(aria2/NDM/IDM 等)的管理员,这些工具可以设置任意头,影响范围有限。建议在 API 文档(或端点注释)补一句:「headers 中的 User-Agent 仅对支持自定义请求头的下载工具有效,浏览器 fetch 会忽略它」。

  3. link() 调用约定(行 1337):linkFn.call(driver, reqPath, resolved.physical ?? "/") 是未来驱动实现 link() 时需遵循的签名。目前没有任何驱动实现它,建议在 StorageDriver 接口中加一条注释说明预期签名 link?(reqPath: string, physicalPath: string): Promise<{url: string; headers?: Record<string, string>}>,避免后续实现者各自理解不一致。


依赖与供应链

无新依赖引入,无版本变更,无供应链风险。


🤖 AI 自动审核声明

本评论由 AI 辅助的自动化评审生成,已经过人工主导的逐条复核。
重要提醒:本评论基于静态代码分析和本地测试,未在真实云盘环境中验证实际下载行为(与作者 PR 描述一致)。建议维护者在合并前对四个驱动的直链下载做一次实机验证。如有任何发现与本评论不符,请以维护者判断为准。

@PIKACHUIM

PIKACHUIM commented Oct 11, 2026 •

Copy link
Copy Markdown
Member

您好,感谢您的贡献,
123驱动现在是有什么问题吗?完全没看懂这个PR的目的

@PIKACHUIM PIKACHUIM closed this Oct 11, 2026
@wumingzhinu

Copy link
Copy Markdown
Contributor Author

您好,感谢您的贡献, 123驱动现在是有什么问题吗?完全没看懂这个PR的目的

羡慕

您好,感谢您的贡献, 123驱动现在是有什么问题吗?完全没看懂这个PR的目的

只是羡慕https://github.com/CYQawa/YunX的下载速度,只是尝试移植,使用多线程下载

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants