8. 常规请求与响应处理

原文

8.1. 错误处理优先级

原文

服务器在处理请求时, 必须[MUST]优先返回授权错误 (authorization errors), 而不是其他类型的错误. 这样做可以避免泄露受保护资源的信息 (e.g., 客户端通过匿名请求受保护资源返回的 423锁定错误响应,从而发现隐藏资源的存在).

8.2. XML 的使用

原文

在 HTTP/1.1 中,方法参数信息仅通过 HTTP标头进行编码. 与 HTTP/1.1 不同, WebDAV 在 XML 请求实体正文([REC-XML])或 HTTP标头中编码方法参数信息. 使用 XML 来编码方法参数是为了能够向现有结构添加额外的 XML元素以提供可扩展性; 并且 XML 能够通过以 ISO 10646 字符集编码信息来提供国际化支持.

除了编码方法参数, WebDAV 中还使用 XML 来编码方法响应, 为方法输出提供 XML 的可扩展性, 国际化, 以及输入方面的优势。

当 XML 用于请求或响应正文时, Content-Type 类型应该[SHOULD]application/xml. 实现必须[MUST]在请求和响应正文中接受 text/xmlapplication/xml. 其中 text/xml 已被弃用。

所有符合 DAV 标准的客户端和资源必须使用符合 [REC-XML] 和 [REC-XML-NAMES] 标准的 XML 解析器. 所有在请求或响应中使用的 XML 必须[MUST]至少是结构正确 (well formed) 且正确使用命名空间的. 如果服务器接收到不良好结构 (not well-formed) 的 XML, 那么服务器必须[MUST]返回 400(Bad Request)拒绝整个请求. 如果客户端在响应中收到了不良格式的 XML, 那么客户端不能[MUST_NOT]对执行的方法结果做出任何假设, 且应该[SHOULD]将服务器视为故障.

注意, 处理不受信来源提交的 XML 可能会导致隐私安全和服务质量相关的风险 (参考第 20 章). 服务器可能[MAY]会拒绝可疑请求 (即使它们由良好格式的 XML 构成), 比如返回 400 (Bad Request) 状态代码和可选的响应正文来解释问题.

8.3. 处理 URL

原文

URL 会出现在请求和响应中的许多地方. 与 [RFC2518] 的互操作性经验显示许多客户端没有完全按照 [RFC3986#5] 中定义的完整引用解析规则实现对多状态 (Multi-Status) 的响应. 因此, 服务器在处理响应中的 URL 时尤其需要小心, 要确保客户端具有足够的上下文来解释所有的 URL. 本章中的规则不仅适用于多状态响应 href元素中的资源URL, 也同样适用于目标和条件 IF标头中的资源URL.

发送者可以从两种方法中选择其一:

  • 使用相对引用 (relative reference), 该引用会根据 Request-URI 进行解析.
  • 使用完整 URI 进行解析.

服务器必须确保每个多状态响应中 href 的值使用相同格式.

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

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

其中,absolute-URI, path-absolutequery 规范分别在 [RFC3986#4.3] [RFC3986#3.3] 和 [RFC3986#3.4] 中定义.

Simple-ref 规范中,发送者不得 (MUST NOT):

  • 使用点分(".", "..")
  • 具有与请求 URI 不匹配的前缀(使用 [RFC2616#3.2.3] 中定义的比较规则).

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

8.3.1. 示例 - 正确处理 URL

考虑集合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 引用中使用时, 它必须进行百分号编码 (percent-encoded), 以符合 [RFC3986#2.1] 中对 URI 的要求. 此外还要注意,一个合法的 URI 仍可能包含在 XML 字符集中需要转义的字符, 比如 & 字符.

8.4. 请求中必要的正文

原文

一些新的方法没有定义请求正文. 服务器必须检查所有请求是否有正文, 即使这个正文不是期望的. 在存在请求正文但服务器需要忽略它的情况下, 必须返回 415 (不支持的媒体类型) 拒绝该请求. 这会通知可能正尝试使用扩展功能客户端, 既服务器无法按照客户端的意图处理该请求正文.

8.5. 用于 WebDAV 的 HTTP 标头

原文

HTTP 定义了许多可用于 WebDAV 请求和响应的标头. 这些标头并非所有情况下都适用, 其中某些交互可能未定义. 注意, HTTP 1.1 在如果可能的情况下会要求在所有响应中包含 Date标头(参见 [RFC2616#14.18]).

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

译者注: 参考"错误处理优先级"小节

8.6. ETag

原文

HTTP 1.1 建议在控制缓存时使用 ETags 而不是修改日期, 甚至有更强烈的理由在编写内容时优先考虑 ETags. 正确使用 ETags 在分布式创作环境中更为重要, 因为在避免丢失更新问题时,锁定ETags 必不可少. e.g.,当锁超时时,客户端可能无法续订锁 (renew a lock), 且客户端有可能在锁定超时时意外离线或正在进行长时间上传. 当客户端无法续订锁时, 只要没有其他任同时进行修改, 该资源仍可以被该客户端重新锁定并让用户继续编辑. 在客户端能够区分这种情况时, ETag 是必须的. 否则客户端将被迫询问用户是否覆盖服务器上的资源, 此时客户端无法判断资源被更改. 时间戳并不能像 ETags 那样有效地解决这个问题.

强ETags弱ETags 在内容编写时候更有用 (见 [RFC2616#13.3.3]). 语义等价性可以是一个有用的概念, 但这取决于文档类型和应用类型, 这之间的互操作性 (interoperability) 可能需要在本规范和 HTTP 范围之外达成一些协议或标准. 同时要注意的是, 弱ETags 在 HTTP 中有一些限制,e.g., 在 If-Match标头中无法使用它们.

需要注意的是,PUT 响应中 ETag 的含义在本文档或 [RFC2616] 中都没有明确定义 (i.e., ETag 是否表示资源与 PUT 请求正文等效; 或服务器是否可以在存储时对文档的格式或内容进行细微更改). 这不仅仅是 WebDAV, 而是 HTTP 的一个问题.

由于如果 ETag 更改,客户端可能强制提示用户或丢弃更改的内容, 因此 WebDAV 服务器在资源主体和位置未变化时,不应该[SHOULD_NOT]更改ETag或最后修改时间. ETag 代表资源正文或内容的状态, 除了 ETag 没有类似的方法来判断属性是否已更改.

译者注: 在 HTTP 中, Etag 包含在其标头中, 其标识资源的状态和版本, 以支持资源锁定, 版本控制和冲突解决等功能.

# 1. 请求
LOCK /file.txt HTTP/1.1
Host: example.com
If: (<opaquelocktoken:123456789>)

# 2. 响应
HTTP/1.1 200 OK
Lock-Token: <opaquelocktoken:123456789>
ETag: "abcdef123456"

在 WebDav 中, 可以通过 PRFINDgetetag 来获取资源ETag 值.

# 1. 请求
PROPFIND /example.txt HTTP/1.1
Host: example.com
Depth: 0
Content-Type: text/xml; charset="utf-8"

<?xml version="1.0" encoding="utf-8"?>
<D:propfind xmlns:D="DAV:">
  <D:prop>
    <D:getetag />
  </D:prop>
</D:propfind>

# 2. 响应 (包含一个多状态响应)
HTTP/1.1 207 Multi-Status
Content-Type: text/xml; charset="utf-8"

<?xml version="1.0" encoding="utf-8"?>
<D:multistatus xmlns:D="DAV:">
  <D:response>
    <D:href>/example.txt</D:href>
    <D:propstat>
      <D:prop>
        <D:getetag>"123456789"</D:getetag>
      </D:prop>
      <D:status>HTTP/1.1 200 OK</D:status>
    </D:propstat>
  </D:response>
</D:multistatus>

8.7. 包含错误响应的正文

原文

在 WebDAV 版本扩展规范引入在错误响应的正文中包含更具体信息的机制前, HTTP 和 WebDAV 的大多数错误响应的正文并不是机器可解析信息 (machine-parsable information) (参见 [RFC3253#1.6]). 错误正文机制适用于任何可能具有正文但尚未定义正文的错误响应. 当状态代码可以表示多种含义时,该机制十分合适 (e.g, 400 (Bad Request) 可能表示缺少必需的标头或者标头格式不正确等等). 关于该错误正文机制的内容将在第 16 章中进行说明.

8.8. 命名空间操作对缓存验证器的影响

原文

需要注意的是, HTTP 响应标头"Etag""Last-Modified" (参见 [RFC2616#14.19] 与 [RFC2616#14.29]) 是按 URL (而不是按资源) 定义的, 并且客户端会用于缓存. 因此, 服务器必须确保执行任何影响 URL命名空间的操作 (比如 COPY, MOVE, DELETE, PUT, MKCOL) 能够满足它们的语义, 特别是:

  • 对于给定的 URL, 每次 GET 返回的表示发生变化时, "Last-Modified" 值必须递增 (在时间戳分辨率的限制内).
  • 对于给定的 URL, GET 请求返回的不同表示不得[MUST_NOT]共用相同的 "ETag".

事实上, 这意味着

  • 当该资源位于命名空间操作的目标命名空间内时, 服务器可能需要为每一个资源递增 "Last-Modified" 时间戳, 除非这个资源可以更有选择性地进行递增;
  • 同样地, 服务器可能需要重新分配这些资源"ETag" 值 (除非服务器按照某种方式分配实体标签, 以确保它们在服务器管理的整个 URL命名空间中是唯一的).

需要注意的是, 这些考虑因素也适用于特定的用例, 比如使用 PUT 在一个 URL 上创建新资源, 然而这个 URL 在之前被映射过, 但此后被删除.

最后, 从 HTTP标头中继承的的 WebDAV属性(比如 DAV:getetagDAV:getlastmodified) 必须按照 HTTP 中相应的行为规则进行操作.

译者注: 怎么理解这话 比如 <DAV:getetag>, <DAV:getlastmodified> 这类属性, e.g.

# 响应
HTTP/1.1 207 Multi-Status
Content-Type: text/xml; charset="utf-8"

<?xml version="1.0" encoding="utf-8"?>
<D:multistatus xmlns:D="DAV:">
  <D:response>
    <D:href>/document.txt</D:href>
    <D:propstat>
      <D:prop>
        <!-- 必须满足http中对etag的定义要求 -->
        <D:getetag>"123456789"</D:getetag>
        <!-- 必须按照getlastmodified属性的定义要求进行解析  -->
        <D:getlastmodified>Tue, 10 Aug 2023 14:30:00 GMT</D:getlastmodified>
      </D:prop>
      <D:status>HTTP/1.1 200 OK</D:status>
    </D:propstat>
  </D:response>
  <!-- ... other responses -->
</D:multistatus>

results matching ""

    No results matching ""