[PR #704] feat: real WebDAV LOCK/UNLOCK with in-memory lock enforcement #7674

Open
opened 2026-06-01 00:26:34 +03:00 by zhus · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/sigoden/dufs/pull/704
Author: @image72
Created: 5/13/2026
Status: 🔄 Open

Base: mainHead: feat/real-webdav-locking


📝 Commits (3)

  • 16ba3a9 feat: real WebDAV LOCK/UNLOCK with in-memory lock enforcement
  • aa7dd4a feat: lock lifecycle management - DELETE/MOVE cleanup + timeout support + 23 tests
  • b7a770b fix: litmus lock compliance — 24/26 tests pass

📊 Changes

5 files changed (+742 additions, -16 deletions)

View changed files

.cargo/config.toml (+5 -0)
📝 src/server.rs (+403 -13)
📝 tests/http.rs (+1 -1)
tests/lock.rs (+318 -0)
📝 tests/webdav.rs (+15 -2)

📄 Description

Summary

  • Replace fake LOCK/UNLOCK with real lock state tracking via LockManager
  • 23 new tests in tests/lock.rs covering all lock workflows
  • litmus compliance: 24/26 lock tests pass (was 16/26 with fake locks)

Changes

Real locking infrastructure

  • LockManager: thread-safe lock registry (RwLock<HashMap<String, Vec<LockInfo>>>)
  • LockInfo: stores token, scope (exclusive/shared), timeout, created_at
  • Supports exclusive AND shared locks with conflict detection
  • LockManager::refresh() for lock renewal via If: header

LOCK improvements

  • Parse lockinfo XML body for exclusive vs shared scope
  • Timeout header support: parse Second-N and Infinite, respond with granted timeout
  • Default timeout: 300 seconds (5 minutes)
  • cleanup_expired() called on acquire (lazy GC)
  • is_expired() filters expired entries in is_locked (read path)
  • LOCK on unmapped URLs and collections now allowed (RFC 4918 §7.4)

Lock enforcement on write operations

  • PUT, PATCH, DELETE, MOVE, MKCOL, PROPPATCH: rejected with 423 Locked if locked without token
  • COPY: destination lock enforcement
  • If: header lock token extraction for owner bypass
  • 412 Precondition Failed when If: token on unlocked resource

Lock lifecycle management

  • DELETE: remove_all() cleans locks on deleted resource
  • MOVE: remove_all() cleans locks on source after rename
  • UNLOCK: validates Lock-Token header, returns 409 on mismatch

Allow/DAV headers

  • Allow now includes PROPPATCH, MKCOL, LOCK, UNLOCK
  • DAV: 1, 2, 3 unchanged (already declared)

litmus test results

locks: 24/26 passed (92%)
✅ lock_excl, discover, refresh, unlock, copy
✅ lock_shared, double_sharedlock  
✅ notowner_lock, notowner_modify (PROPPATCH, DELETE)
✅ owner_modify, cond_put_corrupt_token
✅ fail_cond_put_unlocked, cond_put_with_not
⚠️  cond_put, complex_cond_put — etag in If: not yet evaluated

Files changed

  • src/server.rs: +350/-30
  • tests/lock.rs: new, 23 tests
  • tests/http.rs: update Allow header assertion
  • tests/webdav.rs: update lock/unlock tests
  • .cargo/config.toml: cross-compilation linker config

🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/sigoden/dufs/pull/704 **Author:** [@image72](https://github.com/image72) **Created:** 5/13/2026 **Status:** 🔄 Open **Base:** `main` ← **Head:** `feat/real-webdav-locking` --- ### 📝 Commits (3) - [`16ba3a9`](https://github.com/sigoden/dufs/commit/16ba3a9c1dc9fdcaf94b0ee6b95a222331d590cb) feat: real WebDAV LOCK/UNLOCK with in-memory lock enforcement - [`aa7dd4a`](https://github.com/sigoden/dufs/commit/aa7dd4acf2a555f3e8ca038a6ecb757a7fa17537) feat: lock lifecycle management - DELETE/MOVE cleanup + timeout support + 23 tests - [`b7a770b`](https://github.com/sigoden/dufs/commit/b7a770b3aed791594faf335a707944bd2ffad866) fix: litmus lock compliance — 24/26 tests pass ### 📊 Changes **5 files changed** (+742 additions, -16 deletions) <details> <summary>View changed files</summary> ➕ `.cargo/config.toml` (+5 -0) 📝 `src/server.rs` (+403 -13) 📝 `tests/http.rs` (+1 -1) ➕ `tests/lock.rs` (+318 -0) 📝 `tests/webdav.rs` (+15 -2) </details> ### 📄 Description ## Summary - Replace fake LOCK/UNLOCK with real lock state tracking via `LockManager` - 23 new tests in `tests/lock.rs` covering all lock workflows - litmus compliance: **24/26 lock tests pass** (was 16/26 with fake locks) ## Changes ### Real locking infrastructure - `LockManager`: thread-safe lock registry (`RwLock<HashMap<String, Vec<LockInfo>>>`) - `LockInfo`: stores token, scope (exclusive/shared), timeout, created_at - Supports exclusive AND shared locks with conflict detection - `LockManager::refresh()` for lock renewal via `If:` header ### LOCK improvements - Parse lockinfo XML body for exclusive vs shared scope - `Timeout` header support: parse `Second-N` and `Infinite`, respond with granted timeout - Default timeout: 300 seconds (5 minutes) - `cleanup_expired()` called on `acquire` (lazy GC) - `is_expired()` filters expired entries in `is_locked` (read path) - LOCK on unmapped URLs and collections now allowed (RFC 4918 §7.4) ### Lock enforcement on write operations - **PUT, PATCH, DELETE, MOVE, MKCOL, PROPPATCH**: rejected with 423 Locked if locked without token - **COPY**: destination lock enforcement - `If:` header lock token extraction for owner bypass - 412 Precondition Failed when `If:` token on unlocked resource ### Lock lifecycle management - DELETE: `remove_all()` cleans locks on deleted resource - MOVE: `remove_all()` cleans locks on source after rename - UNLOCK: validates `Lock-Token` header, returns 409 on mismatch ### Allow/DAV headers - `Allow` now includes `PROPPATCH, MKCOL, LOCK, UNLOCK` - `DAV: 1, 2, 3` unchanged (already declared) ## litmus test results ``` locks: 24/26 passed (92%) ✅ lock_excl, discover, refresh, unlock, copy ✅ lock_shared, double_sharedlock ✅ notowner_lock, notowner_modify (PROPPATCH, DELETE) ✅ owner_modify, cond_put_corrupt_token ✅ fail_cond_put_unlocked, cond_put_with_not ⚠️ cond_put, complex_cond_put — etag in If: not yet evaluated ``` ## Files changed - `src/server.rs`: +350/-30 - `tests/lock.rs`: new, 23 tests - `tests/http.rs`: update Allow header assertion - `tests/webdav.rs`: update lock/unlock tests - `.cargo/config.toml`: cross-compilation linker config --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
zhus added the pull-request label 2026-06-01 00:26:34 +03:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: sigoden/dufs#7674