标准方法
目录
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.