Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GAD03: Standard Methods 标准方法 #3

Open
denghuiquan opened this issue Mar 26, 2017 · 0 comments
Open

GAD03: Standard Methods 标准方法 #3

denghuiquan opened this issue Mar 26, 2017 · 0 comments

Comments

@denghuiquan
Copy link
Owner

denghuiquan commented Mar 26, 2017

标准方法

目录
List 列表
Get 获取
Create 创建
Update 更新
Delete 删除

本章定义了标准方法的概念,包括列表、获取、创建、更新和删除。之所以有标准方法的原因是许多API方法在广泛的API之间有非常相似的语义。通过将这些类似的API融合到标准方法中,我们可以大大减少复杂性和提高一致性。在谷歌API库中的API方法中,超过70%是标准方法,这使得它们更容易学习和使用。

下表描述了如何将它们映射到其他的方法,也被称为CRUD方法:
Method | HTTP Mapping | HTTP Request Body | HTTP Response Body
List | GET | | Empty | Resource* list
Get | GET | | Empty | Resource*
Create | POST | | Resource | Resource*
Update | PUT or PATCH | | Resource | Resource*
Delete | DELETE | | Empty | Empty**

*从列表,获取,创建和更新方法中返回的资源可能包含部分数据,如果方法支持字段掩码(标记),该字段指定要返回的字段子集。在某些情况下,API平台为所有方法原生支持字段掩码(标记)。

*不立即删除资源(如更新标志或创建长时间删除操作)的删除方法返回的响应应包含长运行操作或修改后的资源。

一个标准方法也可以为在单个API调用的时间范围内未完成的请求返回一个长运行操作。

以下各节详细描述了每个标准方法。这些示例显示了在.proto文件中定义的方法,这些方法具有针对http映射的特殊注释。您可以在谷歌API库中找到许多生产中使用标准方法的例子。


List

列表(List)方法将集合名称和零或多个参数作为输入,并返回与输入匹配的资源列表。它通常也被用于搜索资源。

列表适合于单个集合的数据,这些集合的大小是有界的,也不缓存。对于更广泛的情况,应使用自定义搜索(Search)方法。

一个批获取(如一个需要多个资源ID并返回这些ID对应的每个对象的方法)应该作为一个自定义Batchget实现的方法,而不是一个列表。但是,如果已有已提供相同功能的列表(List)方法,则可以重用列表(List)方法来达到此目的。如果你使用的是自定义batchget方法,它应该被映射到HTTP GET。

适用类型:分页,结果排序。
适用命名约定:筛选字段、结果字段。

HTTP的映射:

  • 列表(List)方法必须使用HTTP GET谓词。
  • 请求消息字段接收将被列出资源的集合的名称,该映射应映射到URL路径。如果集合名称映射到URL路径,URL模板的最后一段(集合ID)必须是文本。
  • 所有剩余的请求消息字段应映射到url查询参数。
  • 没有请求体,API配置不能声明正文子句。
  • 响应主体应该包含一个资源列表以及可选元数据。
// Lists all the books on a given shelf.
rpc ListBooks(ListBooksRequest) returns (ListBooksResponse) {
  // List method maps to HTTP GET.
  option (google.api.http) = {
    // The `parent` captures the parent resource name, such as "shelves/shelf1".
    get: "/v1/{parent=shelves/*}/books"
  };
}

message ListBooksRequest {
  // The parent resource name, for example, "shelves/shelf1".
  string parent = 1;

  // The maximum number of items to return.
  int32 page_size = 2;

  // The next_page_token value returned from a previous List request, if any.
  string page_token = 3;
}

message ListBooksResponse {
  // The field name should match the noun "books" in the method name.  There
  // will be a maximum number of items returned based on the page_size field
  // in the request.
  repeated Book books = 1;

  // Token to retrieve the next page of results, or empty if there are no
  // more results in the list.
  string next_page_token = 2;
}

Get

GET方法接收资源名称、零个或多个参数,并返回指定的资源。

HTTP的映射:

  • GET方法必须使用HTTP GET谓词。
  • 接收资源名称的请求消息字段应映射到URL路径。
  • 所有剩余的请求消息字段应映射到url查询参数。
  • 没有请求体,API配置不能声明正文子句。
  • 返回的资源应映射到整个响应体。
// Gets the specified book.
rpc GetBook(GetBookRequest) returns (Book) {
  // Get maps to HTTP GET. Resource name is mapped to the URL. No body.
  option (google.api.http) = {
    // Note the URL template variable which captures the multi-segment resource
    // name of the requested book, such as "shelves/shelf1/books/book2"
    get: "/v1/{name=shelves/*/books/*}"
  };
}

message GetBookRequest {
  // The field will contain name of the resource requested, for example:
  // "shelves/shelf1/books/book2"
  string name = 1;
}

Create

创建(Create)方法接收集合名称、资源和零或多个参数。它在指定的集合中创建一个新资源,并返回新创建的资源。
如果API支持一次创建多个资源,它应该为每一种可以创建的资源的类型准备一个创建(Create)方法。

HTTP的映射:

  • 创建(Create)方法必须使用HTTP POST动词。
  • 请求消息应该有一个名为parent的字段来接收要创建资源的父资源名称。
  • 所有剩余的请求消息字段应映射到url查询参数。
  • 请求可能包含一个名为_id以允许调用者选择客户分配的ID。该字段必须映射到URL查询参数。
  • 包含资源的请求消息字段应映射到请求主体。如果请求体的HTTP配置条款用于创建方法,请求体:“<resource_field>“表单必须用。
  • 返回的资源应映射到整个响应体。

如果创建方法支持客户端指定的资源名称和资源已经存在,它要么失败(推荐错误google.rpc.Code.ALREADY_EXISTS),要么使用不同的服务器指定的资源名称,同时文档应该讲清楚创建的资源名称可能与传入的资源名称不同。

rpc CreateBook(CreateBookRequest) returns (Book) {
  // Create maps to HTTP POST. URL path as the collection name.
  // HTTP request body contains the resource.
  option (google.api.http) = {
    // The `parent` captures the parent resource name, such as "shelves/1".
    post: "/v1/{parent=shelves/*}/books"
    body: "book"
  };
}

message CreateBookRequest {
  // The parent resource name where the book to be created.
  string parent = 1;

  // The book id to use for this book.
  string book_id = 3;

  // The book resource to create.
  // The field name should match the Noun in the method name.
  Book book = 2;
}

rpc CreateShelf(CreateShelfRequest) returns (Shelf) {
  option (google.api.http) = {
    post: "/v1/shelves"
    body: "shelf"
  };
}

message CreateShelfRequest {
  Shelf shelf = 1;
}

Update

更新(Update)方法接收包含资源和零或多个参数的请求消息。它更新指定的资源及其属性,并返回更新的资源。
可变资源属性应该由更新(Update)方法更改,除包含资源名称或父属性的属性除外。任何重命名或移动资源的功能不能在更新(Update)方法中发生,而是应该由自定义方法处理。

HTTP的映射:

  • 标准的更新Update方法应该支持部分资源的更新,并使用HTTP动词PATCH与Fieldmask字段命名update_mask
  • 更新(Update)方法,需要更先进的修补(patching)语义,如添加到重复字段,应通过自定义方法提供。
  • 如果更新(Update)方法只支持完全资源更新,则必须使用HTTP谓词PUT。 但是,非常遗憾,因为它在添加新资源字段时存在向后兼容性问题。
  • 接收资源名称的消息字段必须映射到URL路径。字段可能在资源消息本身中。
  • 包含资源的请求消息字段必须映射到请求主体。
  • 所有剩余的请求消息字段必须映射到url查询参数。
  • 响应消息必须是更新的资源本身。

如果API接受客户端分配的资源名称,服务器可能允许客户端指定不存在的资源名称并创建新资源。否则,更新方法将因不存在资源名称失败。如果这是唯一的错误条件则应该使用错误代码NOT_FOUND

具有支持资源创建的更新(Update)方法的API也应该提供创建(Create)方法。理由是,如果更新(Update)方法是唯一的方法来做到这一点,那就不清楚如何创建资源了。

rpc UpdateBook(UpdateBookRequest) returns (Book) {
  // Update maps to HTTP PATCH. Resource name is mapped to a URL path.
  // Resource is contained in the HTTP request body.
  option (google.api.http) = {
    // Note the URL template variable which captures the resource name of the
    // book to update.
    patch: "/v1/{book.name=shelves/*/books/*}"
    body: "book"
  };
}

message UpdateBookRequest {
  // The book resource which replaces the resource on the server.
  Book book = 1;

  // The update mask applies to the resource. For the `FieldMask` definition,
  // see https://developers.google.com/protocol-buffers/docs/reference/google.protobuf#fieldmask
  FieldMask update_mask = 2;
}

Delete

删除(Delete)方法接收资源名称和零个或多个参数,并删除指定资源的删除(s)或计划(s)。删除(Delete)方法应该返回google.protobuf.Empty

注意,API不应依赖于删除方法返回的任何信息,因为它不能多次调用。

HTTP的映射:

  • 删除(Delete)方法必须使用HTTP谓词DELETE。
  • 接收资源名称的请求消息字段应映射到URL路径。
  • 所有剩余的请求消息字段应映射到url查询参数。
  • 没有请求体,API配置不能声明正文子句。
  • 如果删除(Delete)方法立即移除资源,它应该返回一个空响应。
  • 如果删除(Delete)方法启动了长时间运行操作,则应返回长时间运行操作。
  • 如果删除(Delete)方法只标记资源被删除,它应该返回更新的资源。

对删除(Delete)方法的调用实际上是幂等的,但不需要产生相同的响应。任何数量的删除(Delete)请求应导致资源(最终)删除,但只有第一个请求会导致一个成功的代码,后续请求的结果应返回一个google.rpc.Code.NOT_FOUND

rpc DeleteBook(DeleteBookRequest) returns (google.protobuf.Empty) {
  // Delete maps to HTTP DELETE. Resource name maps to the URL path.
  // There is no request body.
  option (google.api.http) = {
    // Note the URL template variable capturing the multi-segment name of the
    // book resource to be deleted, such as "shelves/shelf1/books/book2"
    delete: "/v1/{name=shelves/*/books/*}"
  };
}

message DeleteBookRequest {
  // The resource name of the book to be deleted, for example:
  // "shelves/shelf1/books/book2"
  string name = 1;
}

Editor huiquan @denghuiquan
2017-04-05 15:25pM.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant