Skip to content

fix(webdav): correct COPY/MOVE semantics, dead property persistence, and lock enforcement - #2903

Open
devLythen wants to merge 5 commits into
OpenListTeam:mainfrom
devLythen:main
Open

fix(webdav): correct COPY/MOVE semantics, dead property persistence, and lock enforcement#2903
devLythen wants to merge 5 commits into
OpenListTeam:mainfrom
devLythen:main

Conversation

@devLythen

@devLythen devLythen commented Aug 4, 2026

Copy link
Copy Markdown

Summary / 摘要

修复 WebDAV COPY 方法稳定返回 500 Internal Server Error 的问题,同时修复了 COPY/MOVE 状态码语义、死属性持久化、锁路径解析和共享锁支持。

  • COPY 同目录/跨目录、绝对/相对 Destination 均正常工作,覆盖语义符合 RFC 4918

  • PROPPATCH 设置的自定义属性可持久化,PROPFIND 可检索,MOVE 时自动迁移

  • 锁检查使用用户路径解析后的实际资源路径,支持共享锁

  • 拒绝含非法 XML 声明的 PROPFIND 请求体

  • This PR has breaking changes.
    / 此 PR 包含破坏性变更。

  • This PR changes public API, config, storage format, or migration behavior.
    / 此 PR 修改了公开 API、配置、存储格式或迁移行为。

  • This PR requires corresponding changes in related repositories.
    / 此 PR 需要关联仓库同步修改。

Related repository PRs / 关联仓库 PR:

  • OpenList-Frontend:
  • OpenList-Docs:

Related Issues / 关联 Issue

Testing / 测试

  • go test ./server/webdav ./internal/fs
  • Manual test / 手动测试: Litmus 全量测试套件通过公网 Nginx HTTPS 入口执行
功能 修复前 完成进度
basic 16/16 16/16
copymove 9/13 (COPY 500、MOVE 覆盖语义失败) 13/13
props 9/14 (PROPPATCH 403、namespace 非法通过) 30/30
locks 24/34 (锁不生效、共享锁不支持) 40/41
http 3/3 3/3

其中 locks.fail_complex_cond_put 未通过

该测试要求锁条件中校验无效 ETag,上游 golang.org/x/net/webdav 的 lookup 函数同样标注 TODO: support Condition.Not and Condition.ETag 未实现。主流 WebDAV 客户端不使用 ETag+锁令牌组合条件,无功能影响。

Checklist / 检查清单

  • I have read CONTRIBUTING.
    / 我已阅读 CONTRIBUTING
  • I confirm this contribution follows the repository license, contribution policy, and code of conduct.
    / 我确认此贡献符合仓库许可证、贡献规范和行为准则。
  • I have formatted the changed code with gofmt, go fmt, or prettier where applicable.
    / 我已按适用情况使用 gofmtgo fmtprettier 格式化变更代码。
  • I have requested review from relevant maintainers or code owners where applicable.
    / 我已在适用情况下请求相关维护者或代码所有者审查。

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR improves the server’s WebDAV behavior by aligning COPY/MOVE responses and lock handling with RFC 4918 expectations, and by introducing persistent “dead property” storage so PROPPATCH/PROPFIND can round-trip custom properties across requests and MOVE operations.

Changes:

  • Add shared-lock support and adjust lock confirmation to validate against the user-resolved resource path.
  • Persist dead WebDAV properties in the DB (new model + migration) and surface them via PROPFIND; migrate them on MOVE.
  • Fix COPY/MOVE target naming semantics by introducing a named-copy path (CopyTo) and extending transfer-task metadata to carry the destination name.

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
server/webdav/xml.go Updates lockinfo parsing/output; changes PROPFIND body parsing/validation.
server/webdav/webdav.go Adjusts request dispatch, lock confirmation logic, and property lookup call signatures.
server/webdav/prop.go Implements DB-backed dead property persistence and MOVE migration.
server/webdav/lock.go Extends lock model and in-memory lock system to support shared locks.
server/webdav/file.go Refines MOVE/COPY filesystem behavior (destination validation, overwrite semantics, named copy).
internal/model/webdav_property.go Adds DB model for persisted dead properties.
internal/db/db.go Auto-migrates the new WebDAVProperty table.
internal/fs/fs.go Adds CopyTo API for named COPY operations.
internal/fs/other.go Extends transfer task metadata with DstName.
internal/fs/copy_move.go Threads dstName through transfer execution and stream naming to preserve destination name.
Suppressed comments (1)

server/webdav/file.go:126

  • copyFiles verifies that dstDir exists but does not verify it is a directory. If dstDir exists as a file, COPY should fail with 409 (Conflict) rather than attempting a copy into a non-collection path.
	if _, err = fs.Get(ctx, dstDir, &fs.GetArgs{}); err != nil {
		if errs.IsObjectNotFound(err) {
			return http.StatusConflict, err
		}
		return http.StatusMethodNotAllowed, err

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread server/webdav/prop.go
Comment thread server/webdav/file.go Outdated
Comment thread server/webdav/xml.go Outdated
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.

2 participants