tommwq.work/aip

AIP-133 标准方法:Create

· [tommwq@126.com]
编号 133
原文链接 https://google.aip.dev/133
状态 批准
创建日期 2019-01-23
更新日期 2019-01-23

REST API通常向集合URI(如 /v1/publishers/{publisher}/books )发出POST请求,在集合中创建新资源。

面向资源设计(AIP-121)提供Create方法,遵循这一模式。这些接口接受上级集合和欲创建资源(可能还有其他参数),返回新建的资源。

指南

API通常 应当 为资源提供Create方法,除非对用户没有实际意义。Create方法的目的是在现有集合中创建新资源。

Create方法使用以下模式指定:

rpc CreateBook(CreateBookRequest) returns (Book) {
  option (google.api.http) = {
    post: "/v1/{parent=publishers/*}/books"
    body: "book"
  };
  option (google.api.method_signature) = "parent,book";
}
  • 接口名字 必须 以单词Create开头,其余部分 应当 是目标资源的单数形式。
  • 请求消息 必须 与接口名字一致,并带有 Request 后缀。
  • 应答消息 必须 是资源本身。不存在 CreateBookResponse
    • 应答 应当 包括完整资源数据, 必须 包括所有支持的域,仅输入域除外(参考AIP-203)。
    • 如果Create接口是耗时创建,应答消息 必须 是解析为资源自身的 google.longrunning.Operation
  • HTTP动词 必须POST
  • 接受新资源的集合 应当 映射到URI路径。
    • 集合的上级资源 应当 称为 parent应当 是URI路径中唯一的变量。
    • 集合标识符(例子中的 books必须 是字面值字符串。
  • google.api.http 注解 必须 包含 body 键, 必须 映射到请求消息的资源域。
    • 所有其他域 应当 映射到URI查询参数。
  • 应当 存在唯一的 google.api.method_signature 注解,值为 "parent,{resource},{resource}_id" 。如果不需要传递资源标识,值为 "parent,{resource}"
  • 如果API在管理平面上运行,则操作应具有强一致性:创建操作执行完毕必须意味着所有用户可设定值,以及资源存在性都已达到稳定状态;在读取资源状态时,将返回一致的应答。

请求消息

创建方法实现了一个常见的请求消息模式:

message CreateBookRequest {
  // The parent resource where this book will be created.
  // Format: publishers/{publisher}
  string parent = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      child_type: "library.googleapis.com/Book"
    }];

  // The ID to use for the book, which will become the final component of
  // the book's resource name.
  //
  // This value should be 4-63 characters, and valid characters
  // are /[a-z][0-9]-/.
  string book_id = 2 [(google.api.field_behavior) = REQUIRED];

  // The book to create.
  Book book = 3 [(google.api.field_behavior) = REQUIRED];
}
  • 必须 包含 parent 域,待创建资源是顶级资源的除外。域名字 应当parent
  • 管理平面资源必须包含 {resource}_id 域,数据平面资源 应当 包含此域。
  • 必须 包含 resource 域, 必须 映射到 POST 主体。
  • 请求消息 不得 包含任何其他必需域, 不应 包含其他可选域,本AIP或其他AIP另有要求的除外。

耗时创建

有些资源创建过程所需要的时间,超过通常合理的API应答时间。此时API应使用耗时操作(AIP-151):

rpc CreateBook(CreateBookRequest) returns (google.longrunning.Operation) {
  option (google.api.http) = {
    post: "/v1/{parent=publishers/*}/books"
    body: "book"
  };
  option (google.longrunning.operation_info) = {
    response_type: "Book"
    metadata_type: "OperationMetadata"
  };
}
  • 应答类型 必须 设定为资源(如果接口不是耗时操作,则返回类型是资源自身)。
  • 必须指定 response_typemetadata_type 域。

重要 声明友好资源(AIP-128应当 使用耗时操作。如果请求实际立即完成,服务可以返回设定为已完成的耗时操作对象。

用户设定标识

如果在管理平面运行,API 必须 允许用户在创建时设定资源标识(资源名字的最后一段)。

数据平面,API 应当 允许用户设定标识。特殊情况应遵守以下行为:

  • 数据平面资源允许存在完全相同的记录,无需区分二者(例如没有主键的表中的数据行)。
  • 数据平面资源不会在声明式客户端中使用。

API可以允许 {resource}_id 域具有可选域行为,并在未设定时由系统生成标识。

例如:

// Using user-specified IDs.
publishers/lacroix/books/les-miserables

// Using system-generated IDs.
publishers/012345678-abcd-cdef/books/12341234-5678-abcd
  • {resource}_id必须 包含在请求消息中,而非资源中。
    • 可以 是必需域或可选域。如果是必需域, 应当 包括相应的注解。
  • 必须 忽略资源的 name 域。
  • 接口 应当 包含唯一的 google.api.method_signature 注解。如果待创建资源不是顶级资源,其值为 "parent,{resource},{resource}_id" ;如果待创建资源是顶级资源,其值为 "{resource},{resource}_id"
  • 文档应解释所接受的格式,且格式应遵循AIP-122中的资源名字格式指南。
  • 如果用户试图创建可能导致名字冲突的资源,服务 必须 返回 ALREADY_EXISTS 错误。
    • 但是,如果用户没有权限查看导致冲突的资源,服务 必须 返回 PERMISSION_DENIED 错误。

注意 对于REST API,用户指定标识域 {resource}_id 作为请求URI的查询参数提供。

错误

参考错误,特别是何时使用PERMISSION_DENIED和NOT_FOUND错误

进一步阅读

  • 关于在Create方法中确保幂等性,请参考AIP-155
  • 关于涉及Unicode的资源名字,请参考AIP-210

理由

要求用户设定标识

声明式客户端使用资源标识作为更新资源和冲突解决的方法。缺少用户设定标识意味着客户端无法找到资源,除非在本地存储标识符,并且可能导致重新创建资源。这反过来对所有引用资源的其他资源产生了关联影响,迫使下游资源更新引用的标识。

使用用户设定标识还意味着客户端可以预先生成资源名字,并在其他资源中引用它。

修订记录

  • 2023-10-20 说明 {resource}_id 仅对管理平面资源是必需的。
  • 2023-08-24 添加一致性要求。
  • 2023-05-11resource_id 相关指南改为 必须
  • 2022-11-04 引用AIP-193中的错误指南,类似其他CRUDL AIP。
  • 2022-06-02 修改缀描述,消除多余的“-”。
  • 2020-10-06 添加声明友好指南。
  • 2020-08-14 更新错误指南,使用permission denied替换forbidden。
  • 2020-06-08 添加关于返回完整资源的指南。
  • 2019-11-22 添加关于发送重复名字时使用何种错误的说明。
  • 2019-10-18 添加关于注解的指南。
  • 2019-08-01 将示例从“shelves”更改为“publishers”,以提供更好的资源所有权示例。
  • 2019-06-10 添加耗时创建指南。
  • 2019-05-29 添加禁止在标准方法中使用任意域的规则。