Hacktoberfest 2026: le issue che i maintainer hanno segnato per ottobre, aperte e adatte ai principianti. Sfoglia le issue Hacktoberfest

[BUG] 请修改标题为您遇到的问题

Chiusa Adatta ai principianti
#103 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 3 giorni

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
2/5
Tempo stimato
1-3 ore
Idoneità per principianti
82/100
Tipo di issue
Bug
Chiarezza
Specificata chiaramente
Stato di attività
Attiva
Stack tecnologico
typescript
Ambito
api, backend

Direzione di ricerca

Inizia da src/backend/server/webdav.ts, nel ramo PROPFIND, e verifica come viene usato davPathOf() per costruire l'href passato a buildWebDavPropfindResponse; esamina src/backend/pkg/xml.ts per confermare come quel percorso diventa d:href. Riproduci il problema con una richiesta PROPFIND con Depth: 1 a /dav/ e verifica che i valori href restituiti mantengano il prefisso /dav e che rclone possa elencare la directory.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

bug
请确认以下事项
  • 我确认描述清晰有礼貌,已提供必要诊断信息,在最新版本上可以复现。
  • 我确认已经查过相关文档和已有问题和讨论,本次反馈并非是重复提问。
  • 我确认这是Worker项目问题,并非网络和操作导致,也不是Go版的问题。
  • 我确认已阅读开源许可/免责条款/使用政策,理解使用的风险自行承担。
版本(必填)

v4.2.3

平台(必填)

Cloudflare Workers

DB_FORMAT(必填)

map(整对象 JSON)

DB_DRIVER(必填)

kv

存储驱动(必填)

GuangYaPan(该问题与具体驱动无关,任何存储都会复现)

问题描述(必填)

现象:用标准 WebDAV 客户端(rclone、Windows 资源管理器、RaiDrive 等)挂载 /dav 端点后,所有目录都显示为空,但同级文件接口 /api/fs/list 完全正常。

根因:PROPFIND 响应里的 D:href 缺少 /dav 挂载前缀。

src/backend/server/webdav.ts 中 davPathOf() 已经把 /dav 前缀剥掉得到虚拟径

function davPathOf(c: any): string {
const pathname = new URL(c.req.url).pathname
let p = pathname.replace(/^/dav/, "") // ← 剥掉挂载前缀
...
}

而 PROPFIND 分支直接把这个已剥前缀的 davPath 当作 href 输出:
const href =
davPath === "/"
? "/"
: davPath.endsWith("/")
? davPath
: davPath + "/"
const xml = buildWebDavPropfindResponse(href, items)

src/backend/pkg/xml.ts 的 generateWebDavXml() 再把它原样写进 <d:href>:
xml += <d:href>${path}</d:href>\n
// 子项:const itemHref = ${path}${path.endsWith("/") ? "" : "/"}${encodeURIComponent(item.name)}

这违反 RFC 4918:D:href 必须是完整请求 URI。客户端请求 /dav/wewe,服务端返回的却是 /wewe/70rop,与请求路径不匹配。

实测响应(PROPFIND /dav/,Depth: 1):
<d:multistatus xmlns:d="DAV:">
<d:response>
<d:href>/</d:href>
...
<d:response>
<d:href>/WESSSDQ</d:href>
<d:response>
<d:href>/wee</d:href>
<d:response>
<d:href>/wesd</d:href>
<d:response>
<d:href>/wewe</d:href>

预期应为 /dav/、/dav/WESSSDQ、/dav/wewe
客户端表现:rclone 会为每条记录打印
DEBUG : Item with unknown path received: "/wewe/70rop/", "/dav/wewe/"

并丢弃全部条目 → rclone lsd 输出为空、rclone size 报 0 个对象。Windows 资源管理器同样打开后为空。

说明:GET(下载)不受影响,因为下载走 302 重定向而非依赖 href;只有需要列目录的 PROPFIND 受影响。因此表现为「能下不能列」,容易被误判为客户端问题。

报错信息(必填)

rclone lsd openlist:wewe -vv 输出节选:
2026/10/04 21:45:18 DEBUG : Item with unknown path received: "/wewe/", "/dav/wewe/"
2026/10/04 21:45:18 DEBUG : Item with unknown path received: "/wewe/70rop/", "/dav/wewe/"
2026/10/04 21:45:18 DEBUG : Item with unknown path received: "/wewe/70rop1/", "/dav/wewe/"
2026/10/04 21:45:18 DEBUG : Item with unknown path received: "/wewe/ap/", "/dav/wewe/"
2026/10/04 21:45:18 DEBUG : Item with unknown path received: "/wewe/ddd/", "/dav/wewe/"
2026/10/04 21:45:18 DEBUG : Item with unknown path received: "/wewe/来自:TOKEN订阅/", "/dav/wewe/"
2026/10/04 21:45:18 DEBUG : Item with unknown path received: "/wewe/验证器/", "/dav/wewe/"

服务端响应(curl 直取,未经任何中间层):
$ curl -s -u USER:PASS -X PROPFIND -H "Depth: 1" https:///dav/

<d:multistatus xmlns:d="DAV:">
<d:response>
<d:href>/</d:href>

相关配置(必填)

DB_DRIVER=kv
DB_FORMAT=map
DB_CIPHER=aes-256-gcm
wrangler.jsonc:
"assets": { "directory": "./dist", "binding": "ASSETS", "run_worker_first": ["/", "/index.html"] },
"kv_namespaces": [{ "binding": "KV" }]
存储驱动为 GuangYaPan,mount_path = /wewe,无特殊配置。将该存储换成任意其他驱动,问题一致。

复现链接(可选)

建议修复
在 PROPFIND 分支补回挂载前缀(注意 davPath 后续还需使用,不要原地修改):

ts

// RFC 4918: D:href must be the full request URI, so it has to carry the
// /dav mount prefix that davPathOf() already stripped off.
const hrefPath =
davPath === "/"
? "/dav/"
: "/dav" + (davPath.endsWith("/") ? davPath : davPath + "/")
const xml = buildWebDavPropfindResponse(hrefPath, items)
已实测验证:打上该补丁并部署后,PROPFIND /dav/ 返回 /dav/、/dav/WESSSDQ、/dav/wewe…;rclone 可正常 lsd 与递归遍历,rclone size 正确统计(780 个对象 / 16.768 GiB),Windows 资源管理器与 RaiDrive 等标准客户端亦恢复正常。

补充:同一函数内另外两处相关问题(都是「剥了前缀却按带前缀使用」)

  1. MOVE / COPY 的 Destination 解析省略了 base

ts

dest = decodeURIComponent(new URL(destRaw, c.req.url).pathname).replace(/^/dav/, "")
new URL(destRaw, c.req.url) 的 base 是当前请求 URL。当 Destination 形如 /dav/wewe/b.txt 时能正常工作;但若客户端发相对形式(按 RFC 4918 §9.9.3 的 Destination 应为绝对 URI,实际客户端多按绝对路径发送),其行为取决于 base 推导结果,建议显式固定 base 并明确拒绝非法值,避免静默落到错误路径。

  1. LOCK / UNLOCK 返回 405

上游 Go 版可通过 X-Update-Range / WebDAV 原生写实现 Microsoft Office 直接编辑保存。当前返回 405 Locking not supported,且 OPTIONS 虽声明 DAV: 1, 2(2 表示支持锁定)却未实现 LOCK,属声明与实现不一致;部分客户端(Office)会因此拒绝写入。建议要么实现 LOCK,要么把 DAV 头改为 1 并明确声明不支持锁定。

Lingua principale
TypeScript
Stelle
602
Fork
1k
Merge medio
5g 1h
PR unite (30g)
27

Preparare l'ambiente

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di OpenListTeam/OpenList-Worker

Tutte le issue di OpenListTeam/OpenList-Worker

Issue simili

Altre issue su TypeScript

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.