Skip to content

[BUG] 115 Cloud -> PikPak copy fails with 115 CDN 403 no cookie value due to User-Agent/Cookie mismatch #2502

@nianzhibai

Description

@nianzhibai

请确认以下事项

OpenList 版本

v4.2.1

本地复现构建信息:

  • Commit: c3df8da5
  • Docker 部署,数据目录持久化挂载

使用的存储驱动

  • Source: 115 Cloud
  • Destination: PikPak

问题描述

115 Cloud 复制文件到 PikPak 时,复制任务会在 uploading 阶段失败,进度为 0。失败并不是 PikPak API 创建上传任务失败,而是在 PikPak Put 之前计算 GCID/读取源文件流时,请求 115 CDN 下载直链返回 403。

典型任务状态:

state=failed
status=uploading
progress=0

典型错误:

http request [https://cdnfhnfile.115cdn.net/<hash>/<filename>.mp4?t=<ts>&u=<uid>&s=<size>&d=<vip-node>&c=2&f=3&k=<key>&us=<size>&uc=10&v=1] failure,status: 403|Forbidden response:{"status":403,"message":"no cookie value","request_id":"6A12A7B2CA239135369215C9"}

也见到过同形态响应:

{"message":"no cookie value","request_id":"6A12AD0B8E4DDC3430511C7E","status":403}

复现方式

  1. 配置 115 Cloud 存储,Cookie 有效,存储状态为 work
  2. 配置 PikPak 存储,存储状态为 work
  3. 在 OpenList 中将 115 Cloud 文件复制到 PikPak。
  4. 任务进入 uploading,随后失败,错误为 115 CDN 403 no cookie value

已验证的现象

复现环境中 115 Cookie 本身并非为空,也不是完全失效:

  • 115 存储能正常加载,状态为 work
  • 通过 /api/fs/link 获取同一个 115 文件直链时,返回的 Link.Header 中包含 Cookie
  • 使用相同直链和 Cookie 手动请求 115 CDN 时,不同 User-Agent 会导致不同结果:
Cookie + normal browser/OpenList User-Agent => 206 Partial Content,能读到文件数据
Cookie + Mozilla/5.0 115Browser/<version>  => 403 {"message":"no cookie value"}

因此这里的 no cookie value 容易误导:实际触发条件不是简单的“没有 Cookie”,而是后台复制链路里 115 CDN 请求使用的 User-Agent 与 Cookie/直链组合不被 CDN 接受。

根因分析

后台复制任务走的是:

FileTransferTask.RunWithNextTaskCallback
  -> op.Link(..., model.LinkArgs{})
  -> 115 Cloud Link
  -> stream.NewSeekableStream
  -> PikPak.Put
  -> CacheFullAndHash / RangeRead 读取 115 CDN

复制任务调用 op.Link 时传入的是空 model.LinkArgs{},没有前端请求里的浏览器 User-Agent。115 driver 在生成下载链接和后续读取 CDN 时如果使用空 UA、115Browser UA,或生成直链时的 UA 与 Link.Header 中的 UA 不一致,就可能触发 115 CDN 403 no cookie value

修复建议

在 115 Cloud driver 的 Link 中处理后台任务没有 User-Agent 的情况:

  1. 如果 args.Header.Get("User-Agent") 为空,使用 OpenList 通用浏览器 UA,例如 base.UserAgent,不要默认使用 Mozilla/5.0 115Browser/<version> 作为 CDN 下载 UA。
  2. 调用 DownloadWithUA 生成直链时使用该 UA。
  3. 返回 model.Link 时 clone downloadInfo.Header,并确保 Cookie 与同一个 User-Agent 被保留到 Link.Header,让后续 RangeRead 请求 115 CDN 时使用一致的 header。

示例修复方向:

userAgent := args.Header.Get("User-Agent")
if userAgent == "" {
    userAgent = base.UserAgent
}

downloadInfo, err := d.client.DownloadWithUA(file.(*FileObj).PickCode, userAgent)
if err != nil {
    return nil, err
}

header := http.Header{}
if downloadInfo.Header != nil {
    header = downloadInfo.Header.Clone()
}
if header.Get("Cookie") == "" && d.Cookie != "" {
    header.Set("Cookie", d.Cookie)
}
if header.Get("User-Agent") == "" {
    header.Set("User-Agent", userAgent)
}

return &model.Link{
    URL:    downloadInfo.Url.Url,
    Header: header,
}, nil

本地验证结果

按上述方向修改后,本地测试通过:

  • 115 Cloud -> PikPak 复制 JPG 成功
  • 115 Cloud -> PikPak 复制 MP4 成功
  • 不再出现 115 CDN 403 no cookie value
  • 目标文件能在 PikPak 目录中刷新看到

额外说明

PikPak 秒传/上传路径还可能出现任务已完成但进度停在 50 的显示问题:CacheFullAndHash 会将读源文件/算 GCID 的进度映射到 0-50,如果 PikPak 秒传成功后直接返回,进度不会补到 100。这可以在 PikPak Put 成功返回前补一次 up(100) 作为单独显示修复。

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions