Problem
AsterDrive 当前已经具备一套面向产品存储体系的自研 WebDAV 实现:GET/HEAD 直接使用 StorageDriver::get_stream() / get_range(),PUT 已接入 storage policy、quota、dedup、审计和远端直传,LOCK、PROPFIND、PROPPATCH、COPY、MOVE、DELETE 也有较完整的产品级实现。
但当前实现与历史依赖的 dav-server 0.11.0 在协议完整度、响应内存边界、HTTP 条件请求和自动化合规验证上仍存在差距。当前差距主要集中在:
这张 issue 作为 umbrella roadmap,目标是达到 dav-server 基础 WebDAV/HTTP 行为的验证水平,同时保留 AsterDrive 对对象存储直连、Range 下推、上传策略、审计和权限作用域的优势。
Goal
完成以下目标:
- RFC 4918 基础行为由 Litmus 和真实客户端测试证明,而不是只依赖单元测试。
- HTTP 条件请求、Range、锁 token、COPY/MOVE 目标条件的行为有完整矩阵和边界测试。
- 大目录 PROPFIND、递归 COPY/MOVE/DELETE、Multi-Status 和多区间下载都有明确资源上界。
- 对外
DAV / Allow / live properties 能力声明与实际实现一致。
- 保持大文件 GET 走
StorageDriver::get_stream(),Range GET 走原生 StorageDriver::get_range(),不回退到完整对象临时下载。
Proposed work
Phase 0: Establish the conformance baseline
AsterDrive 适用性说明: dead properties 存放在数据库 entity_properties 表中,并通过解析后的 file/folder entity_type + entity_id 关联;.DAV 没有映射到内部属性数据库。产品语义上 .DAV 是合法的普通用户目录,不需要为了该套件保留或封禁。对 .DAV 的创建、读取、移动或删除只操作普通 file/folder entity,不会触达属性表、锁表或其他可信内部元数据。因此 15 项差异是与 Apache 文件式属性数据库模型的预期差异,本身不代表 dead-property storage 暴露或产品安全漏洞。webdav_block_system_files_* 只负责可配置的客户端垃圾文件策略,不承担内部元数据隔离职责。
当前 Litmus 0.18 默认五组基线:
| Group |
Cases |
Current result |
basic |
16 |
Pass;保留 #424 的 delete_fragment warning |
copymove |
13 |
Pass,无已知差异 |
props |
33 |
Pass,无已知差异 |
locks |
40 |
#425 修复验证后 Pass,无已知差异 |
http |
4 |
Pass,无已知差异 |
Phase 0 期间拆出了 #423、#424、#425 和 #426。当前验证中 Litmus 0.18 已不再复现 #423 / #425 / #426,其中 #425 的 tagged collection-root token 修复后 locks 40/40 通过,待代码合入;#427 继续跟踪跨 PROPFIND、PROPPATCH、LOCK 和 DeltaV handler 的统一 XML QName/extensibility/grammar contract,#411 继续负责 bounded XML parser/writer 实现。
Phase 1: Correct capability advertisement and HTTP preconditions
Phase 2: Range and download contract parity
Phase 3: Bounded and streaming PROPFIND/Multi-Status
Phase 4: Live properties and client compatibility
Phase 5: Optional write parity
Phase 6: Boundary cleanup
Acceptance criteria
- WebDAV Litmus
basic、copymove、props、locks、http 在 CI 中通过,或每个剩余差异都有独立 issue、标准依据和明确的产品决策。
- rclone、curl、cadaver 客户端兼容测试有自动化运行入口,并覆盖当前已写的场景。
If-Range、single-range、multi-range、HEAD with Range、304/412、short read、client cancellation 均有回归测试。
- 大目录 PROPFIND 和递归 mutation 的内存、响应字节、节点数和执行时间有硬边界;客户端取消后不会继续遍历整个资源树。
- Full GET 仍只使用
get_stream(),Range GET 仍只使用目标区间的 get_range();性能测试证明没有退化成完整对象下载。
- OPTIONS、DAV compliance tokens、Allow、live properties 和实际方法集合一致。
- 所有新行为都保留 storage policy、quota、审计、权限 scope、锁 token 和失败清理语义。
Non-goals
- 暂不为了协议对齐引入 CalDAV/CardDAV。
- 暂不引入 Hyper/Warp 兼容层;当前产品运行时仍以 Actix 为边界。
- 暂不默认启用目录 HTML autoindex/indexfile。
- 暂不采用“后端文件截断时补零”的传输策略。
- 暂不把对象存储强行包装成频繁远端
seek() 的本地文件模型。
Depth: infinity 是否开放继续以资源上界和实际客户端需求为前提,不为通过单个测试而移除限制。
Suggested child issues
Filed from Phase 0
Remaining child scopes
- Honest OPTIONS/DAV/DeltaV capability advertisement
- Implement HTTP If-Range and complete conditional request matrix
- Bounded multipart multi-range downloads
- Streaming PROPFIND and 207 Multi-Status responses
- Paginated WebDAV directory enumeration
- Resource limits and cancellation for recursive COPY/MOVE/DELETE
- WebDAV quota and client interoperability properties
- Partial PUT/PATCH backed by staging or upload sessions
- Split WebDAV download and write abstractions
Category
Performance, protocol compatibility, storage backends, and Rust maintenance.
Checklist
Problem
AsterDrive 当前已经具备一套面向产品存储体系的自研 WebDAV 实现:GET/HEAD 直接使用
StorageDriver::get_stream()/get_range(),PUT 已接入 storage policy、quota、dedup、审计和远端直传,LOCK、PROPFIND、PROPPATCH、COPY、MOVE、DELETE 也有较完整的产品级实现。但当前实现与历史依赖的
dav-server 0.11.0在协议完整度、响应内存边界、HTTP 条件请求和自动化合规验证上仍存在差距。当前差距主要集中在:If-Range语义和 multipart/byteranges。read_dir()当前先把一个目录的全部 folder/file 记录和 entries 收集到Vec,下游没有真正的分页/增量读取边界。OPTIONS固定声明DAV: 1, 2, version-control和完整 Allow 集合,但 DeltaV 当前是最小子集,资源级能力也没有动态反映。Depth: infinitycollection lock 的 descendant token propagation([Bug]: Depth-infinity WebDAV collection locks reject valid descendant mutations #425)修复已在本地验证,待合入;locks40/40 通过。DavFiletrait 保留了通用 read/seek 形状,但 AsterDrive GET 已经绕开它,AsterDavFile::read_bytes()实际上是写路径上的禁止操作,抽象边界已经出现分叉。这张 issue 作为 umbrella roadmap,目标是达到
dav-server基础 WebDAV/HTTP 行为的验证水平,同时保留 AsterDrive 对对象存储直连、Range 下推、上传策略、审计和权限作用域的优势。Goal
完成以下目标:
DAV/Allow/ live properties 能力声明与实际实现一致。StorageDriver::get_stream(),Range GET 走原生StorageDriver::get_range(),不回退到完整对象临时下载。Proposed work
Phase 0: Establish the conformance baseline
scripts/ci/webdav-compat/install-litmus.sh在 Linux/macOS 使用同一入口构建。basic、copymove、props、locks、http五组默认测试,并固定每组预期用例数。FAIL/SKIPPED/WARNING、过期豁免、用例数漂移和进程状态不一致都会使检查失败。result.json。tests/webdav/target。largefile、lockbomb、lockbomb-single增加独立 ignored 测试、用例数断言和分组超时;它们保持在普通 PR 门禁之外。protected单独归类为安全实现策略探针,固定TEST_PROTECTED=.DAV和 25 个用例;当前结果为 10 pass / 15 policy differences,结构化记录但不进入 RFC 合规 baseline。当前 Litmus 0.18 默认五组基线:
basicdelete_fragmentwarningcopymovepropslockshttpPhase 0 期间拆出了 #423、#424、#425 和 #426。当前验证中 Litmus 0.18 已不再复现 #423 / #425 / #426,其中 #425 的 tagged collection-root token 修复后
locks40/40 通过,待代码合入;#427 继续跟踪跨PROPFIND、PROPPATCH、LOCK和 DeltaV handler 的统一 XML QName/extensibility/grammar contract,#411 继续负责 bounded XML parser/writer 实现。Phase 1: Correct capability advertisement and HTTP preconditions
Allow、DAV、MS-Author-Via从静态字符串改成与资源类型、启用的扩展和实际方法一致的能力集合。version-controlcompliance token。目前src/webdav/deltav.rs只实现了VERSION-CONTROL和version-tree REPORT的最小子集;需要补齐对应 live properties / report metadata,或者在完整语义准备好前调整对外声明。If-Range:支持强 ETag 和 HTTP date;匹配时保留 Range 并返回206,不匹配时忽略 Range 并返回完整200。If-Match、If-None-Match、If-Modified-Since、If-Unmodified-Since、Ifheader 的 tagged/untagged list,以及 GET/PUT/DELETE/COPY/MOVE/LOCK refresh 的优先级。Cache-Control行为。Phase 2: Range and download contract parity
multipart/byteranges。StorageDriver::get_range();原生 Range 驱动和默认从完整流跳过前缀的驱动分别建立性能断言。Content-Length的数据。Phase 3: Bounded and streaming PROPFIND/Multi-Status
xmltree::Element聚合改为增量 XML writer,逐个资源输出<D:response>。read_dir()增加稳定排序、批量查询和游标/分页能力;当前返回FsStream,但实现内部仍先构造完整 entriesVec。Phase 4: Live properties and client compatibility
DavFileSystem::get_quota(),为quota-used-bytes/quota-available-bytes提供真实 scope-aware 值,并避免每个资源重复查询 quota。getcontentlanguage的返回策略;只有在真实客户端需要时再补 Microsoft Win32 properties 和其他厂商扩展。PROPFIND propname、空 body allprop、指定 namespace、未知 live property、dead property 和锁属性建立标准化快照测试。Phase 5: Optional write parity
PUT + Content-Range和PATCH + X-Update-Range的实际客户端需求。Phase 6: Boundary cleanup
DownloadSource/open_full/open_range,将写入能力单独抽象为DavWriteHandle,不再让 GET 依赖一个实际只用于写入的DavFile::read_bytes()。Acceptance criteria
basic、copymove、props、locks、http在 CI 中通过,或每个剩余差异都有独立 issue、标准依据和明确的产品决策。If-Range、single-range、multi-range、HEAD with Range、304/412、short read、client cancellation 均有回归测试。get_stream(),Range GET 仍只使用目标区间的get_range();性能测试证明没有退化成完整对象下载。Non-goals
seek()的本地文件模型。Depth: infinity是否开放继续以资源上界和实际客户端需求为前提,不为通过单个测试而移除限制。Suggested child issues
Filed from Phase 0
MKCOLover an existing non-collection resource; current Litmus 0.18 run no longer reproduces it, pending issue reconciliation.%23filenames.locks40/40 通过,待合入后关闭。PROPFINDextension elements/subtrees per RFC 4918 Section 17; current Litmus 0.18propextendedpasses, pending issue reconciliation.xmltreewith a bounded parser/writer without changing the protocol contract.Remaining child scopes
Category
Performance, protocol compatibility, storage backends, and Rust maintenance.
Checklist
dav-server 0.11.0behavior were compared.tests/webdav/main.rstarget;普通 PR 默认只运行 Litmus 五组,不混入大文件或锁压力套件。