自定义方法
本章将会讨论如何在API设计中使用自定义方法。
自定义方法指的是五个标准方法之外的API方法。他们应当仅用于标准方法不易表达的功能。一般而言,API设计者应当尽可能优先考虑使用标准方法,而不是自定义方法。标准方法相对更简单,定义完善的语义,并且开发者也更加熟悉;这使标准方法更易用,并且使用者更难犯错。使用标准方法的另一个优势是API平台会有更好的支持,如计费、错误处理、日志、监控等等。
自定义方法可以跟资源、集合或者服务关联。它可以接受任意请求,并返回任意结果;并支持流式的请求与结果。
HTTP映射
对于自定义方法,它们应该使用以下形式的HTTP映射
https://service.name/v1/some/resource/name:customVerb
使用:
而不是/
符号去分隔自定义动词跟资源名,可以让我们支持任意路径。比方说取消删除一个文件可以映射为POST /files/a/long/file/name:undelete
选择HTTP映射时,应当应用以下准则:
- 自定义方法应该使用HTTP POST,因为它含有最灵活的语义。
- 自定义方法可以使用其它HTTP动词(参考以下章节),但方法需要遵从该动词的标准HTTP语义。
- 请注意,使用HTTP
GET
的自定义方法必须是幂等并且无副作用。比方说,支持资源特定视图的自定义方法可以用HTTPGET
。 - 对应于资源名或者资源集合名的请求消息字段应当映射为URL路径
- URL路径必须以冒号 + 自定义动词结尾
- 如果HTTP动词允许请求体消息(如
POST
,PUT
,PATCH
, 或者其它HTTP动词),那么自定义方法的HTTP配置必须使用body: "\*"
,并且其它所有剩余的请求消息自动应当映射到请求体中。(译者注:TODO) - 如果HTTP动词不允许请求体消息(如
GET
,DELETE
),那么自定义方法的HTTP配置就绝不可以使用body
,并且其它所有剩余的请求消息字段自动应当映射到URL查询参数中。
警告:如果一个服务实现了多套API,API的生产者必须谨慎的创建服务配置,以避免API之间的自定义动词相互冲突。
// 这是一个服务级别的自定义方法。
rpc Watch(WatchRequest) returns (WatchResponse) {
// 自定义方法映射到HTTP POST。所有请求参数通过body传递。
option (google.api.http) = {
post: "/v1:watch"
body: "*"
};
}
// 这是一个资源集合级别的自定义方法。
rpc ClearEvents(ClearEventsRequest) returns (ClearEventsResponse) {
option (google.api.http) = {
post: "/v3/events:clear"
body: "*"
};
}
// 这是一个资源级别的自定义方法。
rpc CancelEvent(CancelEventRequest) returns (CancelEventResponse) {
option (google.api.http) = {
post: "/v3/{name=events/*}:cancel"
body: "*"
};
}
// 这是批量获取的自定义方法。
rpc BatchGetEvents(BatchGetEventsRequest) returns (BatchGetEventsResponse) {
// 批量获取方法映射到HTTP GET
option (google.api.http) = {
get: "/v3/events:batchGet"
};
}
使用场景
某些场景下,自定义方法是合理的选择:
- 重启一台虚拟机 另外一种实现方式是:”在重启集合中创建一个新的重启资源”,这让人感觉繁冗的过份。又或者是”虚拟机有客户端能从运行中跟重启中切换的可变状态”?这又会让人困惑是否还其他潜在的状态改变。重启是一个被广泛接受的概念,直接将其设为一个自定义方法,是符合开发者预期的。
- 发送邮件 创建一封电子邮件并不意味着要发送它,也可以仅是存为草稿。比较起其它的设计方式(把邮件移动到”发件箱”集合中),自定义方法的优势是更容易被API使用者察觉,建模也更直接。
- 提拔一位同事 (corpeng) 如果使用标准Update方法,客户端需要复制企业提拔流程中的管理政策,以确保提拔是在正确的等级,并属于同一职业阶梯等等。
- 批处理的方法对于性能关键方法,可以提供自定义批处理方法以减少每次请求开销。例如,accounts.locations.batchget。
有的时候,标准方法则比自定义方法更适用:
- 使用不同的参数查询资源 (使用标准
list
方法,跟标准list过滤)。 - 简单资源属性修改(使用
update
方法跟字段掩码)。 - 关闭一个通知(使用标准
delete
方法)。
常见自定义方法
API设计者应当考虑使用以下一些常见或者有用的自定义方法名;而不是直接定义新的名字,以提高不同API之间的一致性。
方法名 | 自定义动词 | HTTP动词 | 备注 |
---|---|---|---|
Cancel | :cancel | POST | 取消一个未完成的操作(构建,计算等等) |
BatchGet | :batchGet | GET | 批量获取多个资源(查阅List 标准方法中的详细描述) |
Move | :move | POST | 将一个资源从一个父级移到另一个 |
Search | :search | GET | List 的语义不足够时,搜索获取数据 |
Undelete | :undelete | POST | 恢复之前删除的数据;推荐的数据的保留时间是30天。 |