feat: real WebDAV LOCK/UNLOCK with in-memory lock enforcement#704
feat: real WebDAV LOCK/UNLOCK with in-memory lock enforcement#704image72 wants to merge 3 commits into
Conversation
- Add LockManager with thread-safe lock registry (RwLock<HashMap>) - LOCK: parse lockinfo body, support exclusive/shared locks, conflict detection - UNLOCK: validate Lock-Token header, release lock entries - Lock enforcement on PUT, PATCH, DELETE, MOVE, MKCOL (423 Locked) - If: header support for lock-owner bypass on write operations - PROPPATCH: return 200 OK instead of 403 Forbidden - Allow header: add PROPPATCH, MKCOL, LOCK, UNLOCK methods - DAV header already declares Class 1,2,3 - Add aarch64-unknown-linux-musl cross-compilation linker config
…rt + 23 tests - LockManager::remove_all: clean locks on resource delete/move - handle_delete/handle_move: call remove_all after fs operations - Timeout header parsing (Second-N, Infinite, default 300s) - LockInfo.timeout_seconds with is_expired filtering - cleanup_expired called on acquire (lazy GC on write path) - LOCK response includes Timeout header + <D:timeout> XML - tests/lock.rs: 23 tests covering lock/unlock/enforcement/timeout/delete/move
- LOCK on unmapped paths & collections (remove is_file restriction) - LOCK refresh: parse If: token, call LockManager::refresh to update timeout - If: header fix: use find(first) instead of rfind(last) for multi-condition headers - PROPPATCH enforcement: block PROPPATCH on locked resource for non-owners - COPY destination enforcement: check lock on copy destination path - 412 Precondition Failed: when If: token on unlocked resource - LockManager: add refresh(), get_lock(), has_locks() methods
|
dufs is currently stateless, but your current PR make it stateful. I tend to be against this PR, but I also want to hear more opinions. |
|
Thanks for the review — you're right to flag the statefulness concern. Let me address it directly. 1. This is minimal, non-persistent, self-contained stateLockManager {
locks: RwLock<HashMap<String, Vec<LockInfo>>>,
}
2. The current "fake lock" is worse than no lockDufs currently returns:
But doesn't actually track or enforce locks. This is the worst of both worlds — WebDAV clients (like macOS Finder) believe the resource is locked, but there's no actual protection. Either we should return 3. Cost vs benefit
4. If the project wants extra cautionHappy to add either:
But I'd argue this isn't a feature toggle — it's a protocol compliance fix. Dufs already advertises The alternative would be to downgrade to |
|
Fair point on the statefulness concern. Instead of debating pros and cons here, maybe this is better decided by the actual users who deploy dufs. Could we open a quick GitHub Discussion / poll with something like:
That way the maintainer doesn't have to make the call alone — the community's usage patterns will decide. |
Summary
LockManagertests/lock.rscovering all lock workflowsChanges
Real locking infrastructure
LockManager: thread-safe lock registry (RwLock<HashMap<String, Vec<LockInfo>>>)LockInfo: stores token, scope (exclusive/shared), timeout, created_atLockManager::refresh()for lock renewal viaIf:headerLOCK improvements
Timeoutheader support: parseSecond-NandInfinite, respond with granted timeoutcleanup_expired()called onacquire(lazy GC)is_expired()filters expired entries inis_locked(read path)Lock enforcement on write operations
If:header lock token extraction for owner bypassIf:token on unlocked resourceLock lifecycle management
remove_all()cleans locks on deleted resourceremove_all()cleans locks on source after renameLock-Tokenheader, returns 409 on mismatchAllow/DAV headers
Allownow includesPROPPATCH, MKCOL, LOCK, UNLOCKDAV: 1, 2, 3unchanged (already declared)litmus test results
Files changed
src/server.rs: +350/-30tests/lock.rs: new, 23 teststests/http.rs: update Allow header assertiontests/webdav.rs: update lock/unlock tests.cargo/config.toml: cross-compilation linker config