// LOCK 响应解析:从响应头 / 响应体里定出「服务端确认的那把锁」。
// 与 lock_ops.mbt 的操作流程分开,单独成文件以遵守单文件行数上限(RL-04)。
///|
/// 只有令牌、没有 lockdiscovery 元数据时的兜底锁条目。
fn bare_lock(
token : String,
timeout : String?,
scope : @types.LockScope,
) -> @types.ActiveLock {
{ token, scope, depth: None, owner: None, timeout, lockroot: None, }
}
///|
/// 用 `Timeout` 响应头补齐响应体缺失的锁超时。
fn fill_timeout(
lock : @types.ActiveLock,
response : @moonhttp.Response,
) -> @types.ActiveLock {
match lock.timeout {
Some(_) => lock
None =>
{
token: lock.token,
scope: lock.scope,
depth: lock.depth,
owner: lock.owner,
timeout: first_timeout_segment(response),
lockroot: lock.lockroot,
}
}
}
///|
/// 取 `Timeout` 响应头的首段(形如 `Second-600, Infinite`);
/// 没有该头或首段为空时返回 `None`。
fn first_timeout_segment(response : @moonhttp.Response) -> String? {
match response.headers.get("Timeout") {
Some(value) => {
let buf = StringBuilder()
for ch in value {
if ch == ',' {
break
}
buf.write_char(ch)
}
let segment = buf.to_string().trim().to_owned()
if segment == "" {
None
} else {
Some(segment)
}
}
None => None
}
}
///|
/// 从 LOCK 响应里取锁:`Lock-Token` 头优先,其次响应体首个 `activelock`;
/// 两者都没有时用 `fallback`(刷新锁用请求里的令牌),`fallback` 为空则抛错。
/// 服务端没回 `lockscope` 时按 `default_scope`(本次请求的作用域)回填。
fn lock_from_response(
response : @moonhttp.Response,
fallback~ : String,
operation~ : String,
default_scope? : @types.LockScope,
) -> @types.ActiveLock raise @types.WebdavError {
let mut xml_error : @xml.XmlError? = None
let locks = @xmlutil.parse_lockdiscovery(response.text(), default_scope?) catch {
error => {
xml_error = Some(error)
[]
}
}
let header_token = match response.headers.get("Lock-Token") {
Some(value) => @types.normalize_lock_token(value)
None => ""
}
let scope = default_scope.unwrap_or(@types.LockScope::Exclusive)
let from_body = if locks.length() > 0 { Some(locks[0]) } else { None }
match from_body {
Some(lock) => {
// 头与体不一致时以头为准(响应头是权威来源)
let merged : @types.ActiveLock = if header_token != "" &&
header_token != lock.token {
{
token: header_token,
scope: lock.scope,
depth: lock.depth,
owner: lock.owner,
timeout: lock.timeout,
lockroot: lock.lockroot,
}
} else {
lock
}
fill_timeout(merged, response)
}
None =>
if header_token != "" {
fill_timeout(bare_lock(header_token, None, scope), response)
} else if fallback != "" {
fill_timeout(bare_lock(fallback, None, scope), response)
} else {
match xml_error {
Some(error) => raise @types.WebdavError::xml(error)
None =>
raise @types.WebdavError::api(
status=response.status,
operation~,
message="响应缺少锁令牌(既无 Lock-Token 头也无 lockdiscovery)",
)
}
}
}
}