8. 一般请求和响应处理
8.1 错误处理优先级
服务器必须优先返回授权错误而不是其他错误。这样可以避免泄漏有关受保护资源的信息 (例如,客户端通过查看匿名请求对资源的 423 锁定响应来发现隐藏资源存在)。
8.2 XML 的使用
在 HTTP/1.1 中,method 参数信息专门编码在 HTTP 头中。不同于 HTTP/1.1,WebDAV 的 method 参数信息有可能被编码在 XML([REC-XML]) 格式的请求 body 中,也有可能在 HTTP header 中。使用 XML 来编码方法参数的出发点是能够向现有结构中添加额外的 XML 元素从而提供可扩展性,以及 XML 以 iso10646 字符集编码的能力,提供国际化支持。
除了对 method 参数进行编码外,WebDAV 还使用 XML 对服务器的响应进行编码,从而同时为请求和响应的输出和输入提供 XML 的可扩展性和国际化优势。当 XML 用于请求或响应主体时,内容类型类型应该是 application/xml。具体实现的时候必须同时接受 text/xml 和 application/xml 作为请求和响应主体中的格式,但是 text/xml 格式已被废弃。
所有 DAV 兼容的客户端和资源都必须使用符合[RCE-XML]和[REC-XML-NAMES]标准的的 XML 解析器。在请求或响应中使用的所有 XML 至少要求格式良好、并正确使用命名空间。如果服务器接收到的 XML 存在格式问题,那么服务器必须用 400(Bad Request) 来拒绝这个请求。如果客户端接收到的 XML 不是格式良好的,那么客户端一定不要对执行结果进行任何假设,而应该视作服务器故障。
请注意,处理不受信任的来源提交的 XML 可能会导致涉及隐私、安全性和服务质量 (参见第 20 节) 等方面的风险。服务器可能会拒绝有问题的请求 (即使它们由格式良好的 XML 组成),例如,用一个 400(Bad Request) 状态码和一个可选的响应 body 来解释问题。
8.3 URL 处理
URL 出现在请求和响应中的许多位置。使用[RFC2518]的互操作经验表明,许多客户端解析多状态 (Multi-Status) 响应的时候并没有完全实现[RFC3986]第 5 节中定义的完整内容。因此,服务器在响应 URL 时需要特别小心,以确保客户机有足够的上下文信息来解析所有 url。本节中的规则不仅适用于多状态响应中'href'元素中的资源 url,也适用于 Destination header 和 If header 中的资源 url。 发送方可以在两种方法中进行选择:使用相对引用 (以被请求 URI 为起点进行解析),或者使用完整的 URI。服务器必须确保多状态响应中的每个'href'值都使用相同的格式。
WebDAV 在其扩展中只使用一种形式的相对引用,即绝对路径。
Simple-ref = absolute-URI | ( path-absolute [ "?" query ] )absolute-URI, path-absolute 和 query 均在[RFC3986]的 4.3、3.3 和 3.4 节中进行了定义。
使用 Simple-ref 格式,发送者不得出现以下情况:
- 使用点段 (“.”或“..”),或
- 拥有与请求 URI 不匹配的前缀 (使用[RFC2616]3.2.3 节中定义的比较规则)。
集合的标识符应该以'/'字符结束。
8.3.1 示例 - 正确的 URL 处理
现有集合 http://example.com/sample/ 和内部成员 URL http://example.com/sample/a test,通过 PROPFIND 请求如下:
请求内容:
PROPFIND /sample/ HTTP/1.1
Host: example.com
Depth: 1在这种情况下,服务器应该返回两个'href'元素,可以是下面任一格式
- 'http://example.com/sample/' 和 'http://example.com/sample/a test',或
- '/sample/'和'/sample/a%20test'
请注意,即使服务器可能将内部成员资源存储为“a test”,当在 URI 引用中使用时,它必须是被编码的 (参见[RFC3986]的 2.1 节)。还要注意,合法的 URI 可能仍然包含需要在 XML 字符数据中转义的字符,如&字符。
8.4 请求中需要的主体
这些新 methods 中的一部分不会定义 body 主体。但是服务器必须检查所有请求的 body,即使在方法不需要 body 主体的情况下也是如此,以防止出现一个请求 body 分明存在但却被服务器忽略的情况。服务器必须拒绝 415(不支持的媒体类型) 请求,这将告知客户端 (可能正在尝试使用扩展) 不能按客户端预期的方式处理主体。
8.5 WebDAV 中使用的 HTTP 报头
HTTP 定义了许多可以用在 WebDAV 请求和响应中的报头。并不是所有的这些报头都适用于所有情况,有些互动可能是未被定义的。请注意,HTTP 1.1 要求在所有可能的响应中使用 Date header(参见 14.18 节[RFC2616])。
在检查任何 HTTP 报头之前,服务器必须先进行授权检查。
8.6 ETag
HTTP 1.1 建议使用 ETags 而不是修改日期来用于缓存控制。除此之外我们还有更好的理由:在分布式创作环境中,为了避免更新丢失问题,ETag 和锁都是必要的,客户端有时候可能会无法更新锁,例如,当锁超时时,客户端意外脱机了或正在较长的上传过程中。当这种情况发生时,很有可能资源仍然可以被重新锁定(因为原来的锁已经超时),用户可以继续编辑,只要在此期间没有任何其它更改。客户端需要 ETag 来区分这种情况,否则,客户端将被迫询问用户是否要覆盖服务器上的资源,甚至无法告诉用户资源是否已经更改。时间戳几乎不能像 ETag 那样解决这个问题。
在编写用例时,强 ETag 比弱 ETag 更有用 (参见[RFC2616] 13.3.3 节)。语义等价可能是一个有用的概念,但这取决于文档类型和应用程序类型,互操作性可能需要一些超出本规范和 HTTP 范围的协议或标准来协助。还要注意弱 ETag 在 HTTP 中有一定的限制,例如不能用于 If-Match header。
注意,PUT 响应中 ETag 的意义并没有被本文档或者 RFC2616 所明确定义,也就是说,无论 ETag 意味着资源是完全等效于 PUT 请求的 body,还是服务器已经对格式或者内容进行了微调,这是一个 HTTP 的问题,而不是纯粹的 WebDAV 问题。
因为如果 ETag 发生变化,客户端可能会被迫提示用户或丢弃更改的内容,所以 WebDAV 服务器不应该为 body 和位置不变的资源修改 ETag(或最后修改时间)。ETag 表示资源的 body 或内容的状态。没有其它类似的方法来判断属性是否发生了变化。
8.7 包含错误响应体
HTTP 和 WebDAV 没有将大多数错误响应的 body 用于机器解析信息,直到 WebDAV 版本扩展规范 ([RFC3253]第 1.6 节) 引入了一种机制,在错误响应 body 中包含更多具体的信息。错误体 (Error Body) 机制适用于任何可能采用错误 body 但尚未有错误定义的错误响应。
这一机制特别适合状态代码可能有多种意思的情况,例如,400(Bad Request) 可能意味着缺少所需的 header、header 格式不正确、或者更多。第 16 节将介绍这种错误体机制。
8.8 命名空间操作对缓存验证器的影响
请注意,HTTP 响应中的“ETag header”和“Last-Modified header”(参见 RFC2616,章节 14.19 和 14.29) 是根据每个 URL(而不是每个资源) 定义的,并被客户端用于缓存。因此,服务器必须确保执行任何影响 URL 名称空间的操作时 (如 MOVE、COPY、DELETE、PUT 或 MKCOL) 都能保留它们的语义,特别是:
对于任何给定的 URL,“Last-Modified”的值必须在每次 GET 返回的内容存在改变时 (在时间戳的限制内) 进行更新。
对于任何给定的 URL,“ETag”值不能被复用于 GET 返回的不同展示。
在实践中,这意味着服务器:
可能要为命名空间操作中的目标命名空间内每个资源更新“Last-Modified”时间戳,除非它可以有选择性,
类似地,可能必须为这些资源重新分配“ETag”值 (除非服务器以另一种方式分配实体标签,以使它们在服务器管理的整个 URL 命名空间中是唯一的)。
请注意,这些注意事项也适用于特定的用例,例如使用 PUT 在一个 URL 上创建一个曾经被映射过后又被删除的新资源。
最后,继承 HTTP header 语义的 WebDAV 属性 (如 DAV:getetag 和 DAV: getlastmodified) 必须表现出相应的行为。