# 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%20test ,通过PROPFIND请求如下:
请求内容:
PROPFIND /sample/ HTTP/1.1
Host: example.com
Depth: 1
2
3
在这种情况下,服务器应该返回两个'href'元素,可以是下面任一格式
- 'http://example.com/sample/' 和 'http://example.com/sample/a%20test' ,或
- '/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)必须表现出相应的行为。