Session修改:Mutex死锁修复+AGENTS更新

This commit is contained in:
Warren Lo
2026-05-18 17:02:30 +08:00
parent 8589a02042
commit 14863d323e
41 changed files with 10152 additions and 28 deletions

View File

@@ -0,0 +1,238 @@
# WebDAV LOCK拦截机制详解
## 核心拦截点
dav-server框架在HTTP请求处理流程中内置锁检查机制无需手动拦截。
### 1. PUT写文件拦截点
**文件位置**: `~/.cargo/registry/src/*/dav-server-0.11.0/src/handle_put.rs:131-139`
```rust
// if locked check if we hold that lock.
if let Some(ref locksystem) = self.ls {
let principal = self.principal.as_deref();
if let Err(_l) = locksystem
.check(&path, principal, false, false, &tokens)
.await
{
return Err(DavError::StatusClose(SC::LOCKED)); // 423 LOCKED
}
}
```
**拦截流程**:
```
客户端 PUT /webdav/file.txt
DavHandler.handle_put()
if_match_get_tokens() - 解析If头中的lock token
locksystem.check() - 检查锁冲突
↓ (失败)
返回 423 LOCKED (客户端无权限)
↓ (成功)
LocalFs.write() - 执行实际写入
```
### 2. DELETE删除拦截点
**文件位置**: `~/.cargo/registry/src/*/dav-server-0.11.0/src/handle_delete.rs:123-132`
```rust
// check locks. since we cancel the entire operation if there is
// a conflicting lock, we do not return a 207 multistatus, but
// just a simple status.
if let Some(ref locksystem) = self.ls {
let principal = self.principal.as_deref();
if let Err(_l) = locksystem
.check(&path, principal, false, true, &tokens) // deep=true
.await
{
return Err(DavError::Status(StatusCode::LOCKED));
}
}
```
**关键参数**: `deep=true` 表示检查整个路径树(包括子目录)
**拦截流程**:
```
客户端 DELETE /webdav/folder/
DavHandler.handle_delete()
locksystem.check(&path, principal, false, true, &tokens)
↓ (冲突)
返回 423 LOCKED
↓ (成功)
locksystem.delete(&path) - 删除所有锁记录
LocalFs.remove_dir() - 执行删除
```
### 3. LOCK加锁拦截点
**文件位置**: `~/.cargo/registry/src/*/dav-server-0.11.0/src/handle_lock.rs`
```rust
// 创建新锁
let lock = locksystem.lock(
&path,
principal,
owner,
timeout,
shared,
deep,
).await;
// 刷新锁
let lock = locksystem.refresh(&path, &tokens[0], timeout).await;
```
**拦截流程**:
```
客户端 LOCK /webdav/file.txt
DavHandler.handle_lock()
检查If头中的token
↓ (有token)
locksystem.refresh() - 刷新现有锁
↓ (无token)
locksystem.lock() - 创建新锁
返回 200 OK + lock token
```
### 4. UNLOCK解锁拦截点
**文件位置**: `~/.cargo/registry/src/*/dav-server-0.11.0/src/handle_lock.rs`
```rust
locksystem.unlock(&path, &lock_token).await
```
**拦截流程**:
```
客户端 UNLOCK /webdav/file.txt
Header: Lock-Token: <urn:uuid:xxx>
DavHandler.handle_unlock()
解析Lock-Token头
locksystem.unlock(&path, &token)
↓ (成功)
返回 204 No Content
↓ (失败)
返回 403 Forbidden (token无效)
```
## DavLockSystem.check() 参数详解
```rust
fn check(
path: &DavPath, // 文件路径
principal: Option<&str>, // 用户身份来自Authorization头
ignore_principal: bool, // true=忽略用户身份检查
deep: bool, // true=检查子路径锁
submitted_tokens: &[String], // If头中的lock tokens
) -> LsFuture<'_, Result<(), DavLock>>
```
**返回值**:
- `Ok(())` - 有权限(锁匹配或无锁)
- `Err(DavLock)` - 冲突锁返回423 LOCKED
## if_match_get_tokens() 作用
**文件位置**: `~/.cargo/registry/src/*/dav-server-0.11.0/src/conditional.rs`
解析HTTP请求中的lock tokens
- `If: <urn:uuid:xxx>` - 单个token
- `If: (<urn:uuid:xxx>)` - 标准格式
- `If-Match: *` - 需要任意锁
- `If-None-Match: *` - 需要无锁
## MarkBase实现位置
**LockManager**: `src/webdav/lock_manager.rs`
```rust
impl DavLockSystem for LockManager {
fn check(
&'_ self,
path: &DavPath,
principal: Option<&str>,
ignore_principal: bool,
deep: bool,
submitted_tokens: &[String],
) -> LsFuture<'_, Result<(), DavLock>> {
// 1. 查询SQLite数据库中的锁
// 2. 清理过期锁cleanup_expired_locks
// 3. 比对submitted_tokens匹配则允许
// 4. 比对principal同用户则允许
// 5. 检查deep锁子路径冲突
// 6. 返回冲突锁Err或允许Ok
}
}
```
## HTTP状态码对照
|状态码 |含义 |触发条件 |
|-------|------|----------|
| 200 OK | LOCK成功 | lock()返回Ok |
| 204 No Content | UNLOCK/PUT成功 | unlock()或write()成功 |
| 403 Forbidden | UNLOCK失败 | unlock()返回Errtoken无效|
| 423 Locked | 操作被锁阻止 | check()返回Err |
| 409 Conflict | 目标不存在 | 文件不存在且无法创建 |
| 412 Precondition Failed | If条件不满足 | If-Match/If-None-Match失败 |
## macOS Finder行为
**典型请求序列**:
```
1. PROPFIND /webdav/ - 获取文件列表
2. LOCK /webdav/file.txt - 加锁( exclusive
Header: If: (<urn:uuid:xxx>)
3. PUT /webdav/file.txt - 写入带If头
Header: If: (<urn:uuid:xxx>)
4. UNLOCK /webdav/file.txt - 解锁
Header: Lock-Token: <urn:uuid:xxx>
```
**锁有效期**: macOS Finder默认60秒超时需定期refresh
## 测试方法
```bash
# 手动测试锁机制
curl -X LOCK http://localhost:4919/webdav/test.txt \
-H "Content-Type: application/xml" \
-d '<D:lockinfo><D:locktype><D:write/></D:locktype><D:lockscope><D:exclusive/></D:lockscope></D:lockinfo>'
# 查看锁token
curl -X PROPFIND http://localhost:4919/webdav/test.txt \
-H "Depth: 0" \
-H "Content-Type: application/xml" \
-d '<D:propfind><D:prop><D:lockdiscovery/></D:prop></D:propfind>'
# 尝试写入无锁token
curl -X PUT http://localhost:4919/webdav/test.txt \
-d "test content"
# 预期423 Locked
# 写入带正确token
curl -X PUT http://localhost:4919/webdav/test.txt \
-H "If: (<urn:uuid:YOUR_TOKEN>)" \
-d "test content"
# 预期204 No Content
```
---
**创建时间**: 2026-05-17 03:30
**版本**: 1.0(拦截点详解版)