跳到主要内容

RFC 4918 - HTTP 扩展: Web 分布式创作和版本控制 (WebDAV)

  • 状态: Proposed Standard
  • 发布日期: 2007 年 6 月
  • Stream: IETF
  • 废弃了: RFC2518
  • 勘误: 无勘误

摘要 (Abstract)​

Web 分布式创作和版本控制 (Web Distributed Authoring and Versioning, WebDAV) 由一组辅助 HTTP/1.1 的方法, 头部和 content-type 组成, 用于管理资源属性, 创建和管理资源集合, 操作 URL 命名空间, 以及执行资源锁定 (冲突避免).

RFC 2518 发布于 1999 年 2 月. 本规范基于互操作性经验作出少量修订, 并废弃 RFC 2518.


本备忘录状态 (Status of This Memo)​

本文档为互联网社区规定了一个 Internet 标准路线协议, 并请求讨论和改进建议. 关于此协议的标准化阶段和状态, 请参考当前版本的 "Internet Official Protocol Standards" (STD 1). 本备忘录的分发不受限制.


Copyright (C) The IETF Trust (2007).


WebDAV 核心概念 (Core WebDAV Concepts)​

关键特性 (Key Features)​

WebDAV 使用以下核心能力扩展 HTTP/1.1 协议:

  1. 属性 (Properties): 为 Web 资源添加, 修改和查询元数据
  2. 集合 (Collections): 创建和管理资源的层次结构
  3. 锁定 (Locking): 防止并发编辑冲突, 支持排他锁和共享锁
  4. 命名空间操作 (Namespace Operations): 复制和移动 Web 资源

新增 HTTP 方法 (New HTTP Methods)​

  • PROPFIND: 检索资源属性
  • PROPPATCH: 修改资源属性
  • MKCOL: 创建集合 (类似于创建目录)
  • COPY: 复制资源或集合
  • MOVE: 移动或重命名资源或集合
  • LOCK: 锁定资源以防止冲突
  • UNLOCK: 解锁资源

新增 HTTP 状态码 (New HTTP Status Codes)​

  • 207 Multi-Status: 用于批量操作的多状态响应
  • 422 Unprocessable Entity: 请求格式良好, 但包含语义错误
  • 423 Locked: 资源已被锁定
  • 424 Failed Dependency: 请求因先前请求失败而失败
  • 507 Insufficient Storage: 存储空间不足, 无法完成请求

使用场景 (Use Cases)​

  • 协同编辑 (Collaborative Editing): 多个用户同时编辑 Web 内容
  • 内容管理系统 (Content Management Systems, CMS): 远程管理网站内容
  • 文件共享 (File Sharing): 通过 HTTP 协议上传和下载文件
  • 云存储 (Cloud Storage): 实现基于 HTTP 的文件存储服务



1. 简介 (Introduction)​

本文档描述了HTTP/1.1协议的扩展,允许客户端执行远程Web内容创作操作.该扩展提供了一组连贯的方法,头部,请求实体主体格式和响应实体主体格式,支持以下操作:

属性 (Properties): 创建,删除和查询Web页面信息的能力,如作者,创建日期等.

集合 (Collections): 创建文档集合并检索分层成员列表的能力(类似文件系统中的目录列表).

锁定 (Locking): 防止多人同时处理一个文档的能力.这可以防止"丢失更新问题",即当第一个作者和第二个作者先后写入更改而未合并彼此的更改时,修改会丢失.

命名空间操作 (Namespace Operations): 指示服务器复制和移动Web资源的能力,这些操作改变了URL到资源的映射.

这些操作的需求和原理在配套文档"分布式创作和版本控制协议的需求"[RFC2291]中进行了描述.

本文档未指定[RFC2291]建议的版本控制操作.该工作在单独的文档"WebDAV的版本控制扩展"[RFC3253]中完成.

以下各节详细介绍了各种WebDAV抽象:资源属性(第4节),资源集合(第5节),通用锁定(第6节)以及特定的写锁定(第7节).

这些抽象通过WebDAV特定的HTTP方法(第9节)和与WebDAV方法一起使用的额外HTTP头部(第10节)进行操作.WebDAV中处理HTTP请求和响应的一般考虑因素在第8节中介绍.

虽然HTTP/1.1提供的状态码足以描述WebDAV方法遇到的大多数错误条件,但有些错误无法完全归入现有类别.本规范定义了为WebDAV方法开发的额外状态码(第11节),并描述了WebDAV中使用的现有HTTP状态码(第12节).由于某些WebDAV方法可能对多个资源进行操作,因此引入了多状态响应(Multi-Status,第13节)来返回多个资源的状态信息.最后,此版本的WebDAV在错误响应主体中引入了前置条件和后置条件(第16节)XML元素.

WebDAV使用XML([REC-XML])作为属性名称和某些值,还使用XML来编组复杂的请求和响应.本规范包含所有属性(第15节)和编组中使用的所有其他XML元素(第14节)的DTD和文本定义.WebDAV包含一些关于以向后兼容的方式扩展WebDAV XML编组的特殊规则(第17节).

规范的最后几节涉及资源符合本规范的含义(第18节),国际化支持(第19节)以及安全性(第20节).


2. 符号约定 (Notational Conventions)​

由于本文档描述了一组HTTP/1.1协议的扩展,因此用于描述协议元素的增强BNF与[RFC2616]第2.1节中描述的完全相同,包括关于隐式线性空白的规则.由于这种增强BNF使用[RFC2616]第2.2节中提供的基本生成规则,因此这些规则也适用于本文档.请注意,这不是其他RFC中使用的标准BNF语法.

本文档中的关键词"MUST","MUST NOT","REQUIRED","SHALL","SHALL NOT","SHOULD","SHOULD NOT","RECOMMENDED","MAY"和"OPTIONAL"应按[RFC2119]中的描述进行解释.

注意,在自然语言中,"DAV:" XML命名空间中的属性(如"creationdate"属性)有时为了简洁而称为"DAV:creationdate".


3. 术语 (Terminology)​

本节定义了WebDAV规范中使用的关键术语.

URI/URL​

URI (统一资源标识符,Uniform Resource Identifier)和URL (统一资源定位符,Uniform Resource Locator).这些术语(以及它们之间的区别)在[RFC3986]中定义.

URI/URL映射 (URI/URL Mapping)​

绝对URI与资源之间的关系.由于资源可以表示网络可检索和不可检索的项目,因此资源可以具有零个,一个或多个URI映射.将资源映射到"http"方案URI使得可以使用该URI向资源提交HTTP协议请求.

路径段 (Path Segment)​

非正式地说,URI中斜杠("/")之间的字符.正式定义见[RFC3986]第3.3节.

集合 (Collection)​

非正式地说,也充当子资源引用容器的资源.正式地说,包含路径段和资源之间的映射集并满足第5节中定义的要求的资源.

内部成员 (Internal Member,集合的)​

非正式地说,集合的子资源.正式地说,由集合中包含的路径段映射引用的资源.

内部成员URL (Internal Member URL,集合的)​

内部成员的URL,由集合的URL(包括尾部斜杠)加上标识内部成员的路径段组成.

成员 (Member,集合的)​

非正式地说,集合的"后代".正式地说,集合的内部成员,或递归地说,内部成员的成员.

成员URL (Member URL,集合的)​

既是集合本身的内部成员URL,又是该集合成员的内部成员URL的URL.

属性 (Property)​

包含有关资源的描述性信息的名称/值对.

活属性 (Live Property)​

语义和语法由服务器强制执行的属性.例如,活属性DAV:getcontentlength的值(GET请求返回的实体长度)由服务器自动计算.

死属性 (Dead Property)​

语义和语法不由服务器强制执行的属性.服务器仅记录死属性的值;客户端负责维护死属性的语法和语义的一致性.

主体 (Principal)​

发起对网络资源访问的独特人类或计算参与者.

状态令牌 (State Token)​

表示资源状态的URI.锁令牌是本规范中定义的唯一状态令牌.


4. 资源属性的数据模型 (Data Model for Resource Properties)​

4.1 资源属性模型 (The Resource Property Model)​

属性是描述资源状态的数据片段.属性是关于数据的数据.

在分布式创作环境中使用属性来提供资源的高效发现和管理.例如,'subject'属性可能允许按主题对所有资源进行索引,'author'属性可能允许发现哪些作者编写了哪些文档.

DAV属性模型由名称/值对组成.属性的名称标识属性的语法和语义,并提供引用其语法和语义的地址.

属性有两类:"活"属性和"死"属性.活属性的语法和语义由服务器强制执行.活属性包括以下情况:a)属性的值由服务器保护和维护,b)属性的值由客户端维护,但服务器对提交的值执行语法检查.给定活属性的所有实例必须符合与该属性名称关联的定义.死属性的语法和语义由客户端强制执行;服务器仅逐字记录属性的值.

4.2 属性和HTTP头 (Properties and HTTP Headers)​

属性在有限的意义上已经存在于HTTP消息头中.然而,在分布式创作环境中,需要相对大量的属性来描述资源的状态,通过HTTP头设置/返回所有属性是低效的.因此,需要一种机制允许主体识别其感兴趣的一组属性,并仅设置或检索这些属性.

4.3 属性值 (Property Values)​

属性的值始终是(格式良好的)XML片段.

选择XML是因为它是一种灵活的,自描述的,结构化的数据格式,支持丰富的模式定义,并且支持多个字符集.XML的自描述性质允许通过添加元素来扩展任何属性的值.客户端在遇到扩展时不会中断,因为它们仍然拥有原始模式中指定的数据,并且必须忽略它们不理解的元素.

XML对多个字符集的支持允许以用户熟悉的字符集对任何人类可读的属性进行编码和读取.XML对多种人类语言的支持(使用"xml:lang"属性)处理了同一字符集被多种人类语言使用的情况.请注意,xml:lang的作用域是递归的,因此包含属性名称元素的任何元素上的xml:lang属性都适用于属性值,除非它已被更局部作用域的属性覆盖.请注意,一个属性只有一种语言的一个值(或可以不定义语言);一个属性不具有不同语言的多个值或多种语言的单个值.

属性始终用由属性名称组成的XML元素表示,称为"属性名称元素".最简单的例子是空属性,这与不存在的属性不同:

<R:title xmlns:R="http://www.example.com/ns/"><R:title>

属性的值出现在属性名称元素内部.该值可以是任何类型的格式良好的XML内容,包括纯文本和混合内容.服务器必须在存储和传输死属性时保留以下XML信息项(使用[REC-XML-INFOSET]中的术语):

对于属性名称元素信息项本身:

对于属性值中的所有元素信息项:

对于属性值中的属性信息项:

对于属性值中的字符信息项:

由于前缀在某些XML词汇表(例如XPath和XML Schema)中使用,服务器应该为值中的任何信息项保留:

上面未列出的XML Infoset属性可以由服务器保留,但客户端不得依赖它们被保留.除非另有定义,否则上述规则也将默认适用于活属性.

服务器必须忽略XML属性xml:space(如果存在),并且永远不要使用它来更改空白处理.属性值中的空白是有意义的.

4.3.1 示例 - 包含混合内容的属性 (Example - Property with Mixed Content)​

考虑客户端创建的死属性'author'如下:

<D:prop xml:lang="en" xmlns:D="DAV:">
<x:author xmlns:x='http://example.com/ns'>
<x:name>Jane Doe<x:name>
<!-- Jane's contact info -->
&lt;x:uri type='email'
added='2005-11-26'>mailto:[email protected]&lt;x:uri>
&lt;x:uri type='web'
added='2005-11-27'>http://www.example.com&lt;x:uri>
&lt;x:notes xmlns:h='http://www.w3.org/1999/xhtml'>
Jane has been working way &lt;h:em>too&lt;h:em> long on the
long-awaited revision of <![CDATA[&lt;RFC2518>]]>.
&lt;x:notes>
&lt;x:author>
&lt;D:prop>

请求此属性时,服务器可能返回:

&lt;D:prop xmlns:D='DAV:'>&lt;author
xml:lang='en'
xmlns:x='http://example.com/ns'
xmlns='http://example.com/ns'
xmlns:h='http://www.w3.org/1999/xhtml'>
&lt;x:name>Jane Doe&lt;x:name>
&lt;x:uri added="2005-11-26" type="email"
>mailto:[email protected]&lt;x:uri>
&lt;x:uri added="2005-11-27" type="web"
>http://www.example.com&lt;x:uri>
&lt;x:notes>
Jane has been working way &lt;h:em>too&lt;h:em> long on the
long-awaited revision of &lt;RFC2518&gt;.
&lt;x:notes>
&lt;/author>
&lt;D:prop>

在此示例中请注意:

  • 属性名称本身的[prefix]没有被保留,因为它不重要,而所有其他[prefix]值都已被保留,
  • 属性值已用双引号而不是单引号重写(引号样式不重要),并且属性顺序未被保留,
  • xml:lang属性已在属性名称元素本身上返回(设置属性时它在作用域内,但响应中的确切位置不被视为重要,只要它在作用域内),
  • 标签之间的空白已在所有地方保留(属性之间的空白则不然),
  • CDATA封装已替换为字符转义(反之亦然也是合法的),
  • 注释项已被剥离(处理指令项也会被剥离).

实现说明:在某些情况下(如编辑场景),客户端可能需要逐字符保留XML内容(如属性顺序或引号样式).在这种情况下,客户端应考虑使用纯文本属性值,方法是转义在XML解析中具有特殊含义的所有字符.

4.4 属性名称 (Property Names)​

属性名称是一个全局唯一标识符,与提供有关属性语法和语义信息的模式关联.

因为属性的名称是全局唯一的,所以客户端可以依赖于跨多个资源,在同一服务器和不同服务器上的特定属性的一致行为,只要该属性在相关资源上是"活"的,并且活属性的实现忠实于其定义.

XML命名空间机制(基于URI[RFC3986])用于命名属性,因为它可以防止命名空间冲突并提供不同程度的管理控制.

属性命名空间是扁平的;也就是说,没有明确识别属性的层次结构.因此,如果资源上存在属性A和属性A/B,则不识别两个属性之间的任何关系.预计最终将产生一个单独的规范来解决与分层属性相关的问题.

最后,不可能在单个资源上两次定义相同的属性,因为这会导致资源属性命名空间中的冲突.

4.5 源资源和输出资源 (Source Resources and Output Resources)​

某些HTTP资源由服务器动态生成.对于这些资源,可能存在某处的源代码控制该资源的生成方式.源文件与输出HTTP资源的关系可能是一对一,一对多,多对一或多对多.HTTP中没有机制来确定资源是否是动态的,更不用说其源文件的存在位置或如何创作它们.尽管解决这个问题会很有用,但可互操作的WebDAV实现已被广泛部署,而实际上并没有解决这个问题,只是处理静态资源.因此,源与输出问题在本规范中没有解决,已推迟到单独的文档中.


5. Web资源集合 (Collections of Web Resources)​

本节描述了一种Web资源类型——集合,并讨论了它与HTTP URL命名空间和HTTP方法的交互.集合资源的目的是在服务器的命名空间中对类似集合的对象(例如文件系统目录)进行建模.

所有符合DAV的资源必须支持本文指定的HTTP URL命名空间模型.

5.1 HTTP URL命名空间模型 (HTTP URL Namespace Model)​

HTTP URL命名空间是一个分层命名空间,其中层次结构由"/"字符分隔.

如果HTTP URL命名空间满足以下条件,则称其是一致的:对于HTTP层次结构中的每个URL,都存在一个包含该URL作为内部成员URL的集合.所考虑的命名空间的根或顶级集合不受前一规则的约束.所考虑的命名空间的顶级集合不一定是由绝对路径'/'标识的集合——它可能由一个或多个路径段标识(例如,/servlets/webdav/...).

HTTP/1.1和WebDAV都不要求整个HTTP URL命名空间是一致的——与WebDAV兼容的资源可能没有父集合.但是,某些WebDAV方法被禁止产生导致命名空间不一致的结果.

正如[RFC2616]和[RFC3986]中所隐含的,任何资源(包括集合资源)都可以由多个URI标识.例如,一个资源可以由多个HTTP URL标识.

5.2 集合资源 (Collection Resources)​

集合资源与其他资源的不同之处在于它们也充当容器.某些HTTP方法仅适用于集合,但有些方法适用于集合定义的容器内的部分或全部资源.当方法的范围不清楚时,客户端可以指定要应用的深度.深度可以是零级(仅集合),一级(集合和直接包含的资源)或无限级(集合和递归包含的所有资源).

集合的状态至少包括一组路径段和资源之间的映射,以及集合本身的一组属性.在本文档中,如果存在映射到B的路径段映射并且该映射包含在A中,则称资源B包含在集合资源A中.一个集合对于给定的路径段最多只能包含一个映射,即,让同一路径段映射到多个资源是非法的.

在集合上定义的属性的行为与非集合资源上的属性完全相同.集合可以具有其他状态,例如GET返回的实体主体.

对于所有符合 WebDAV 的资源 A 和 B, 分别由 URL "U" 和 "V" 标识, 且 "V" 等于 "U/SEGMENT", A 必须是包含从 "SEGMENT" 到 B 的映射的集合. 因此, 如果 URL 为 http://example.com/bar/blah 的资源 B 符合 WebDAV, 并且 URL 为 http://example.com/bar/ 的资源 A 符合 WebDAV, 则资源 A 必须是一个集合, 并且必须恰好包含一个从 "blah" 到 B 的映射.

尽管通常映射由单个段和资源组成,但一般来说,映射由一组段和资源组成.这允许服务器将一组段视为等效的(即,要么所有段都映射到同一资源,要么所有段都不映射到资源).例如,对段执行大小写折叠的服务器会将段"ab","Ab","aB"和"AB"视为等效.然后,客户端可以使用这些段中的任何一个来标识资源.请注意,PROPFIND结果将选择这些等效段之一来标识映射,因此每个映射将有一个PROPFIND响应元素,而不是映射中每个段一个.

集合资源可以在HTTP URL命名空间层次结构中具有到非WebDAV兼容资源的映射,但不是必须这样做.例如,如果URL为http://example.com/bar/blah的资源X不符合WebDAV,并且URL为http://example.com/bar/的资源A标识WebDAV集合,则A可能有也可能没有从"blah"到X的映射.

如果符合WebDAV的资源在HTTP URL命名空间层次结构中没有符合WebDAV的内部成员,则该符合WebDAV的资源不需要是集合.

有一个长期约定,即当通过不带尾部斜杠的名称引用集合时,服务器可以像存在尾部斜杠一样处理请求.在这种情况下,它应该在响应中返回一个Content-Location头,指向以"/"结尾的URL.例如,如果客户端在http://example.com/blah(无尾部斜杠)上调用方法,服务器可以像操作在http://example.com/blah/(尾部斜杠)上调用一样响应,并且应该返回值为http://example.com/blah/的Content-Location头.无论服务器在何处生成引用集合的URL,服务器都应该包含尾部斜杠.一般来说,客户端应该使用集合名称的尾部斜杠形式.如果客户端不使用尾部斜杠形式,客户端需要准备好看到重定向响应.客户端会发现DAV:resourcetype属性比URL更可靠,可以找出资源是否是集合.

客户端必须能够支持WebDAV资源包含在非WebDAV资源内的情况.例如,如果来自http://example.com/servlet/dav/collection的OPTIONS响应指示WebDAV支持,客户端不能假设http://example.com/servlet/dav/或其父级必然是WebDAV集合.

映射URL不作为其父集合成员出现的典型情况是服务器允许链接或重定向到非WebDAV资源的情况.例如,"/col/link"可能不会作为"/col/"的成员出现,尽管服务器会对"/col/link"的GET请求响应302状态;因此,URL"/col/link"确实会被映射.类似地,动态生成的页面可能具有来自"/col/index.html"的URL映射,因此此资源可能对GET请求响应200 OK,但不作为"/col/"的成员出现.

甚至一些到WebDAV兼容资源的映射可能不会出现在父集合中.这种情况的一个例子是支持每个WebDAV兼容资源的多个别名URL的服务器.服务器可以实现不区分大小写的URL,因此"/col/a"和"/col/A"标识同一资源,但在列出"/col/"的成员时仅报告"a"或"A"中的一个.在服务器将一组段视为等效的情况下,服务器必须在PROPFIND响应中仅公开每个映射一个一致选择的首选段.


6. 锁定 (Locking)​

锁定资源的能力提供了一种序列化访问该资源的机制.使用锁,创作客户端可以合理地保证在编辑资源时其他主体不会修改该资源.通过这种方式,客户端可以防止"丢失更新"问题.

本规范允许锁在两个客户端指定的参数上变化:涉及的主体数量(独占锁与共享锁)以及要授予的访问类型.本文档仅定义了一种访问类型的锁定:写入.但是,语法是可扩展的,允许最终为其他访问类型指定锁定.

6.1 锁模型 (Lock Model)​

本节提供了WebDAV锁定的非规范性描述.

锁由锁令牌标识.锁令牌是URL,可以通过HTTP传输.锁令牌仅与一个锁关联.

锁可以是独占的或共享的.锁的类型决定了服务器如何处理对锁定资源的请求:

独占锁 (Exclusive Lock):

  • 只有创建锁的主体才能修改资源
  • 阻止任何其他主体获得冲突的锁

共享锁 (Shared Lock):

  • 多个主体可以持有共享锁
  • 所有持有共享锁的主体都可以修改资源
  • 阻止不持有锁的主体修改资源

锁可以具有不同的范围:

  • 直接锁 (Direct Lock): 锁直接应用于资源
  • 深度锁 (Depth Lock): 锁应用于资源及其所有成员

对于集合,可以指定深度:

  • Depth: 0: 仅锁定集合本身
  • Depth: infinity: 锁定集合及其所有成员(递归)

6.2 独占锁与共享锁 (Exclusive vs. Shared Locks)​

最常见的锁类型是独占锁.独占锁的目的是强制执行特定主体的编辑策略.独占锁的常见用途是防止不同的主体在长时间的创作会话期间修改资源.

共享锁旨在支持协作创作,其中一组主体需要同时修改资源.共享锁的关键特征是多个主体可以持有共享锁,但独占锁排除所有其他锁.

锁兼容性表 (Lock Compatibility Table):

当前状态共享锁请求独占锁请求
无✅ True✅ True
共享锁✅ True❌ False
独占锁❌ False❌ False

6.3 必需支持 (Required Support)​

服务器必须支持独占写锁.

服务器可以支持共享写锁.如果服务器不支持共享写锁,当客户端请求共享写锁时,服务器必须返回错误.

6.4 锁创建者和特权 (Lock Creator and Privileges)​

锁与创建锁的主体关联.只有具有适当锁令牌的主体才能解锁资源.这确保了锁创建者对锁的生命周期有控制权.

创建锁的主体需要具有在资源上创建锁的特权.具体的特权要求由服务器的访问控制策略确定.

6.5 锁令牌 (Lock Tokens)​

锁令牌是唯一标识锁的URL.锁令牌通常使用opaquelocktoken: URI方案(见附录C).

锁令牌特征 (Lock Token Characteristics):

  • 全局唯一性 (Global Uniqueness): 每个锁令牌都是全局唯一的
  • 不可预测性 (Unpredictability): 锁令牌应该是不可预测的,以防止未经授权的访问
  • URL格式 (URL Format): 锁令牌是有效的URL

锁令牌示例 (Example Lock Token):

opaquelocktoken:f81d4fae-7dec-11d0-a765-00a0c91e6bf6

客户端通过以下方式提交锁令牌:

  • 在If头中包含锁令牌
  • 在Lock-Token头中包含锁令牌(仅用于UNLOCK方法)

6.6 锁超时 (Lock Timeout)​

锁具有有限的生命周期.服务器为每个锁分配一个超时值,之后锁会自动过期.

超时特征 (Timeout Characteristics):

  • 客户端可以在Timeout请求头中建议超时值
  • 服务器可以忽略客户端的建议并分配自己的超时值
  • 服务器必须在锁响应中返回实际的超时值
  • 客户端可以通过刷新锁来延长锁的生命周期

超时格式 (Timeout Format):

Timeout: Second-4100
Timeout: Infinite

最佳实践 (Best Practices):

  • 服务器应该允许客户端刷新锁
  • 客户端应该定期刷新长期锁
  • 客户端应该在编辑完成时解锁资源

6.7 锁能力发现 (Lock Capability Discovery)​

在尝试锁定资源之前,客户端可以使用OPTIONS方法发现服务器的锁定能力.响应中的DAV头指示服务器的WebDAV合规性类别,其中包括锁定支持.

6.8 活动锁发现 (Active Lock Discovery)​

客户端可以使用PROPFIND方法检索DAV:lockdiscovery属性来发现资源上的活动锁.此属性包含有关资源上所有活动锁的信息,包括锁类型,范围,深度,所有者,超时和锁令牌.


7. 写锁 (Write Lock)​

本节描述写锁,这是本规范中定义的唯一锁类型.写锁是授予锁所有者修改资源权利的锁.锁所有者是创建锁的主体.

7.1 写锁和属性 (Write Locks and Properties)​

虽然没有写锁的人不能更改资源的内容,但他们可以修改资源的死属性.例如,这允许主体在不需要写访问权限的情况下向锁定的资源添加注释.

活属性通常具有由服务器强制执行的语义.因此,服务器可以自行决定是否以及如何允许在资源被锁定时更改活属性.例如,即使资源被锁定,服务器也可以允许修改活属性.

7.2 避免丢失更新 (Avoiding Lost Updates)​

写锁的目的是防止丢失更新.当多个主体在没有协调的情况下尝试修改资源时,会发生丢失更新,导致一个或多个主体的更改被后续更新覆盖.

写锁提供了序列化机制:只有锁持有者可以修改锁定的资源.这通过确保修改按顺序而不是并发发生来防止丢失更新问题.

丢失更新场景示例 (Example Lost Update Scenario) (无锁定):

  1. 用户A检索资源版本1
  2. 用户B检索资源版本1
  3. 用户A修改并保存 → 创建版本2
  4. 用户B修改(基于版本1)并保存 → 创建版本3,覆盖A的更改

使用写锁 (With Write Lock):

  1. 用户A锁定资源
  2. 用户B尝试修改 → 收到423 Locked错误
  3. 用户A修改并解锁
  4. 用户B现在可以锁定和修改

7.3 写锁和未映射的URL (Write Locks and Unmapped URLs)​

对未映射URL的成功LOCK请求会创建一个被锁定的空资源.此机制允许客户端在创建资源内容之前保留URL.

创建锁定的空资源时:

  • 资源没有内容(零长度实体)
  • 资源使用指定的锁锁定
  • 后续的 PUT 或 MKCOL 可以向资源添加内容
  • 必须在PUT或MKCOL请求中提交锁令牌

此"锁空资源 (lock-null resource)"机制在附录D中详细描述.

7.4 写锁和集合 (Write Locks and Collections)​

集合上的写锁锁定集合资源本身,防止修改集合的成员资格(添加或删除内部成员).

当深度无限锁应用于集合时:

  • 集合本身被锁定
  • 所有内部成员被锁定
  • 所有后代资源递归锁定
  • 添加到集合的新成员自动锁定

锁继承 (Lock Inheritance): 当新资源添加到锁定的集合(深度无限)时,新资源从父集合继承锁.

示例 (Example):

集合 /folder/ 使用 Depth: infinity 锁定
- 无法向 /folder/ 添加新成员
- 无法修改 /folder/file1.txt
- 无法删除 /folder/subfolder/
- 无法修改 /folder/subfolder/file2.txt

7.5 写锁和If请求头 (Write Locks and the If Request Header)​

客户端使用If请求头提交锁令牌.此头允许基于锁令牌存在的方法条件执行.

If头语法支持:

  • 单个锁令牌
  • 多个锁令牌(用于多个锁)
  • 标记列表(将令牌与特定URL关联)
  • NOT条件(要求不存在锁)

7.5.1 示例 - 写锁和COPY (Example - Write Lock and COPY)​

COPY /source HTTP/1.1
Host: example.com
Destination: http://example.com/destination
If: \`http://example.com/destination\` (&lt;opaquelocktoken:token123>)

此请求将/source复制到/destination,但仅当客户端持有/destination的锁令牌时.

7.5.2 示例 - 删除锁定集合的成员 (Example - Deleting a Member of a Locked Collection)​

DELETE /folder/file.txt HTTP/1.1
Host: example.com
If: \`http://example.com/folder/\` (&lt;opaquelocktoken:folder-token>)

要删除锁定集合的成员,客户端必须提交集合的锁令牌.

7.6 写锁和COPY/MOVE (Write Locks and COPY/MOVE)​

COPY方法在目标位置创建新资源.新资源不会自动锁定,即使源被锁定.锁不会被复制.

MOVE方法在语义上等同于COPY后跟DELETE.移动资源时,源上的锁被删除.目标不会自动锁定.

如果COPY或MOVE的目标被锁定,客户端必须提交适当的锁令牌来覆盖目标.

7.7 刷新写锁 (Refreshing Write Locks)​

锁具有有限的生命周期.为了防止过早的锁过期,客户端可以通过提交带有以下内容的LOCK请求来刷新锁:

  • If头中的相同锁令牌
  • 无请求主体(或空的lockinfo元素)

服务器响应新的超时值.锁刷新允许长期编辑会话而不会锁过期.

锁刷新示例 (Example Lock Refresh):

LOCK /resource HTTP/1.1
Host: example.com
If: (&lt;opaquelocktoken:token123>)
Timeout: Second-3600

服务器延长锁超时并返回新的过期时间.


8. 通用请求和响应处理 (General Request and Response Handling)​

8.1 错误处理中的优先级 (Precedence in Error Handling)​

服务器必须优先返回授权错误而不是其他错误.这避免了泄漏有关受保护资源的信息(例如,客户端通过对资源的匿名请求看到423 Locked响应来发现隐藏资源的存在).

8.2 XML的使用 (Use of XML)​

在HTTP/1.1中,方法参数信息专门在HTTP头中编码.与HTTP/1.1不同,WebDAV将方法参数信息编码在XML([REC-XML])请求实体主体或HTTP头中.使用XML编码方法参数的动机是能够向现有结构添加额外的XML元素,提供可扩展性;以及XML能够在ISO 10646字符集中编码信息,提供国际化支持.

除了编码方法参数外,WebDAV还使用XML编码方法的响应,为方法输出和输入提供XML的可扩展性和国际化优势.

当XML用于请求或响应主体时,Content-Type类型应该是application/xml.实现必须接受请求和响应主体中的text/xml和application/xml.不建议使用text/xml.

所有符合DAV的客户端和资源必须使用符合[REC-XML]和[REC-XML-NAMES]的XML解析器.请求或响应中使用的所有XML至少必须是格式良好的并正确使用命名空间.如果服务器收到格式不良的XML,则服务器必须以400(Bad Request)拒绝整个请求.如果客户端在响应中收到格式不良的XML,则客户端不得假设执行的方法的任何结果,并且应该将服务器视为故障.

请注意,处理不受信任来源提交的XML可能会导致与隐私,安全和服务质量相关的风险(见第20节).服务器可以拒绝可疑的请求(即使它们由格式良好的XML组成),例如,使用400(Bad Request)状态码和解释问题的可选响应主体.

8.3 URL处理 (URL Handling)​

URL出现在请求和响应的许多地方.与[RFC2518]的互操作性经验表明,许多解析Multi-Status响应的客户端没有完全实现[RFC3986]第5节中定义的完整引用解析.因此,特别是服务器需要小心处理响应中的URL,以确保客户端有足够的上下文来解释所有URL.本节中的规则不仅适用于Multi-Status响应中'href'元素中的资源URL,还适用于Destination和If头资源URL.

发送方在两种方法之间进行选择:使用相对引用(针对Request-URI解析),或完整URI.服务器必须确保Multi-Status响应中的每个'href'值使用相同的格式.

WebDAV在其扩展中仅使用一种形式的相对引用,即绝对路径.

Simple-ref = absolute-URI | ( path-absolute [ "?" query ] )

absolute-URI,path-absolute和query生成在[RFC3986]的第4.3,3.3和3.4节中定义.

在Simple-ref生成中,发送方不得:

  • 使用点段("."或".."),或
  • 具有与Request-URI不匹配的前缀(使用[RFC2616]第3.2.3节中定义的比较规则).

集合的标识符应该以'/'字符结尾.

####8.3.1 示例 - 正确的URL处理 (Example - Correct URL Handling)

考虑集合http://example.com/sample/,内部成员URL为http://example.com/sample/a%20test,以及下面的PROPFIND请求:

请求 (Request):

PROPFIND /sample/ HTTP/1.1
Host: example.com
Depth: 1

在这种情况下,服务器应该返回两个'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 请求中的必需主体 (Required Bodies in Requests)​

这些新方法中的一些没有定义主体.服务器必须检查所有请求的主体,即使不期望有主体.在存在请求主体但会被服务器忽略的情况下,服务器必须以415(Unsupported Media Type)拒绝请求.这通知客户端(可能一直在尝试使用扩展)主体无法按照客户端的意图进行处理.

8.5 WebDAV中使用的HTTP头 (HTTP Headers for Use in WebDAV)​

HTTP 定义了许多可以在 WebDAV 请求和响应中使用的 Header. 并非所有这些 Header 都适用于所有情况, 且某些交互可能未定义. 请注意, HTTP 1.1 要求在所有响应中尽可能使用 Date Header (见 [RFC2616] 第 14.18 节).

服务器必须在检查任何HTTP条件头之前进行授权检查.

8.6 ETag​

HTTP 1.1建议使用ETag而不是修改日期进行缓存控制,并且在创作中更有理由优先使用ETag.ETag的正确使用在分布式创作环境中更为重要,因为ETag与锁一起需要避免丢失更新问题.例如,当锁超时且客户端意外离线或正在进行长时间上传时,客户端可能无法续订锁.当客户端无法续订锁时,只要在此期间没有进行任何更改,资源仍然可以重新锁定,用户可以继续编辑.客户端需要ETag才能区分这种情况.否则,客户端被迫询问用户是否覆盖服务器上的资源,甚至无法告诉用户它是否已更改.时间戳解决这个问题的效果远不如ETag.

强ETag对于创作用例比弱ETag更有用(见[RFC2616]第13.3.3节).语义等效性可以是一个有用的概念,但这取决于文档类型和应用程序类型,互操作性可能需要本规范和HTTP范围之外的某些协议或标准.还要注意,弱ETag在HTTP中有某些限制,例如,这些不能在If-Match头中使用.

请注意,PUT响应中ETag的含义在本文档或RFC 2616中都没有明确定义(即,ETag是否意味着资源与PUT请求主体逐字节等效,或者服务器是否可能在存储时对文档的格式或内容进行了微小更改).这是HTTP问题,而不仅仅是WebDAV问题.

因为如果ETag更改,客户端可能被迫提示用户或丢弃已更改的内容,所以WebDAV服务器不应该更改具有未更改主体和位置的资源的ETag(或Last-Modified时间).ETag表示资源主体或内容的状态.没有类似的方法来判断属性是否已更改.

8.7 包含错误响应主体 (Including Error Response Bodies)​

HTTP和WebDAV直到WebDAV版本控制扩展规范引入了在错误响应主体中包含更具体信息的机制([RFC3253]第1.6节)之前,没有使用大多数错误响应的主体进行机器可解析的信息.错误主体机制适合与可能采用主体但尚未定义主体的任何错误响应一起使用.当状态码可能意味着许多事情时(例如,400 Bad Request可能意味着缺少必需的头,头格式不正确等等),该机制特别合适.此错误主体机制在第16节中介绍.

8.8 命名空间操作对缓存验证器的影响 (Impact of Namespace Operations on Cache Validators)​

请注意,HTTP响应头"Etag"和"Last-Modified"(见[RFC2616]第14.19和14.29节)是按URL(而不是按资源)定义的,并由客户端用于缓存.因此,服务器必须确保执行影响URL命名空间的任何操作(例如COPY,MOVE,DELETE,PUT或MKCOL)确实保留其语义,特别是:

  • 对于任何给定的URL,"Last-Modified"值必须在GET返回的表示每次更改时递增(在时间戳分辨率的限制内).
  • 对于任何给定的URL,"ETag"值不得用于GET返回的不同表示.

实际上,这意味着服务器

  • 可能必须为命名空间操作的目标命名空间内的每个资源递增"Last-Modified"时间戳,除非它可以更有选择地这样做,并且
  • 类似地,可能必须为这些资源重新分配"ETag"值(除非服务器以使它们在服务器管理的整个URL命名空间中唯一的方式分配实体标签).

请注意,这些考虑也适用于特定的用例,例如使用PUT在之前已映射但此后已删除的URL处创建新资源.


9. 分布式创作的HTTP方法 (HTTP Methods for Distributed Authoring)​

本章描述WebDAV定义的HTTP方法以及对现有HTTP方法的扩展.

WebDAV方法概述 (WebDAV Methods Overview)​

方法目的目标
PROPFIND检索资源属性资源或集合
PROPPATCH修改资源属性资源
MKCOL创建集合未映射URL
COPY复制资源源和目标
MOVE移动/重命名资源源和目标
LOCK锁定资源资源或集合
UNLOCK解锁资源锁定的资源

9.1 PROPFIND方法 (PROPFIND Method)​

PROPFIND检索Request-URI标识的资源上定义的属性.

请求类型 (Request Types):

  • propname: 检索所有属性名称
  • allprop: 检索所有属性
  • prop: 检索特定属性
  • allprop + include: 检索所有属性加上其他属性

请求示例 (Example Request):

PROPFIND /file HTTP/1.1
Host: example.com
Depth: 0
Content-Type: application/xml

&lt;?xml version="1.0" encoding="utf-8" ?>
&lt;D:propfind xmlns:D="DAV:">
&lt;D:prop>
&lt;D:displayname/>
&lt;D:getcontentlength/>
&lt;D:prop>
&lt;D:propfind>

响应 (Response): 207 Multi-Status,包含属性值

Depth头 (Depth Header):

  • Depth: 0 - 仅目标资源
  • Depth: 1 - 目标和直接成员
  • Depth: infinity - 目标和所有后代

9.2 PROPPATCH方法 (PROPPATCH Method)​

PROPPATCH修改资源上的属性.

操作 (Operations):

  • set: 创建或更新属性
  • remove: 删除属性

示例 (Example):

PROPPATCH /file HTTP/1.1
Host: example.com

&lt;?xml version="1.0" encoding="utf-8" ?>
&lt;D:propertyupdate xmlns:D="DAV:">
&lt;D:set>
&lt;D:prop>&lt;D:displayname>New Name&lt;D:displayname>&lt;D:prop>
&lt;D:set>
&lt;D:remove>
&lt;D:prop>&lt;D:author/>&lt;D:prop>
&lt;D:remove>
&lt;D:propertyupdate>

原子性 (Atomicity): 所有操作必须一起成功或失败.

9.3 MKCOL方法 (MKCOL Method)​

MKCOL在Request-URI处创建新的集合资源.

示例 (Example):

MKCOL /new-collection/ HTTP/1.1
Host: example.com

要求 (Requirements):

  • Request-URI 必须是未映射的 URL
  • 父集合必须存在
  • 请求主体应该为空(或可以包含内容类型信息)

状态码 (Status Codes):

  • 201 Created - 集合成功创建
  • 403 Forbidden - URL处已存在资源
  • 409 Conflict - 父集合不存在

9.4 集合的GET,HEAD (GET, HEAD for Collections)​

当应用于集合时, GET 和 HEAD 可以返回:

  • HTML目录列表
  • 集合成员列表
  • 空主体

行为是实现特定的.

9.5 集合的POST (POST for Collections)​

集合的POST用于添加成员.服务器确定新成员URL.

9.6 DELETE方法 (DELETE Method)​

DELETE删除Request-URI标识的资源.

对于集合 (For Collections):

  • 递归删除集合和所有成员
  • 如果省略Depth: infinity头,行为等同于Depth: infinity

部分失败 (Partial Failure): 如果任何成员的删除失败,整个操作失败(需要原子性).

9.7 PUT方法 (PUT Method)​

PUT创建或更新资源.

写锁交互 (Write Lock Interaction):

  • 如果目标被锁定,客户端必须在If头中提交适当的锁令牌
  • 如果在未映射的URL上使用了LOCK,则创建锁空资源

9.8 COPY方法 (COPY Method)​

COPY在目标位置创建源资源的副本.

头 (Headers):

  • Destination: 目标URL(必需)
  • Depth: 0或infinity(默认:infinity)
  • Overwrite: T(true)或F(false)(默认:T)

示例 (Example):

COPY /source HTTP/1.1
Host: example.com
Destination: http://example.com/dest
Overwrite: F
Depth: infinity

行为 (Behavior):

  • 复制资源内容和死属性
  • 活属性根据其定义处理
  • 集合复制是递归的(使用Depth: infinity)
  • 不复制锁

状态码 (Status Codes):

  • 201 Created - 目标已创建
  • 204 No Content - 目标已覆盖
  • 207 Multi-Status - 部分成功(某些成员失败)
  • 412 Precondition Failed - Overwrite: F且目标存在

9.9 MOVE方法 (MOVE Method)​

MOVE在逻辑上等同于COPY + DELETE.

示例 (Example):

MOVE /old-location HTTP/1.1
Host: example.com
Destination: http://example.com/new-location
Overwrite: T

行为 (Behavior):

  • 将资源移动到目标
  • 更新所有引用该资源的URL
  • 保留属性
  • 删除源上的锁
  • 移动后目标不被锁定

原子性 (Atomicity): MOVE操作必须是原子的(不分为COPY + DELETE).

9.10 LOCK方法 (LOCK Method)​

LOCK获取资源上的锁.

锁类型 (Lock Types):

  • 独占写锁 (Exclusive write lock): 只有一个主体可以持有
  • 共享写锁 (Shared write lock): 多个主体可以持有

示例 (Example):

LOCK /resource HTTP/1.1
Host: example.com
Timeout: Second-3600
Depth: 0

&lt;?xml version="1.0" encoding="utf-8" ?>
&lt;D:lockinfo xmlns:D="DAV:">
&lt;D:lockscope>&lt;D:exclusive/>&lt;D:lockscope>
&lt;D:locktype>&lt;D:write/>&lt;D:locktype>
&lt;D:owner>
&lt;D:href>http://example.com/user&lt;D:href>
&lt;D:owner>
&lt;D:lockinfo>

响应 (Response): 200 OK,包含lockdiscovery属性,其中包含锁令牌.

锁刷新 (Lock Refresh): 在If头中提交带有锁令牌的LOCK,无主体.

9.11 UNLOCK方法 (UNLOCK Method)​

UNLOCK删除由锁令牌标识的锁.

示例 (Example):

UNLOCK /resource HTTP/1.1
Host: example.com
Lock-Token: &lt;opaquelocktoken:a515cfa4-5da4-22e1-f5b5-00a0451e6bf7>

要求 (Requirements):

  • Lock-Token头必须包含锁令牌
  • 只有锁创建者或特权主体可以解锁

状态码 (Status Codes):

  • 204 No Content - 锁成功删除
  • 409 Conflict - 资源未被锁定
  • 423 Locked - 资源被不同的令牌锁定

有关完整的方法规范,错误处理和详细示例,请参阅RFC 4918第9.1-9.11节.


10. HTTP Headers for Distributed Authoring (用于分布式创作的HTTP头)​

WebDAV定义了几个新的HTTP头部,用于支持分布式创作功能.

10.1 DAV Header (DAV头)​

DAV头指示服务器支持的WebDAV功能级别.

语法​

DAV: 1, 2, 3, access-control, calendar-access

合规性级别​

  • 1: 基本WebDAV支持(PROPFIND, PROPPATCH, MKCOL, GET/HEAD扩展, PUT扩展, DELETE扩展, OPTIONS, COPY, MOVE)
  • 2: 包括级别1 + LOCK和UNLOCK支持
  • 3: 包括级别2 + 有序集合支持(可选)

使用场景​

OPTIONS响应:

OPTIONS /resource HTTP/1.1
Host: example.com

HTTP/1.1 200 OK
DAV: 1, 2
Allow: OPTIONS, GET, HEAD, POST, PUT, DELETE, PROPFIND, PROPPATCH, MKCOL, COPY, MOVE, LOCK, UNLOCK

10.2 Depth Header (Depth头)​

Depth头用于指定操作应该应用于资源层次结构的深度.

语法​

Depth: 0 | 1 | infinity

值的含义​

  • 0: 仅应用于目标资源本身
  • 1: 应用于资源及其直接成员
  • infinity: 递归应用于资源及其所有后代

适用方法​

方法Depth支持默认值
PROPFIND0, 1, infinityinfinity
COPY0, infinityinfinity
MOVEinfinity(忽略其他值)infinity
LOCK0, infinityinfinity
DELETE忽略(总是递归)N/A

示例​

<!-- 仅查询集合本身的属性 -->
PROPFIND /collection/ HTTP/1.1
Host: example.com
Depth: 0

<!-- 查询集合及其直接成员 -->
PROPFIND /collection/ HTTP/1.1
Host: example.com
Depth: 1

10.3 Destination Header (Destination头)​

Destination头指定COPY或MOVE操作的目标URL.

语法​

Destination: absoluteURI

要求​

  • 必需: COPY和MOVE方法必须包含此头
  • 绝对URI: 必须是完整的绝对URI
  • 同一服务器: 通常要求源和目标在同一服务器上

示例​

COPY /source/file.txt HTTP/1.1
Host: example.com
Destination: http://example.com/destination/file.txt
Overwrite: T

MOVE /old-name.doc HTTP/1.1
Host: example.com
Destination: http://example.com/new-name.doc

10.4 If Header (If头)​

If头提供了一种条件化执行WebDAV方法的机制,用于提交锁令牌和ETag.

语法​

If头有两种形式:

No-tag-list形式:

If: (&lt;locktoken>) ([etag])

Tagged-list形式:

If: &lt;resource-url> (&lt;locktoken>)

用途​

  1. 提交锁令牌 - 证明客户端持有锁
  2. 条件请求 - 基于ETag的条件执行
  3. 逻辑组合 - 支持AND和OR逻辑

示例​

提交锁令牌:

PUT /locked-resource HTTP/1.1
Host: example.com
If: (&lt;urn:uuid:181d4fae-7d8c-11d0-a765-00a0c91e6bf2>)
Content-Type: text/plain

Updated content

多个条件:

DELETE /resource HTTP/1.1
Host: example.com
If: `http://example.com/resource`
(&lt;urn:uuid:181d4fae-7d8c-11d0-a765-00a0c91e6bf2>)
(["e0-b2-1a2"])

NOT条件:

If: (Not &lt;urn:uuid:181d4fae-7d8c-11d0-a765-00a0c91e6bf2>)

If头的匹配规则​

  1. 锁令牌匹配 - 检查提交的令牌是否与资源锁匹配
  2. ETag匹配 - 检查实体标签是否匹配
  3. 逻辑评估 - 从左到右评估,支持短路

使用场景​

场景1:修改锁定资源

PUT /locked-doc HTTP/1.1
If: (&lt;urn:uuid:lock-token-here>)

场景2:COPY到锁定目标

COPY /source HTTP/1.1
Destination: http://example.com/locked-dest
If: `http://example.com/locked-dest`
(&lt;urn:uuid:dest-lock-token>)

场景3:条件更新

PUT /resource HTTP/1.1
If: (["etag-value"])

10.5 Lock-Token Header (Lock-Token头)​

Lock-Token头用于UNLOCK方法中指定要删除的锁.

语法​

Lock-Token: &lt;uri>

使用​

仅用于UNLOCK:

UNLOCK /resource HTTP/1.1
Host: example.com
Lock-Token: &lt;urn:uuid:a515cfa4-5da4-22e1-f5b5-00a0451e6bf7>

HTTP/1.1 204 No Content

与If头的区别​

  • Lock-Token: 仅用于UNLOCK,指定要删除的锁
  • If: 用于其他方法,提交锁令牌以证明授权

10.6 Overwrite Header (Overwrite头)​

Overwrite头指定COPY或MOVE操作是否应覆盖目标资源.

语法​

Overwrite: T | F

值​

  • T (True): 覆盖目标资源(默认)
  • F (False): 不覆盖,如果目标存在则失败

行为​

Overwrite: T:

  • 如果目标存在,先删除目标
  • 然后创建新资源
  • 返回204 No Content

Overwrite: F:

  • 如果目标存在,操作失败
  • 返回412 Precondition Failed
  • 不修改任何资源

示例​

<!-- 不覆盖现有文件 -->
COPY /source.txt HTTP/1.1
Host: example.com
Destination: http://example.com/dest.txt
Overwrite: F

<!-- 如果dest.txt存在 -->
HTTP/1.1 412 Precondition Failed

<!-- 如果dest.txt不存在 -->
HTTP/1.1 201 Created

10.7 Timeout Request Header (Timeout请求头)​

Timeout头用于LOCK请求中建议锁的超时时间.

语法​

Timeout: Second-&lt;seconds> | Infinite

示例​

LOCK /resource HTTP/1.1
Host: example.com
Timeout: Second-3600

<!-- 或者请求无限超时 -->
Timeout: Infinite

<!-- 多个超时值(按优先级) -->
Timeout: Infinite, Second-604800, Second-86400

服务器行为​

  • 可以拒绝: 服务器可以忽略客户端的建议
  • 返回实际值: 响应中必须包含服务器选择的超时值
  • 安全限制: 服务器可以限制最大超时时间

响应中的Timeout​

&lt;D:activelock>
&lt;D:timeout>Second-3600&lt;D:timeout>
...
&lt;D:activelock>

HTTP头快速参考​

头部用于方法必需/可选说明
DAVOPTIONS响应服务器支持的功能级别
DepthPROPFIND, COPY, LOCK可选操作深度
DestinationCOPY, MOVE必需目标URL
If所有方法可选条件执行和锁令牌提交
Lock-TokenUNLOCK必需要删除的锁令牌
OverwriteCOPY, MOVE可选是否覆盖目标
TimeoutLOCK可选建议的锁超时

本章总结:第10章定义了WebDAV的7个专用HTTP头部,这些头部扩展了HTTP/1.1的能力,支持深度操作(Depth),资源操作(Destination, Overwrite),锁定管理(Lock-Token, Timeout)和条件执行(If).正确使用这些头部对于实现可靠的WebDAV客户端和服务器至关重要.


12. HTTP状态码的使用 (Use of HTTP Status Codes)​

这些HTTP代码没有被重新定义,但它们的使用在某种程度上被WebDAV方法和要求所扩展.一般来说,许多HTTP状态码可以用于响应任何请求,而不仅仅是本文档中描述的情况.还要注意,已知WebDAV服务器使用300级重定向响应(早期互操作性测试发现客户端没有准备好看到这些响应).当服务器响应请求创建了新资源时,不得使用300级响应.

12.1. 412 Precondition Failed (前置条件失败)​

任何请求都可以包含HTTP中定义的条件头(If-Match,If-Modified-Since等)或本规范中定义的"If"或"Overwrite"条件头.如果服务器评估条件头,并且该条件不成立,则必须返回此错误代码.另一方面,如果客户端在请求中未包含条件头,则服务器不得使用此状态码.

12.2. 414 Request-URI Too Long (请求URI过长)​

此状态码在HTTP 1.1中仅用于Request-URI,而不用于其他位置的URI.


13. 多状态响应 (Multi-Status Response)​

多状态响应在可能适合多个状态码的情况下传递有关多个资源的信息.默认的多状态响应主体是text/xml或application/xml HTTP实体,具有'multistatus'根元素.其他元素包含在方法调用期间生成的200,300,400和500系列状态码.100系列状态码不应该记录在'response' XML元素中.

虽然'207'用作整体响应状态码,但接收方需要查阅多状态响应主体的内容以获取有关方法执行成功或失败的更多信息.响应可以用于成功,部分成功以及失败情况.

'multistatus'根元素以任何顺序保存零个或多个'response'元素,每个元素都包含有关单个资源的信息.每个'response'元素必须有一个'href'元素来标识资源.

多状态响应使用两种不同格式之一来表示状态:

  1. 作为'response'元素子项的'status'元素指示已标识资源作为整体的消息执行状态(例如,请参见第9.6.2节).某些方法定义提供有关客户端应准备在响应中看到的特定状态码的信息.但是,客户端必须能够使用[RFC2616]第10节中定义的通用规则处理其他状态码.

  2. 对于PROPFIND和PROPPATCH,格式已使用'propstat'元素而不是'status'进行了扩展,提供有关资源的各个属性的信息.此格式特定于PROPFIND和PROPPATCH,并在第9.1和9.2节中详细描述.

13.1. 响应头 (Response Headers)​

HTTP定义Location头来指示Request-URI中寻址的资源的首选URL(例如,响应成功的PUT请求或重定向响应).但是,当响应主体中有URL时(如多状态),使用此头会产生歧义.因此,在多状态响应中使用Location头是故意未定义的.

13.2. 处理重定向的子资源 (Handling Redirected Child Resources)​

HTTP 1.1中定义的重定向响应(300-303,305和307)通常采用Location头来指示从Request-URI重定向的单个资源的新URI.多状态响应包含许多资源地址,但[RFC2518]中的原始定义没有任何地方供服务器为重定向的资源提供新URI.本规范确实为此信息定义了'location'元素(请参见第14.9节).服务器必须在多状态中的重定向响应中使用此新元素.

在多状态中遇到重定向资源的客户端不得依赖'location'元素与新URI一起存在.如果元素不存在,客户端可以向单个重定向资源重新发出请求,因为对该请求的响应可以使用包含新URI的Location头进行重定向.

13.3. 内部状态码 (Internal Status Codes)​

第9.2.1,9.1.2,9.6.1,9.8.3和9.9.2节定义了多状态响应中使用的各种状态码.本规范未定义可能出现在这些响应中的其他状态码的含义.


16. 前置/后置条件XML元素 (Precondition/Postcondition XML Elements)​

如第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错误.对于本文档中未指定的错误条件,服务器可以简单地选择适当的数字状态并将响应主体留空.但是,服务器可以使用自定义条件代码和其他支持文本,因为即使客户端不自动识别条件代码,它们在互操作性测试和调试中也可能非常有用.

示例 - 带有前置条件代码的响应 (Example - Response with precondition code):

HTTP/1.1 423 Locked
Content-Type: application/xml; charset="utf-8"
Content-Length: xxxx

&lt;?xml version="1.0" encoding="utf-8" ?>
&lt;D:error xmlns:D="DAV:">
&lt;D:lock-token-submitted>
&lt;D:href>/workspace/webdav/&lt;D:href>
&lt;D:lock-token-submitted>
&lt;D:error>

在此示例中,不知道父集合"/workspace/webdav/"上的深度无限锁的客户端尝试修改集合成员"/workspace/webdav/proposal.doc".

在其他扩展WebDAV的规范中已定义了一些其他有用的前置条件和后置条件,例如RFC3744,[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的情况下,客户端可能很难找出哪个锁定资源导致请求失败 -- 但服务器只负责返回一个这样的锁定资源.如果服务器知道所有阻止请求成功的锁定资源,则可以返回它们.

&lt;!ELEMENT lock-token-submitted (href+) >

no-conflicting-lock​

名称 (Name): no-conflicting-lock (前置条件)

使用 (Use with): 通常为423 Locked

目的 (Purpose): 由于存在已经存在的冲突锁,LOCK请求失败.请注意,即使请求所针对的资源仅被间接锁定,锁也可能存在冲突.在这种情况下,前置条件代码可用于通知客户端作为冲突锁根的资源,避免单独查找"lockdiscovery"属性.

&lt;!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节.


17. DAV中的XML可扩展性 (XML Extensibility in DAV)​

本规范中使用XML命名空间扩展([REC-XML-NAMES]),以便可以添加新的XML元素而不必担心与其他元素名称冲突.尽管WebDAV请求和响应主体可以由任意XML元素扩展(消息接收方可以忽略这些元素),但除非该XML元素在由WebDAV工作组审查的IETF RFC中明确定义,否则不应该在请求或响应主体中使用"DAV:"命名空间中的XML元素.

为了使WebDAV既可扩展又向后兼容,客户端和服务器都需要知道在收到意外或无法识别的命令扩展时如何行为.对于XML处理,这意味着客户端和服务器必须处理收到的XML文档,就好像意外的元素和属性(以及无法识别的元素的所有子元素)不在那里一样.意外的元素或属性包括可能在另一个上下文中使用但在此处不需要的元素或属性.出于处理目的忽略此类项目当然可以与记录所有信息或呈现以进行调试保持一致.

此限制也适用于客户端对DAV属性值的处理,其中应该忽略意外的XML元素,除非属性的模式另有声明.

此限制不适用于在服务器上设置死DAV属性,其中服务器必须记录所有XML元素.

此外,此限制不适用于XML恰好是实体主体的内容类型的使用,例如,当用作PUT的主体时.

XML中的处理指令应该被接收方忽略.因此,扩展WebDAV的规范不应该使用处理指令来定义规范行为.

XML DTD片段包含在本规范中定义的所有XML元素中.但是,由于命名空间使用和扩展规则,正确的XML根据任何DTD都不会有效.特别是:

  • 元素(来自本规范)在"DAV:"命名空间中,
  • 元素顺序无关紧要,除非另有说明,
  • 可以添加扩展属性,
  • 对于"ANY"的元素类型定义,该元素的规范文本定义定义了其中可以包含什么以及这意味着什么.
  • 对于"#PCDATA"的元素类型定义,不得添加扩展元素.
  • 对于其他元素类型定义,包括"EMPTY",可以添加扩展元素.

请注意,这意味着包含元素的元素不能扩展为包含文本,反之亦然.

通过上述规则放宽了DTD验证,DTD片段描述的约束是规范性的(例如,请参见附录A).具有XML主体的WebDAV消息的接收方不得根据任何硬编码或动态声明的DTD验证XML文档.

请注意,本节描述了向后兼容的可扩展性规则.也可能有时扩展设计为不向后兼容,例如,定义重用本文档中定义的XML元素但省略本规范中DTD所需的子元素之一的扩展.


18. DAV合规性类别 (DAV Compliance Classes)​

符合DAV的资源可以宣传几个合规性类别.客户端可以通过在资源上执行OPTIONS并检查返回的"DAV"头来发现资源的合规性类别.请特别注意,所说的是资源而不是服务器符合.这是因为理论上服务器上的某些资源可以支持不同的功能集.例如,服务器可以具有支持版本控制等高级功能的子存储库,即使该功能在所有子存储库上都不受支持.

由于本文档描述了对HTTP/1.1协议的扩展,因此最低限度所有符合DAV的资源,客户端和代理都必须符合[RFC2616].

类别2或类别3合规的资源也必须是类别1合规的.

18.1. 类别1 (Class 1)​

类别1合规资源必须满足本文档所有节中的所有"MUST"要求.

类别1合规资源必须在对OPTIONS方法的所有响应中的DAV头中至少返回值"1".

18.2. 类别2 (Class 2)​

类别 2 合规资源必须满足所有类别 1 要求, 并支持 LOCK 方法, DAV:supportedlock 属性, DAV:lockdiscovery 属性, Time-Out 响应 Header 和 Lock-Token 请求 Header. 类别 2 合规资源还应该支持 Timeout 请求 Header 和 'owner' XML 元素.

类别2合规资源必须在对OPTIONS方法的所有响应中的DAV头中至少返回值"1"和"2".

18.3. 类别3 (Class 3)​

资源可以明确宣传其对本文档中对[RFC2518]所做修订的支持.也必须支持类别1.可以支持类别2.除类别1和2外宣传类别3支持意味着服务器支持本规范中的所有要求.宣传类别3和类别1支持,但不宣传类别2,意味着服务器支持本规范中的所有要求,除了可能涉及锁定支持的那些要求.

示例 (Example):

DAV: 1, 3

19. 国际化考虑 (Internationalization Considerations)​

在国际化领域, 本规范符合 IETF 字符集策略 [RFC2277]. 在本规范中, 人类可读字段可以在属性值中找到, 或者在响应实体主体中返回的错误消息中找到. 在这两种情况下, 人类可读内容都使用 XML 编码, XML 具有明确的字符集标记和编码规定, 并要求 XML 处理器至少使用 ISO 10646 多语言平面的 UTF-8 [RFC3629] 和 UTF-16 [RFC2781] 编码读取 XML 元素. 本规范中的 XML 示例演示了 Content-Type Header 的 charset 参数 (在 [RFC3023] 中定义) 以及 XML 字符集声明的使用.

XML还提供了语言标记功能,用于指定特定XML元素内容的语言."xml:lang"属性出现在XML元素上以标识其内容和属性的语言.有关值和作用域的定义,请参见[REC-XML].

WebDAV应用程序必须支持XML规范的字符集标记,字符集编码和语言标记功能.强烈建议WebDAV应用程序的实现者阅读"XML Media Types"[RFC3023],以了解XML传输应使用哪种MIME媒体类型,以及Content-Type头的charset参数的使用.

本规范中使用的名称分为四类:协议元素名称(如方法和头),XML元素名称,属性名称和条件名称.协议元素的命名遵循HTTP的先例,使用US-ASCII编码的英文名称作为方法和头.由于这些协议元素对用户不可见,只是长标记标识符,因此不需要支持多种语言.类似地,本规范中使用的XML元素名称对用户不可见,因此不需要支持多种语言.

WebDAV属性名称是限定的XML名称(XML命名空间名称和本地名称对).尽管某些应用程序(例如,通用属性查看器)将直接向用户显示属性名称,但预期典型应用程序将使用固定的属性集,并在向用户显示属性名称时提供从属性名称和命名空间到人类可读字段的映射.只有在属性集事先未知的情况下,应用程序才需要向用户显示属性名称.我们建议应用程序尽可能提供人类可读的属性名称.

对于错误报告,我们遵循HTTP/1.1状态码的约定,每个状态码包含一个简短的英文描述(例如,423(Locked)).虽然存在设计不当的用户代理将此消息显示给用户的可能性,但国际化应用程序将忽略此消息,并以用户的语言和字符集显示适当的消息.

由于客户端和服务器的互操作不需要区域设置信息,因此本规范未指定任何传输此信息的机制.


20. 安全考虑 (Security Considerations)​

本节提供有关WebDAV应用程序需要注意的安全影响问题的详细信息.

HTTP/1.1(在[RFC2616]中讨论)和XML(在[RFC3023]中讨论)的所有安全考虑也适用于WebDAV.此外,远程创作固有的安全风险需要更强的身份验证技术,引入了几个新的隐私问题,并可能增加来自糟糕服务器设计的危险.这些问题详述如下.

20.1. 客户端身份验证 (Authentication of Clients)​

由于强调创作,WebDAV服务器需要使用身份验证技术来保护不仅是对网络资源的访问,还有资源的完整性.此外,锁定功能的引入需要身份验证支持.

通过不安全的通道以明文发送的密码不足以保护资源的可访问性和完整性,因为密码可能被截获.由于HTTP/1.1的Basic身份验证本质上执行密码的明文传输,因此除非连接是安全的,否则不得使用Basic身份验证来向服务器验证WebDAV客户端.此外,除非连接是安全的,否则WebDAV服务器不得在WWW-Authenticate头中发送Basic身份验证质询.安全连接的示例是使用强密码套件和服务器身份验证的传输层安全(TLS)连接.

WebDAV应用程序必须支持Digest身份验证方案[RFC2617].由于Digest身份验证验证通信双方都知道共享密钥(密码),而无需明文发送该密钥,因此Digest身份验证避免了Basic身份验证固有的安全问题,同时在广泛的场景中提供了有用的身份验证级别.

20.2. 拒绝服务 (Denial of Service)​

拒绝服务攻击是WebDAV服务器特别关注的问题.WebDAV加HTTP使拒绝服务攻击能够针对系统资源的每个部分.

  • 可以通过PUTting极大的文件来攻击底层存储.
  • 请求对大型集合的递归操作可以攻击处理时间.
  • 在多个连接上进行多个管道请求可以攻击网络连接.

WebDAV服务器需要在所有级别都意识到拒绝服务攻击的可能性.对此类攻击的适当响应可能是简单地断开连接.或者,如果服务器能够做出响应,服务器可以使用400级状态请求(如400(Bad Request))并指示请求被拒绝的原因(500级状态响应将表明问题在于服务器,而无意的DoS攻击是客户端能够补救的).

20.3. 通过隐藏的安全 (Security through Obscurity)​

WebDAV通过PROPFIND方法提供了列出集合的成员资源的机制.这大大降低了仅依赖于发现网络资源名称困难性的安全或隐私技术的有效性.鼓励WebDAV服务器的用户使用访问控制技术来防止对资源的不需要的访问,而不是依赖于其资源名称的相对隐藏性.

20.4. 与锁相关的隐私问题 (Privacy Issues Connected to Locks)​

提交锁请求时,用户代理还可以提交'owner' XML字段,给出获取锁的人的联系信息(对于人而不是机器人获取锁的情况).此联系信息存储在资源的DAV:lockdiscovery属性中,其他协作者可以使用它来开始就对资源的访问进行协商.但是,在许多情况下,此联系信息可能非常私密,不应广泛传播.服务器应该适当限制对DAV:lockdiscovery属性的读取访问.此外,用户代理应该提供对是否发送联系信息的控制,如果发送联系信息,则控制发送什么信息.

20.5. 与属性相关的隐私问题 (Privacy Issues Connected to Properties)​

由于属性值通常用于保存诸如文档作者之类的信息,因此可能会出现与广泛访问资源的属性数据有关的隐私问题.为了减少通过属性无意泄露私人信息的风险,鼓励服务器开发访问控制机制,将对资源主体的读取访问和对资源属性的读取访问分开.这允许用户控制其属性数据的传播,而不会过度限制对资源内容的访问.

20.6. XML实体的含义 (Implications of XML Entities)​

XML支持称为"外部实体"的功能(在[REC-XML]第4.2.2节中定义),它指示XML处理器检索并包含额外的XML.外部XML实体可用于附加或修改与XML文档关联的文档类型声明(DTD).外部XML实体也可用于在XML文档的内容中包含XML.对于非验证XML(如本规范中使用的XML),XML不需要包含外部XML实体.但是,XML确实声明XML处理器可以自行决定包含外部XML实体.

外部XML实体没有固有的可信度,并受到HTTP GET请求所特有的所有攻击.此外,外部XML实体可能修改DTD,从而影响XML文档的最终形式,在最坏的情况下,显著修改其语义或使XML处理器面临[RFC3023]中讨论的安全风险.因此,实现者必须意识到外部XML实体应被视为不可信.如果服务器选择不处理外部XML实体,它应该使用'no-external-entities'条件代码响应包含外部实体的请求.

还存在伴随广泛部署的使用外部XML实体的应用程序的可扩展性风险.在这种情况下,可能会有大量对一个外部XML实体的请求,可能会使任何处理包含外部XML实体的资源请求的服务器过载.

此外,还存在基于评估[REC-XML]第4.2.2节中定义的"内部实体"的风险.使用嵌套内部实体的精心设计的小请求可能需要大量内存和/或处理时间来处理.服务器实现者应该意识到这种风险,并配置其XML解析器,以便可以尽早检测和拒绝此类请求.

20.7. 与锁令牌相关的风险 (Risks Connected with Lock Tokens)​

本规范鼓励对锁令牌(第6.5节)使用"通用唯一标识符(UUID)URN命名空间"([RFC4122]),以保证其在空间和时间上的唯一性.版本1 UUID(在第4节中定义)可能包含"节点"字段,"由IEEE 802 MAC地址组成,通常是主机地址.对于具有多个IEEE地址的系统,可以使用任何可用的地址".由于WebDAV服务器在其生命周期内将发出许多锁,这意味着它也可能公开暴露其IEEE 802地址.

暴露IEEE 802地址存在几个风险.使用IEEE 802地址:

  • 可以跟踪硬件从子网到子网的移动.
  • 可能能够识别运行WebDAV服务器的硬件制造商.
  • 可能能够确定运行WebDAV的每种类型计算机的数量.

此风险仅适用于基于主机地址的UUID版本.[RFC4122]的第4节描述了几种其他生成UUID的机制,这些机制不涉及主机地址,因此不会遇到此风险.

20.8. 托管恶意内容 (Hosting Malicious Content)​

HTTP具有托管在客户端机器上执行的程序的能力.这些程序可以采取许多形式,包括Web脚本,可执行文件,插件模块和文档中的宏.WebDAV不会改变围绕这些程序的任何安全问题,但WebDAV通常用于广泛的用户可以在服务器上发布文档的环境中.服务器可能与发布文档的作者没有密切的信任关系.允许客户端发布任意内容的服务器可以有效地实施预防措施,检查发布到服务器的内容对其他客户端没有危害.服务器可以通过诸如限制允许发布的内容类型并对发布的内容运行病毒和恶意软件检测软件等技术来做到这一点.服务器还可以通过对允许向服务器发布内容的用户进行适当的访问限制和身份验证来降低风险.


21. IANA考虑 (IANA Considerations)​

21.1. 新URI方案 (New URI Schemes)​

本规范定义了两个URI方案:

  1. 附录C中定义的"opaquelocktoken"方案,以及

  2. "DAV" URI方案,历史上在[RFC2518]中用于消除WebDAV属性和XML元素名称的歧义,并在本规范和其他扩展WebDAV的规范中继续用于该目的."DAV:"命名空间中标识符的创建由IETF控制.

请注意,现在不鼓励为XML命名空间定义新的URI方案."DAV:"是在标准最佳实践出现之前定义的.

21.2. XML命名空间 (XML Namespaces)​

XML命名空间消除WebDAV属性名称和XML元素的歧义.任何WebDAV用户或应用程序都可以定义新命名空间,以创建自定义属性或扩展WebDAV XML语法.IANA不需要管理此类命名空间,属性名称或元素名称.

21.3. 消息头字段 (Message Header Fields)​

以下消息头字段应添加到永久注册表(见[RFC3864]).

21.3.1. DAV​

头字段名称 (Header field name): DAV

适用协议 (Applicable protocol): http

状态 (Status): standard

作者/变更控制者 (Author/Change controller): IETF

规范文档 (Specification document): 本规范(第10.1节)

21.3.2. Depth​

头字段名称: Depth

适用协议: http

状态: standard

作者/变更控制者: IETF

规范文档: 本规范(第10.2节)

21.3.3. Destination​

头字段名称: Destination

适用协议: http

状态: standard

作者/变更控制者: IETF

规范文档: 本规范(第10.3节)

21.3.4. If​

头字段名称: If

适用协议: http

状态: standard

作者/变更控制者: IETF

规范文档: 本规范(第10.4节)

21.3.5. Lock-Token​

头字段名称: Lock-Token

适用协议: http

状态: standard

作者/变更控制者: IETF

规范文档: 本规范(第10.5节)

21.3.6. Overwrite​

头字段名称: Overwrite

适用协议: http

状态: standard

作者/变更控制者: IETF

规范文档: 本规范(第10.6节)

21.3.7. Timeout​

头字段名称: Timeout

适用协议: http

状态: standard

作者/变更控制者: IETF

规范文档: 本规范(第10.7节)

21.4. HTTP状态码 (HTTP Status Codes)​

本规范定义了以下HTTP状态码

  • 207 Multi-Status(第11.1节)
  • 422 Unprocessable Entity(第11.2节)
  • 423 Locked(第11.3节)
  • 424 Failed Dependency(第11.4节)以及
  • 507 Insufficient Storage(第11.5节)

应在<http://www.iana.org/assignments/http-status-codes&gt;的注册表中更新.

注意: HTTP状态码102(Processing)已在本规范中删除;其IANA注册应继续引用RFC 2518.


22. 致谢 (Acknowledgements)​

像这样的规范在尖锐的批判性审查中茁壮成长,在冷漠的忽视中枯萎.作者衷心感谢以下人员的贡献,他们的洞察力在我们工作的每个阶段都非常宝贵.

RFC 2518的贡献者 (Contributors to RFC 2518)​

Terry Allen, Harald Alvestrand, Jim Amsden, Becky Anderson, Alan Babich, Sanford Barr, Dylan Barrell, Bernard Chester, Tim Berners-Lee, Dan Connolly, Jim Cunningham, Ron Daniel, Jr., Jim Davis, Keith Dawson, Mark Day, Brian Deen, Martin Duerst, David Durand, Lee Farrell, Chuck Fay, Wesley Felter, Roy Fielding, Mark Fisher, Alan Freier, George Florentine, Jim Gettys, Phill Hallam-Baker, Dennis Hamilton, Steve Henning, Mead Himelstein, Alex Hopmann, Andre van der Hoek, Ben Laurie, Paul Leach, Ora Lassila, Karen MacArthur, Steven Martin, Larry Masinter, Michael Mealling, Keith Moore, Thomas Narten, Henrik Nielsen, Kenji Ota, Bob Parker, Glenn Peterson, Jon Radoff, Saveen Reddy, Henry Sanders, Christopher Seiwald, Judith Slein, Mike Spreitzer, Einar Stefferud, Greg Stein, Ralph Swick, Kenji Takahashi, Richard N. Taylor, Robert Thau, John Turner, Sankar Virdhagriswaran, Fabio Vitali, Gregory Woodhouse, and Lauren Wood.

这个列表中有两个人值得特别提及.Larry Masinter的贡献是无价的;他既帮助了工作组的组建,又在整个过程中耐心地指导作者.他以如此多的方式设定了我们努力达到的高标准.Judith Slein的贡献也是无价的;通过澄清需求并耐心地审查一个又一个版本,她既改进了本规范,又拓展了我们对文档管理的认识.

我们还要感谢John Turner开发了XML DTD.

RFC 2518的作者是Yaron Goland,Jim Whitehead,A. Faizi,Steve Carter和D. Jensen.尽管由于IETF作者数量限制,他们的名字不得不被删除,但他们可以为WebDAV的大部分设计获得荣誉.

本规范的额外致谢 (Additional Acknowledgements for This Specification)​

本规范文本的重要贡献者在下面的贡献者部分列出.我们还必须衷心感谢Geoff Clemm,Joel Soderberg和Dan Brotsky在列表或会议中详细讨论具体文本.Joe Hildebrand和Cullen Jennings帮助解决了许多问题.Barry Lind描述了一个额外的安全考虑因素,Cullen Jennings为该考虑因素提供了文本.Jason Crawford多年来跟踪了本文档的问题状态,Elias Sinderson紧随其后.


附录A. 处理XML元素的注意事项 (Notes on Processing XML Elements)​

A.1. 空XML元素的注意事项 (Notes on Empty XML Elements)​

XML支持两种机制来指示XML元素没有任何内容.第一种是声明形式为&lt;A>&lt;/A>的XML元素.第二种是声明形式为&lt;A/>的XML元素.这两个XML元素在语义上是相同的.

A.2. 非法XML处理的注意事项 (Notes on Illegal XML Processing)​

XML是一种灵活的数据格式,可以轻松提交看似合法但实际上不合法的数据."在接受内容时要灵活,在发送内容时要严格"的理念仍然适用,但不得不适当地应用.XML在处理空白,元素排序,插入新元素等问题时非常灵活.这种灵活性不需要扩展,特别是在元素含义方面.

接受非法的XML元素组合没有任何好处.充其量,它会导致不需要的结果,最坏的情况下会造成真正的损害.

A.3. 示例 - XML语法错误 (Example - XML Syntax Error)​

以下PROPFIND方法的请求主体是非法的.

&lt;?xml version="1.0" encoding="utf-8" ?>
&lt;D:propfind xmlns:D="DAV:">
&lt;D:allprop/>
&lt;D:propname/>
&lt;D:propfind>

propfind元素的定义只允许allprop或propname元素,不能同时存在.因此,上述是错误的,必须以400(Bad Request)响应.

然而,假设服务器想要"友好"并决定选择allprop元素作为真正的元素并对其响应.通过带宽受限线路运行的客户端如果打算执行propname,如果服务器将命令视为allprop,将会大吃一惊.

此外,如果服务器宽容并决定响应此请求,结果将在服务器之间随机变化,一些服务器执行allprop指令,而其他服务器执行propname指令.这降低了互操作性而不是提高了互操作性.

A.4. 示例 - 意外的XML元素 (Example - Unexpected XML Element)​

前面的示例是非法的,因为它包含两个明确禁止在propfind元素中一起出现的元素.但是,XML是一种可扩展的语言,因此可以想象为与propfind一起使用定义新元素.下面是PROPFIND的请求主体,与前面的示例一样,对于不理解expired-props元素的服务器,必须以400(Bad Request)拒绝.

&lt;?xml version="1.0" encoding="utf-8" ?>
&lt;D:propfind xmlns:D="DAV:"
xmlns:E="http://www.example.com/standards/props/">
&lt;E:expired-props/>
&lt;D:propfind>

要理解为什么返回400(Bad Request),让我们看看不熟悉expired-props的服务器如何看待请求主体.

&lt;?xml version="1.0" encoding="utf-8" ?>
&lt;D:propfind xmlns:D="DAV:"
xmlns:E="http://www.example.com/standards/props/">
&lt;D:propfind>

由于服务器不理解'expired-props'元素,根据第17节中指定的WebDAV特定XML处理规则,它必须处理请求,就好像该元素不在那里一样.因此,服务器看到一个空的propfind,根据propfind元素的定义,这是非法的.

请注意,如果扩展是附加的,它不一定会导致400(Bad Request).例如,想象以下PROPFIND的请求主体:

&lt;?xml version="1.0" encoding="utf-8" ?>
&lt;D:propfind xmlns:D="DAV:"
xmlns:E="http://www.example.com/standards/props/">
&lt;D:propname/>
&lt;E:leave-out>*boss*&lt;E:leave-out>
&lt;D:propfind>

前面的示例包含虚构的元素leave-out.其目的是防止返回名称与提交的模式匹配的任何属性.如果将前面的示例提交给不熟悉'leave-out'的服务器,唯一的结果是'leave-out'元素将被忽略,并执行propname.


附录B. HTTP客户端兼容性注意事项 (Notes on HTTP Client Compatibility)​

WebDAV被设计为与HTTP 1.1向后兼容,并且已被发现是向后兼容的.PUT和DELETE方法在HTTP中定义,因此可以由HTTP客户端和WebDAV感知客户端使用,但对PUT和DELETE的响应在本规范中以只有WebDAV客户端才能完全准备好的方式进行了扩展.关于这些响应是否会导致与纯HTTP客户端的互操作性问题,提出了一些理论问题,本节解决了这些问题.

由于任何HTTP客户端都应该将无法识别的400级和500级状态码作为错误处理,因此以下新状态码不应该出现任何问题:422,423和507(424也是新状态码,但它仅出现在Multistatus响应的主体中).因此,例如,如果HTTP客户端尝试PUT或DELETE锁定的资源,423 Locked响应应该导致向用户呈现通用错误.

207 Multistatus响应很有趣,因为向集合发出DELETE请求的HTTP客户端可能会将207响应解释为成功,即使它没有意识到资源是集合,也无法理解DELETE操作可能是完全或部分失败.这种解释并不完全合理,因为200级响应表示服务器"接收,理解并接受"了请求,而不是请求导致完全成功.

一种选择是服务器可以将集合的DELETE视为原子操作,并在成功的情况下使用204 No Content,或对于错误使用某些适当的错误响应(400或500级).这种方法确实会最大化向后兼容性.但是,由于互操作性测试和工作组讨论没有发现HTTP客户端对WebDAV集合发出DELETE请求的任何实例,因此这种担忧更多是理论上的而不是实际的.因此,即使服务器将任何集合DELETE请求视为WebDAV请求并发送207 Multi-Status响应,服务器也很可能在与HTTP客户端互操作时完全成功.

一般来说,鼓励服务器实现使用本文档中定义的详细响应和其他机制,而不是为理论上的互操作性问题进行更改.


附录C. 'opaquelocktoken'方案和URI (The 'opaquelocktoken' Scheme and URIs)​

'opaquelocktoken' URI方案在[RFC2518]中定义(并由IANA注册),以便从UUID创建语法正确且易于生成的URI,旨在用作锁令牌,并在所有时间对所有资源都是唯一的.

opaquelocktoken URI通过连接'opaquelocktoken'方案与UUID以及可选的扩展来构造.服务器可以为每个新锁令牌创建新的UUID.如果服务器希望重用UUID,服务器必须添加扩展,并且生成扩展的算法必须保证同一扩展永远不会与关联的UUID一起使用两次.

OpaqueLockToken-URI = "opaquelocktoken:" UUID [Extension]
; UUID在[RFC4122]第3节中定义.请注意,LWS
; 不允许在此生成的元素之间使用.

Extension = path
; path在[RFC3986]第3.3节中定义

附录D. 锁空资源 (Lock-null Resources)​

锁定未映射URL的原始WebDAV模型创建了"锁空资源".这个模型过于复杂,并且发现了一些互操作性和实现问题.锁定未映射URL的新WebDAV模型(见第7.3节)创建"锁定的空资源".锁空资源已被弃用.本节简要讨论原始模型,因为客户端必须能够处理任一模型.

在原始的"锁空资源"模型中(不再建议实现):

  • 锁空资源有时显示为"Not Found".服务器对除PUT,MKCOL,OPTIONS,PROPFIND,LOCK,UNLOCK之外的任何方法响应404或405.

  • 但是,锁空资源确实作为其父集合的成员出现.

  • 如果锁在转换为常规资源之前消失,服务器会完全删除锁空资源(其URI变为未映射).回想一下,锁不仅在过期或解锁时消失,而且如果资源被重命名或移动,或者如果任何父集合被重命名或移动,锁也会被删除.

  • 如果对URL的PUT请求成功,服务器会将锁空资源转换为常规资源.

  • 如果对URL的MKCOL请求成功,服务器会将锁空资源转换为集合(尽管互操作性经验表明并非所有服务器都遵循此要求).

  • 为DAV:lockdiscovery和DAV:supportedlock属性定义了属性值,但不一定为其他属性(如DAV:getcontenttype)定义.

客户端可以轻松地与支持旧模型"锁空资源"和推荐的"锁定的空资源"模型的服务器互操作,只需在LOCK到未映射URL后仅尝试PUT,而不是MKCOL或GET.

D.1. 使用LOCK创建资源的客户端指南 (Guidance for Clients Using LOCK to Create Resources)​

实现本规范的WebDAV客户端可能会发现创建锁空资源的服务器(使用[RFC2518]在本规范之前实现)以及创建锁定空资源的服务器.对LOCK请求的响应不会指示创建了什么类型的资源.有几种技术可以帮助客户端处理任一类型.

  • 如果客户端希望避免意外创建锁空资源或空锁定资源,可以在LOCK请求中包含"If-Match: *"头,以防止服务器创建新资源.

  • 如果LOCK请求创建了资源,并且客户端随后想要使用COPY或MOVE请求覆盖该资源,客户端应该包含"Overwrite: T"头.

  • 如果LOCK请求创建了资源,然后客户端决定摆脱该资源,DELETE请求应该在锁空资源上失败,应该使用UNLOCK.但是对于锁定的空资源,UNLOCK不会使资源消失.因此,客户端可能必须尝试两个请求并忽略两个请求之一中的错误.


附录F. 与RFC 2518的变更摘要 (Summary of Changes from RFC 2518)​

本附录提供了与RFC 2518的变更摘要.

F.1. 客户端和服务器实现的变更 (Changes for Both Client and Server Implementations)​

澄清 (Clarifications):

  • 添加了关于必须支持哪些HTTP功能的澄清.
  • 添加了关于何时必须返回ETag的澄清.
  • 澄清了永远不能删除根集合.
  • 澄清了客户端需要能够处理包含任何顺序属性的PROPFIND响应.
  • 澄清了对PROPFIND Depth infinity请求的要求.
  • 添加了关于Timeout请求头使用的澄清.
  • 添加了关于时间值处理的澄清.

处理澄清 (Processing Clarifications):

  • 澄清了何时可以使用HTTP的If头而不是WebDAV的If头.
  • 澄清了WebDAV客户端在与WebDAV服务器交互时需要能够处理401响应.

增强的指南 (Enhanced Guidance):

  • 添加了关于使用DAV头的指南.
  • 添加了处理HTTP条件头的指南.
  • 添加了对具有过多资源的集合进行PROPFIND请求的指南.
  • 添加了PROPFIND响应示例并澄清了格式要求.
  • 添加了COPY请求示例并澄清了Overwrite头处理.

新功能 (New Functionality):

  • 102(Processing)状态码已从本规范中删除.它未被广泛实现,已移至RFC 2518.

F.2. 客户端实现的变更 (Changes for Client Implementations)​

新指南 (New Guidance):

  • 添加了关于XML可扩展性的附录.
  • 添加了关于客户端身份验证的附录.
  • 添加了关于XML实体含义的安全考虑.

处理变更 (Processing Changes):

  • 客户端不再需要在响应中接收到无效的元素排序时失败.

F.3. 服务器实现的变更 (Changes for Server Implementations)​

锁空资源 (Lock-Null Resources):

  • 服务器支持的锁空资源已被弃用,改为锁定的空资源.
  • 为了向后兼容,服务器仍可以支持锁空资源.

属性变更 (Property Changes):

  • 更改了许多属性定义以使其更加一致和清晰.
  • 在需要DAV:getlastmodified的地方强制使用DAV:getetag属性.
  • 删除了集合上的 DAV:getcontenttype 要求.

错误报告 (Error Reporting):

  • 添加了前置条件/后置条件XML元素,以便在响应主体中更好地报告错误.
  • 添加了关于使用前置条件和后置条件的指南.

COPY/MOVE行为 (COPY/MOVE Behavior):

  • 澄清了COPY/MOVE相对于属性的行为.
  • 澄清了COPY/MOVE与锁的行为.
  • 澄清了COPY/MOVE相对于Depth头的行为.

锁处理 (Lock Handling):

  • 澄清了LOCK请求中的锁所有者字段未经身份验证.
  • 澄清了何时锁必须超时以及何时可以扩展.
  • 添加了LockInfo元素澄清.
  • 更正了DAV:supportedlock模式.

其他服务器变更 (Other Server Changes):

  • 澄清了服务器何时必须使用404与405响应.
  • 澄清了DELETE集合行为和错误报告.
  • 澄清了PROPPATCH事务要求.
  • OPTIONS方法必须在响应中包含"DAV"头.

F.4. XML处理的澄清 (Clarifications to XML Processing)​

验证 (Validation):

  • 澄清了XML处理和验证的要求级别.
  • 澄清了XML处理规则仅适用于WebDAV定义的元素.
  • 添加了关于处理未知XML元素的指南.

命名空间处理 (Namespace Handling):

  • 澄清了属性和XML元素中的命名空间使用.
  • 澄清了属性名称始终是限定的.

DTD变更 (DTD Changes):

  • DTD已从规范中删除.它从未是规范性的,有时是不正确或不完整的.

F.5. 协议细节的澄清 (Clarifications to Protocol Details)​

状态码澄清 (Status Code Clarifications):

  • 澄清了何时必须或应该使用每个WebDAV状态码.
  • 澄清了WebDAV状态码与HTTP状态码的交互.

头澄清 (Header Clarifications):

  • 澄清了Depth头与各种方法的使用.
  • 澄清了If头语法和处理.
  • 澄清了Overwrite头使用.

响应格式 (Response Format):

  • 使Multi-Status响应格式的要求更加清晰.
  • 使href处理在所有使用中保持一致.

错误处理 (Error Handling):

  • 使用前置条件/后置条件元素增强了整个错误处理.
  • 添加了处理授权失败的具体指南.