denghuiquan / gg-apidesignguide Goto Github PK
View Code? Open in Web Editor NEWA Translation of google api design guide.
A Translation of google api design guide.
目录
HTTP Mapping HTTP映射
Use Cases 用例
Common Custom Methods 公共自定义方法
本章将讨论如何使用API设计的自定义方法。
除了5种标准方法外,自定义方法是指API方法。它们只能用于不能通过标准方法容易表达的功能。在一般情况下,API设计者应该选择标准方法优先于自定义方法,只要它是可行的。标准方法具有较简单和明确的语义,大多数开发人员都熟悉,所以它们更容易使用和更少的错误倾向。标准方法的另一个优点是API平台对标准方法有更好的理解和支持,如计费、错误处理、日志记录、监控等。
自定义方法可以与资源、集合或服务关联。它可以采取任意请求并返回任意响应,也支持流请求和响应。
对于自定义方法,他们应该使用以下通用HTTP映射:
https://service.name/v1/some/resource/name:customVerb
使用 :
而不是 /
将自定义谓词与资源名称分隔开来的原因是为了支持(更多的)任意路径。例如,撤销删除一个文件可以映射到 POST
/files/ a/long/file/name:undelete
。
选择HTTP映射时应使用以下准则:
HTTP POST
谓词,因为它具有最灵活的语义。HTTP PATCH
,但可以使用其他HTTP谓词。在这种情况下,方法必须遵循标准的HTTP语义的动词。HTTP GET
的自定义方法必须是幂等的并且没有副作用。例如,在资源上实现特殊视图的自定义方法应该使用HTTP GET
。:
组成的后缀结尾。body:“*”
子句和所有剩余的请求消息字段将映射到HTTP请求体。body
子句”,其余所有请求消息字段应映射到url查询参数。Warning: 如果服务实现多个API,API生产者必须小心创建服务配置,避免API之间的自定义谓词冲突。
// This is a service level custom method.
rpc Watch(WatchRequest) returns (WatchResponse) {
// Custom method maps to HTTP POST. All request parameters go into body.
option (google.api.http) = {
post: "/v1:watch"
body: "*"
};
}
// This is a collection level custom method.
rpc ClearEvents(ClearEventsRequest) returns (ClearEventsResponse) {
option (google.api.http) = {
post: "/v3/events:clear"
body: "*"
};
}
// This is a resource level custom method.
rpc CancelEvent(CancelEventRequest) returns (CancelEventResponse) {
option (google.api.http) = {
post: "/v3/{name=events/*}:cancel"
body: "*"
};
}
// This is a batch get custom method.
rpc BatchGetEvents(BatchGetEventsRequest) returns (BatchGetEventsResponse) {
// The batch get method maps to HTTP GET verb.
option (google.api.http) = {
get: "/v3/events:batchGet"
};
}
一些额外的场景,自定义方法可能是正确的选择:
重启虚拟机。 该设计供选方案可以是在重启集合中创建重启资源,这感觉不成比例的复杂,或“虚拟机具有可变状态,也就是说客户端可以从运行状态到重启状态的更新,其他的状态转换是可能的这样的开放的问题。 此外,重新启动是一个众所周知的概念,可以很好地转化为一个自定义的方法,直观地满足开发者的期望。
发送邮件。 创建电子邮件信息不一定要发送(草稿)。相比于设计供选方案(邮件移动到“发件箱”集合)的自定义方法的优点是更容易被API用户发现(了解),模型的概念更直接。
提拔员工。 如果作为一个标准的update
方法来实现,客户必须复制公司政策,以确保晋升过程中发生的正确的水平,在同一职业阶梯等。
批批处理方法。 对于性能关键方法,提供自定义批处理方法以减少每次请求开销可能是有帮助的。例如,accounts.locations.batchget
。
标准方法比自定义方法更适合的几个例子:
使用不同查询参数查询资源(使用标准列表(list)过滤方法)。
简单的资源属性更改(使用带字段掩码的标准更新(update)方法)。
驳回通知(使用标准删除(delete)方法)。
下面是有用的精选常用列表或自定义方法的名称。API设计师应该在引入自己的API之前考虑这些名称,以促进一致性。
方法名称 自定义谓词 HTTP谓词 注释
Cancel :cancel
POST
取消未完成的操作(生成、计算等)
BatchGet :batchGet
GET
多资源批处理。(详见清单描述)
Move :move
POST
将资源从一个父资源移动到另一个父资源。
Search :search
GET
替代不包含列表语义的数据获取列表。
Undelete :undelete
POST
还原以前删除的资源。推荐保留期为30天。
Editor huiquan @denghuiquan
2017-04-18 23:30 pM.
目录
Full Resource Name 完整资源名称
RelativeResource Name 相对资源名称
Resource ID 资源ID
Collection ID 集合ID
Resource Name vs URL 资源名称与URL的差异
Resource Name as String 字符串资源名称
在面向资源的API中,资源是命名实体,资源名称是它们的标识符。每个资源必须有它唯一的资源名称。资源名称由资源本身的ID、任何父资源的ID和它的API服务名称组成。下面我们来看一下资源ID以及如何构造资源名称。
gRPC API应该使用scheme-lessURIS作为资源名称。他们通常遵循其余的URL约定和行为就像网络文件路径。他们可以很容易地映射到REST URLs:详情见标准方法部分。
一个集合是一种包含同类型子资源列表的特殊的资源。例如,目录是文件资源的集合。集合的资源ID称为集合ID。
资源名称是使用集合ID和资源ID分层组织的,用正斜杠分隔。如果资源包含子资源,子资源的名字是通过指定父资源名称后跟子资源的ID,用正斜杠分隔形成的。
例子1:存储服务有一个桶(bucket)集合,每个桶都有一个对象(object)集合:
API Service Name | Collection ID | Resource ID | Collection ID | Resource ID
//storage.googleapis.com | /buckets | /bucket-id | /objects | /object-id
例子2:一个邮件服务有一个用户集合。每个用户有一个设置子资源,同时设置子资源有一系列其他的子资源,包括customFrom
:
API Service Name | Collection ID | Resource ID | Resource ID | Resource ID
//mail.googleapis.com | /users | /[email protected] | /settings | /customFrom
API生产者可以选择资源和集合ID的任何可接受值,只要它们在资源层次结构中是唯一的。您可以在下面找到更多选择适当的资源和集合ID的指导方针。
通过拆分资源名称,如名称、拆分(“/”)n,假设没有片段段包含任何正向斜杠,那么就可以得到单独的集合ID和资源ID。
由DNS兼容的API服务名称和资源路径组成的无计划(scheme-less )URI。资源路径也称为相对资源名称。例如:
"//library.googleapis.com/shelves/shelf1/books/book2"
API服务名称是为客户定位API服务端点的;它可能是一个指向内部唯一的服务的假DNS名称。如果API服务名称在上下文中是明显可见的,则通常使用相对资源名称。
一个不是由”/“开头的URI路径(path-noscheme)。它标识API服务中的资源。例如:
"shelves/shelf1/books/book2"
一个标识其父资源内的资源的非空URI片段(segment-nz-nc),请参见上面的例子。
资源名称中的尾随资源id可能有多个URI片段。例如:
Collection ID | Resource ID
files | /source/py/parser.py
API服务在可行的时候应该使用URL友好的资源ID。资源ID必须清楚地记录是否由客户机、服务器分配,或者不是。例如,文件名通常由客户端分配,而电子邮件ID通常由服务器分配。
一个标识其父资源内的集合资源的非空URI段(segment-nz-nc),请参见上面的例子。
由于集合ID经常出现在生成的客户端库中,所以它们必须符合以下要求:
RowValue
好过Value
。下列词汇应严格无条件避免:虽然完整资源名称类似正常网址,他们却不是同样的东西。可以通过不同版本的API和不同的API协议暴露单个资源。完整的资源名称没有指定这些信息,因此必须将其映射到特定的协议和API版本以供实际使用。
通过REST API使用完整资源名称,必须在服务名称之前添加HTTPS方案将其转换为其他URL,在资源路径之前添加API主版本,和经URL转义后的资源路径。例如:
// This is a calendar event resource name.
*"//calendar.googleapis.com/users/john smith/events/123"*
// This is the corresponding HTTP URL.
*"https://calendar.googleapis.com/v3/users/john%20smith/events/123"*
谷歌API必须使用字符串来表示资源名称,除非向后兼容是一个问题。资源名称应像正常文件路径一样处理,它们不支持%编码。
对于资源定义,第一个字段应该是资源名称的字符串字段,它应该被称为名称。
注意:其他与名城相关字段应避免混淆的名字,如display_name
,first_name
,last_name
,full_name
。
例如:
service LibraryService {
rpc GetBook(GetBookRequest) returns (Book) {
option (google.api.http) = {
get: "/v1/{name=shelves/*/books/*}"
};
};
rpc CreateBook(CreateBookRequest) returns (Book) {
option (google.api.http) = {
post: "/v1/{parent=shelves/*}/books"
body: "book"
};
};
}
message Book {
// Resource name of the book. It must have the format of "shelves/*/books/*".
// For example: "shelves/shelf1/books/book2".
string name = 1;
// ... other properties
}
message GetBookRequest {
// Resource name of a book. For example: "shelves/shelf1/books/book2".
string name = 1;
}
message CreateBookRequest {
// Resource name of the parent resource where to create the book.
// For example: "shelves/shelf1".
string parent = 1;
// The Book resource to be created. Client must not set the `Book.name` field.
Book book = 2;
}
注意:对于资源名称的一致性,前面的斜杠不能被任何URL模板变量捕获。例如,URL模板"/v1/{name=shelves/*/books/*}"
必须用"/v1{name=/shelves/*/books/*}"
代替。
Editor huiquan @denghuiquan
2017-03-26 14:20pM.
本节描述了一组标准的消息字段定义,当需要类似的概念时应使用该字段。这将确保相同的概念具有相同的名称和语义在不同的API。
Name Type Description
name string The name field should contain the relative resource name.
parent string For resource definitions and List/Create requests, the parent field should contain the parent relative resource name.
create_time Timestamp The creation timestamp of an entity.
update_time Timestamp The last update timestamp of an entity. Note: update_time is updated when create/patch/delete operation is performed.
delete_time Timestamp The deletion timestamp of an entity, only if it supports retention.
time_zone string The time zone name. It should be an IANA TZ name, such as "America/Los_Angeles". For more information, see https://en.wikipedia.org/wiki/List_of_tz_database_time_zones.
region_code string The Unicode country/region code (CLDR) of a location, such as "US" and "419". For more information, see http://www.unicode.org/reports/tr35/#unicode_region_subtag.
language_code string The BCP-47 language code, such as "en-US" or "sr-Latn". For more information, see http://www.unicode.org/reports/tr35/#Unicode_locale_identifier.
display_name string The display name of an entity.
title string The official name of an entity, such as company name. It should be treated as the formal version of display_name.
description string One or more paragraphs of text description of an entity.
filter string The standard filter parameter for List methods.
query string The same as filter if being applied to a search method (ie :search)
page_token string The pagination token in the List request.
page_size int32 The pagination size in the List request.
total_size int32 The total count of items in the list irrespective of pagination.
next_page_token string The next pagination token in the List response. It should be used as page_token for the following request. An empty value means no more result.
order_by string Specifies the result ordering for List requests.
request_id string A unique string id used for detecting duplicated requests.
resume_token string An opaque token used for resuming a streaming request.
labels map<string, string> Represents Cloud resource labels.
deleted bool If a resource allows undelete behavior, it must have a deleted field indicating the resource is deleted.
show_deleted bool If a resource allows undelete behavior, the corresponding List method must have a show_deleted field so client can discover the deleted resources.
update_mask FieldMask It is used for Update request message for performing partial update on a resource.
validate_only bool If true, it indicates that the given request should only be validated, not executed.
Command | Description |
---|---|
git status |
List all new or modified files |
git diff |
Show file differences that haven't been staged |
Editor huiquan @denghuiquan
2017-04-18 23:30 pM.
目录
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)方法将集合名称和零或多个参数作为输入,并返回与输入匹配的资源列表。它通常也被用于搜索资源。
列表适合于单个集合的数据,这些集合的大小是有界的,也不缓存。对于更广泛的情况,应使用自定义搜索(Search)方法。
一个批获取(如一个需要多个资源ID并返回这些ID对应的每个对象的方法)应该作为一个自定义Batchget实现的方法,而不是一个列表。但是,如果已有已提供相同功能的列表(List)方法,则可以重用列表(List)方法来达到此目的。如果你使用的是自定义batchget方法,它应该被映射到HTTP GET。
适用类型:分页,结果排序。
适用命名约定:筛选字段、结果字段。
HTTP的映射:
// 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方法接收资源名称、零个或多个参数,并返回指定的资源。
HTTP的映射:
// 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)方法接收集合名称、资源和零或多个参数。它在指定的集合中创建一个新资源,并返回新创建的资源。
如果API支持一次创建多个资源,它应该为每一种可以创建的资源的类型准备一个创建(Create)方法。
HTTP的映射:
parent
的字段来接收要创建资源的父资源名称。如果创建方法支持客户端指定的资源名称和资源已经存在,它要么失败(推荐错误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)方法中发生,而是应该由自定义方法处理。
HTTP的映射:
Fieldmask
字段命名update_mask
如果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)方法接收资源名称和零个或多个参数,并删除指定资源的删除(s)或计划(s)。删除(Delete)方法应该返回google.protobuf.Empty
。
注意,API不应依赖于删除方法返回的任何信息,因为它不能多次调用。
HTTP的映射:
对删除(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.
这个设计指南的目标是要帮助开发者设计出简单、一致、而且易用的网络化接口(API)。同时,它也有助于融合基于HTTP的协议的REST API和基于套接字协议的RPC API的设计。
传统上,人们在API 接口和方法方面来设计RPC API,如CORBA和Windows COM。随着时间的推移,越来越多的接口和方法被介绍了。最终的结果可能是数量众多的接口和方法,它们各不相同。开发者必须小心地学习了解每一种以便可以正确地使用这些接口。这既费时又容易出错。
REST的建筑风格最早是在2000推出的,主要是为配合HTTP / 1.1工作设计的。它的核心原则是定义命名资源,那样就可以使用少量的方法进行操作。资源和方法被称为API的名词和动词。用HTTP协议,将资源名称自然映射到URL,这样一来方法自然地映射到HTTP的获取、放置、修补和删除方法上。
在网络中,HTTP REST API 最近已经非常成功。在2010年, 大概74%的公共网络API属于HTTP REST API(或类REST API)。
虽然HTTP REST API在Internet上非常流行,但它们承载的流量比传统RPC API小。例如,在美国,大约有一半在高峰时间的互联网流量是视频内容,考虑到性能原因很少有人会考虑使用REST API提供这些内容。在内部数据中心中,许多公司使用基于套接字的RPC API来承载大部分网络流量,这可以比公共REST API高出一个数量级。
事实上,由于各种原因,RPC API和HTTP REST API都需要。理想的情况下,API平台应该为所有API提供最好的支持。这个设计指南帮助你设计和构建出符合此原则的API。它通过将面向资源的设计原则应用于通用API设计,同时定义了许多通用的设计模式,以提高可用性和减少复杂性。
注意:本设计指南解释了如何将REST原则应用于与编程语言、操作系统或网络协议无关的API设计中。它不是指导创建REST API的指南。
REST API被建模为单独可寻址资源的集合(API的名词)。资源可通过它们的资源名称来引用,并通过一组方法(也称为动词或操作)进行操作。
谷歌API(也称为REST方法)的标准方法是列表(List), 获取(Get), 创建(Create), 更新(Update), 以及删除(Delete)。自定义方法(也称为自定义谓词或自定义操作)也可用于为那些不容易映射到一个标准的方法的功能的API设计器,如数据库事务。
注意:自定义动词并不意味着创建自定义HTTP谓词以支持自定义方法。对于基于HTTP的API,它们只映射到最合适的HTTP谓词。
设计指南建议在设计面向资源的API时采取以下步骤(更多细节包括在以下部分):
一个面向资源的API通常被建模为资源层次结构,这些层次结构要么是一个简单的资源要么就是一个资源的集合。为了方便,它们通常分别被称为一个资源和一个集合。
例如,Gmail API有一个用户集合,每个用户拥有一个消息集合、一个线程集合、一个标签集合、一个配置文件资源和多个设置资源。
虽然存储系统和REST API之间有一些概念上的一致性,一个拥有面向资源API的服务不一定是个数据库,同时它在解释资源和方法方面有巨大的灵活性。例如,创建日历事件(资源)可以为与会者创建附加事件,向与会者发送电子邮件邀请,保留会议室,并更新视频会议日程。
面向资源的API的主要特点是它强调资源(数据模型)在资源(功能)上执行的方法。一个典型的面向资源API会用少量的方法公开大量资源。这些方法可以是标准方法,也可以是自定义方法。对于本指南,标准方法是:列表(List)、获取(Get)、创建(Create)、更新(Update)和删除(Delete)。
API函数自然地映射到标准方法之一,该方法应该在API设计中使用。对于不能够自然地映射到标准方法之一的功能,可以使用自定义方法。自定义方法提供了与传统RPC API相同的设计自由度,可用于实现通用的编程模式,如数据库事务或数据分析。
下面的章节介绍了一些关于如何将面向资源的API设计应用到大规模服务的真实世界的例子。
Gmail API服务实现了Gmail API并公开了大部分Gmail功能。它具有以下资源模型:
users/*
。每个用户都有以下资源。
users/*/messages/*
。users/*/threads/*
。users/*/threads/*
。users/*/history/*
。users/*/profile
。users/*/settings
pubsub.googleapis.com实现谷歌云服务的发布/订阅API,它定义了以下资源模型:
projects/*/topics/*
。projects/*/subscriptions/*
注意: 其他发布/订阅API的实现可以选择不同的资源命名方案。
Editor huiquan @denghuiquan
2017-03-23 01:25AM.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.