16. Precondition/Postcondition XML Elements (前置/后置条件 XML 元素)
16. Precondition/Postcondition XML Elements (前置/后置条件 XML 元素)
如第 8.7 节所介绍, 关于错误条件的额外信息可以包含在许多状态响应的正文中。本节对错误正文机制的使用提出要求, 并引入了许多前置条件和后置条件代码。
方法的 "前置条件 (precondition)" 描述了必须为真才能执行该方法的服务器状态。方法的 "后置条件 (postcondition)" 描述了该方法完成后必须为真的服务器状态。
每个前置条件和后置条件都有一个与之关联的唯一 XML 元素。在 207 Multi-Status 响应中, XML 元素必须出现在适当的 'propstat 或 'response' 元素中的 'error' 元素内, 具体取决于条件是应用于一个或多个属性还是应用于整个资源。在使用本规范的 'error' 正文的所有其他错误响应中, 前置条件/后置条件 XML 元素必须作为响应正文中顶级 'error' 元素的子元素返回, 除非请求另有协商, 同时返回适当的响应状态。最常见的响应状态码是 403 (Forbidden), 如果请求不应重复因为它总是会失败, 以及 409 (Conflict), 如果预期用户可能能够解决冲突并重新提交请求。'error' 元素可以包含具有特定错误信息的子元素, 并且可以使用任何自定义子元素进行扩展。
此机制不能取代使用此处或 HTTP 中定义的正确数字状态码, 因为客户端必须始终能够仅根据数字代码采取合理的行动方案。但是, 它确实消除了定义新数字代码的需要。用于此目的的新机器可读代码是分类为前置条件和后置条件的 XML 元素, 因此自然地, 任何定义新条件代码的组都可以使用自己的命名空间。与往常一样, "DAV:" 命名空间保留供 IETF 特许的 WebDAV 工作组使用。
支持本规范的服务器应该在违反本文档中定义的前置条件或后置条件时使用 XML 错误。对于本文档中未指定的错误条件, 服务器可以简单地选择适当的数字状态并将响应正文留空。但是, 服务器可以改为使用自定义条件代码和其他支持文本, 因为即使客户端不会自动识别条件代码, 它们在互操作性测试和调试中也非常有用。
示例 - 带有前置条件代码的响应:
HTTP/1.1 423 Locked
Content-Type: application/xml; charset="utf-8"
Content-Length: xxxx
<?xml version="1.0" encoding="utf-8" ?>
<D:error xmlns:D="DAV:">
<D:lock-token-submitted>
<D:href>/workspace/webdav/</D:href>
</D:lock-token-submitted>
</D:error>
在此示例中, 客户端不知道父集合 "/workspace/webdav/" 上的深度无限锁, 试图修改集合成员 "/workspace/webdav/proposal.doc"。
其他一些有用的前置条件和后置条件已在扩展 WebDAV 的其他规范中定义, 例如 [RFC3744] (特别参见第 7.1.1 节)、[RFC3253] 和 [RFC3648]。
所有这些元素都在 "DAV:" 命名空间中。除非另有说明, 否则每个条件的 XML 元素的内容定义为空。
lock-token-matches-request-uri
名称 (Name): lock-token-matches-request-uri
使用 (Use with): 409 Conflict
目的 (Purpose): (前置条件) -- 请求可以包含 Lock-Token 头来标识 UNLOCK 方法的锁。但是, 如果 Request-URI 不在令牌标识的锁范围内, 服务器应该使用此错误。锁可能具有不包括 Request-URI 的范围, 或者锁可能已消失, 或者令牌可能无效。
lock-token-submitted
名称 (Name): lock-token-submitted (前置条件)
使用 (Use with): 423 Locked
目的 (Purpose): 请求无法成功, 因为应该提交锁令牌。如果存在此元素, 则必须包含至少一个阻止请求的已锁定资源的 URL。在涉及集合锁的 MOVE、COPY 和 DELETE 情况下, 客户端可能很难找出哪个已锁定的资源导致请求失败 -- 但服务器只负责返回一个这样的已锁定资源。如果服务器知道所有阻止请求成功的已锁定资源, 则可以返回所有这些资源。
<!ELEMENT lock-token-submitted (href+) >
no-conflicting-lock
名称 (Name): no-conflicting-lock (前置条件)
使用 (Use with): 通常为 423 Locked
目的 (Purpose): LOCK 请求由于存在已经存在的冲突锁而失败。请注意, 尽管请求所针对的资源仅被间接锁定, 但锁也可能存在冲突。在这种情况下, 前置条件代码可用于通知客户端关于冲突锁根源的资源, 避免单独查找 "lockdiscovery" 属性。
<!ELEMENT no-conflicting-lock (href)* >
no-external-entities
名称 (Name): no-external-entities
使用 (Use with): 403 Forbidden
目的 (Purpose): (前置条件) -- 如果服务器因请求正文包含外部实体而拒绝客户端请求, 服务器应该使用此错误。
preserved-live-properties
名称 (Name): preserved-live-properties
使用 (Use with): 409 Conflict
目的 (Purpose): (后置条件) -- 服务器收到了原本有效的 MOVE 或 COPY 请求, 但无法在目标位置维护具有相同行为的活动属性。可能是服务器仅在存储库的某些部分支持某些活动属性, 或者只是出现内部错误。
propfind-finite-depth
名称 (Name): propfind-finite-depth
使用 (Use with): 403 Forbidden
目的 (Purpose): (前置条件) -- 此服务器不允许对集合进行无限深度的 PROPFIND 请求。
cannot-modify-protected-property
名称 (Name): cannot-modify-protected-property
使用 (Use with): 403 Forbidden
目的 (Purpose): (前置条件) -- 客户端尝试在 PROPPATCH 中设置受保护的属性 (例如 DAV:getetag)。另请参见 [RFC3253] 第 3.12 节。