AIP-154 资源时效性验证

发布于:2025-02-28 ⋅ 阅读:(14) ⋅ 点赞:(0)

编号 154
原文链接 AIP-154: Resource freshness validation
状态 批准
创建日期 2019-07-24
更新日期 2019-07-24

在资源上执行某类操作之前,API往往需要确认客户端和服务器一致认定资源当前状态。例如,两个进程并行更新同一个资源可能产生竞态条件,后一个进程可能会“覆盖”前面进程的工作。

ETag给出了解决之道。服务器根据资源当前内容发送校验和,当客户端把校验和送回来时,服务器可以确保校验和匹配后处理请求。

指南

如果需要客户端在执行某些请求之前拥有最新的资源,资源 可以 包含 etag 域:

// A representation of a book.
message Book {
  // Other fields...

  // This checksum is computed by the server based on the value of other
  // fields, and may be sent on update and delete requests to ensure the
  // client has an up-to-date value before proceeding.
  string etag = 99;
}
  • etag域 必须 是字符串, 必须 命名为 etag 。
  • 资源 的etag域 不应 包含任何行为注解。
  • etag域 必须 由服务器输出,并且值 应当 符合RFC 7232
  • 如果用户发送的etag与当前etag值匹配,服务 必须 允许该请求(除非存在其他导致失败的原因)。
  • 如果用户发送的etag与当前etag值不匹配,服务 必须 发送 ABORTED 错误应答(除非存在优先级更高的错误。例如,如果用户未获授权则返回 PERMISSION_DENIED )。
  • 如果用户没有发送etag值,服务 应当 允许该请求。然而,具有强一致性或并行性要求的服务 可以 要求用户必须发送etag,拒绝缺少etag的请求,返回 INVALID_ARGUMENT 错误。

注意 ETag值 应当 按照RFC 7232要求包含引号。例如, "foo" 是有效的etag值,而 foo 不是。

声明友好资源

声明友好资源(AIP-128) 必须 包含 etag 域。

请求方法的Etag

有时,etag需要包含在请求消息中,而非资源本身。例如, Update 标准方法可以“借用”资源上的 etag 域,但 Delete 标准方法不行:

message DeleteBookRequest {
  // The name of the book.
  string name = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "library.googleapis.com/Book"
    }];

  // The current etag of the book.
  // If an etag is provided and does not match the current etag of the book,
  // deletion will be blocked and an ABORTED error will be returned.
  string etag = 2 [(google.api.field_behavior) = OPTIONAL];
}

在请求消息中, etag 域 应当 包含行为注解——要么是 REQUIRED ,要么是 OPTIONAL 。有关更多信息,请参考AIP-203

etag 域也 可以 用于自定义方法,类似前文示例。

强验证和弱验证

ETag可以是“强验证的”或“弱验证的”:

  • 强验证的etag意味着具有相同etag的两个资源是逐字节相同的。
  • 弱验证的etag意味着具有相同etag的两个资源是等同的,但可能在一些服务认为不重要的方面有所不同。

资源 可以 根据需要选择强验证或弱验证,但 应当 以文档记录具体行为。此外,根据RFC 7232规定,弱验证etag 必须 具有 W/ 前缀。

进一步阅读

  • 关于客户端库如何在失败时重试,请参考AIP-194

修订记录

  • 2021-04-01 将 FAILED_PRECONDITION 引用改为 ABORTED 。
  • 2021-03-05 将etag错误从 FAILED_PRECONDITION (即HTTP 400)改为 ABORTED (即HTTP 409)。
  • 2020-10-06 添加声明友好资源要求。
  • 2020-09-02 明确其他错误可能优先于 FAILED_PRECONDITION etag不匹配。
  • 2020-09-02 添加关于请求消息中的etag的指难。
  • 2019-09-23 将标题改为“资源时效性验证”。