Rest API - 方法

最后更新:2020-09-27

1. 标准方法

我们定义五个标准方法,包括了List, Get, Create, Update, and Delete。很多不同类型的API都拥有非常类似的语义,把它们归纳为标准方法能够显著降低复杂度并提高一致性,我们实行的大部分API属于标准方法。标准方法更容易学习和使用。 以下表格描述了如何将标准方法映射为REST方法,也就是所谓的CRUD方法:

方法 HTTP方法映射 HTTP请求体 HTTP返回体
List GET <集合URL> 资源 列表
Get GET <资源URL> 资源
Create POST <集合URL 资源 资源
Update PUT or PATCH <资源URL> 资源 资源
Delete DELETE <资源URL>

Delete方法如果并没有立刻删除响应的资源(例如创建一个耗时删除操作或者更新标识),它的响应应该包括耗时操作或更新后的资源。

如果请求无法在单个API调用时间段内完成时,标准方法可以返回一个耗时操作。

1.1. List

List方法接受一个集合名,零或者多个参数,根据输入返回相应的资源列表。它也经常被用作搜索资源。

List适用于量有限且无缓存的单一集合数据查询;若需要更广的应用,应该用自定义方法Search。

批量获取(如接受多个资源ID并返回每个ID对象的方法)应该使用自定义方法BatchGet实现,而不是List方法。但如果你已经有了提供相似功能的List方法,你也可以继续使用。如果你使用自定义的BatchGet方法,应该确保它映射为HTTP GET方法。

使用常见模式:分页,结果排序。

适用命名约定:过滤字段,结果字段。

HTTP 映射

  • List方法必须使用HTTP Get方法。
  • 请求消息字段接收资源名称集合,而相关资源应该映射为URL路径。如果集合名称映射到URL路径,URL模板中的最后一段(即集合ID)必须为文字。
  • 其他所有请求消息字段应当映射为URL请求参数
  • 没有请求体,即API配置中不应该声明请求体
  • 返回体应该包含资源集合以及可选的元数据

1.2 Get

Get方法接受一个资源名,零到多个参数,返回指定的资源。

HTTP 映射

  • Get方法必须使用HTTP Get方法。
  • 接收资源名称的请求消息字段(可多个)应该映射到URL路径中。
  • 其他所有请求消息字段应当映射到URL查询参数中。
  • 无请求体,即API配置中绝对不可以出现请求体声明。
  • 返回资源应当映射到返回体中

1.3. Create

Create方法接受一个集合名,一个资源,并且有零或多个参数;然后在相应集合中创建新的资源,最后返回新创建的资源。

如果API支持创建资源,那么它应该有Create方法用于创建各种类型的资源。

HTTP 映射

  • Create方法必须使用HTTP POST方法。
  • 请求消息应该有一个名为parent的字段,以接受父级资源名,当前资源将在父资源下创建
  • 其他所有请求消息字段应当映射到URL查询参数中。
  • 请求可以包括一个名为_id的字段,以允许调用方选择客户端分配的ID,此字段必须映射为URL查询参数
  • 包含资源的请求消息字段应该映射到请求体中
  • 返回的资源应当映射到整个返回体中。

如果Create方法支持客户端指定资源名,并且相应资源已经存在;那么它应该返回错误(推荐使用google.rpc.Code.ALREADY_EXISTS错误代码),或使用其它服务器指定的资源名:文档中需要清晰说明被创建的资源名可能跟传入的资源名不同。

1.4. Update

Update方法接受包括一个资源的请求消息,并且有零或多个参数。它更新相应资源以及它的属性;返回更新后的资源。

可变的资源属性应当被Update方法修改,除非属性包含资源的名称或者父资源。所有的重命名或者移动资源操作一定不能用Update方法,这些应当用自定义方法处理。

HTTP 映射

  • 标准的Update方法应该支持部分资源更新,并使用 HTTP PATCH方法以及名为update_mask的FieldMask字段。
  • 如果Update方法需要更高级的修复语义,比方说给重复字段增补新值,那么应该使用自定义方法。
  • 如果Update方法仅支持完整的资源更新,它必须使用HTTP PUT;但是强烈不推荐这么做,因为这会造成添加新资源字段时的兼容性问题。
  • 接受资源名的字段必须映射到URL路径中;字段也可以包含在资源消息中
  • 包含资源的请求消息中字段必须映射到请求体中。
  • 其他所有请求消息字段必须映射到URL查询参数中。
  • 返回的结果必须是更新后的资源。

如果API允许客户端指定资源名,服务器可以允许客户端指定一个不存在的资源名并创建新的资源。否则,使用不存在的资源名时Update方法应该报错。如果不存在资源是唯一的错误条件,那么错误码应该用NOT_FOUND

API如果有Update方法,并且支持资源创建的话,就应该提供Create方法;以避免调用者误以为Update方法是创建资源的唯一方式。

1.5. Delete

Delete方法接受一个资源名,零或多个参数;然后删除,或者安排删除相应的资源。Delete方法应该返回google.protobuf.Empty。

注意API不应该依赖于Delete方法返回的任何信息,因为它不能被反复调用(译者注:因为资源可能已经被删除了)。

HTTP 映射

  • Delete方法必须使用HTTP DELETE方法
  • 对应于资源名称的请求消息字段(可多个)应该绑定到URL路径中。
  • 其他所有请求消息字段应当映射到URL查询参数中。
  • 无请求体,即API配置中绝对不可以出现请求体声明。
  • 如果Delete方法立刻删除除资源,它应该返回空。
  • 如果Delete方法开启了一个耗时操作,它应该返回这个耗时操作
  • 如果Delete方法仅是把资源标记为删除,它需要返回更新后的资源

调用Delete方法必须是幂等的,但返回值可以不同。任意次数的Delete请求应当使得一个资源(最终)被删除,但只有第一次请求获得成功的返回值,后续的请求应当返回google.rpc.Code.NOT_FOUND.

1.6. 自定义方法

自定义方法指的是五个标准方法之外的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的自定义方法必须是幂等并且无副作用。比方说,支持资源特定视图的自定义方法可以用HTTP GET。
  • 对应于资源名或者资源集合名的请求消息字段应当映射为URL路径。
  • URL路径必须以冒号 + 自定义动词结尾。
  • 如果HTTP动词允许请求体消息(如 POST, PUT, PATCH, 或者其它HTTP动词),那么自定义方法的HTTP配置必须使用body: “*“,并且其它所有剩余的请求消息自动应当映射到请求体中。
  • 如果HTTP动词不允许请求体消息(如 GET, DELETE),那么自定义方法的HTTP配置就绝不可以使用body,并且其它所有剩余的请求消息字段自动应当映射到URL查询参数中。。

常见自定义方法

API设计者应当考虑使用以下一些常见或者有用的自定义方法名;而不是直接定义新的名字,以提高不同API之间的一致性。

方法名 自定义动词 HTTP动词 备注
Cancel :cancel POST 取消一个未完成的操作(构建,计算等等)
BatchGet :batchGet GET 批量获取多个资源
Move :move POST 将一个资源从一个父级移到另一个
Search :search GET List的语义不足够时,搜索获取数据
Undelete :undelete POST 恢复之前删除的数据;推荐的数据的保留时间是30天。

2. 标准字段

本节描述了在需要类似概念时应使用的一组标准消息字段定义。 这将确保相同的概念在不同的API上具有相同的名称和语义。

字段名 类型 描述
name string name字段应该包含相对资源名
parent string 对于资源定义和List/Create请求,parent字段应包含父级相对资源名
create_time Timestamp 一个实体的创建时间戳
update_time Timestamp 一个实体的最后更新时间戳;注意update_time会被create/patch/delete等操作更新
delete_time Timestamp 实体的删除时间戳,仅当支持保留时。
time_zone string 时区名,它应该符合IANA时区标准,如”America/Los_Angeles”。请参阅 https://en.wikipedia.org/wiki/List_of_tz_database_time_zones.
region_code string 位置的Unicode国家/地区代码(CLDR),例如“US”和“419”。请参阅 http://www.unicode.org/reports/tr35/#unicode_region_subtag。
language_code string BCP-47语言代码,如“en-US”或“sr-Latn”。请参阅http://www.unicode.org/reports/tr35/#Unicode_locale_identifier。
display_name string 一个实体显示的名称
title string 实体的正式名称,例如公司名称。 它应该被视为正规版本的display_name
description string 一个实体的详细文字描述
filter string List方法的标准过滤参数
query string 应用于Search方法的(也就是说 :search)过滤参数
page_token string List请求的数据分页令牌
page_size int32 List请求的数据分页大小
total_size int32 列表中的总条目数,不考虑分页
next_page_token string List返回结果中下一个分页的令牌。它应该在后续请求中传递为page_token参数;空值意味着没有更多数据
request_id string 用于检测重复请求的唯一字符串id
resume_token   用于恢复流式传输请求的隐含令牌
labels map 表示云资源的标签
deleted bool 如果资源允许取消删除,则它必须有deleted字段表示资源是否已被删除
show_deleted bool 如果资源允许取消删除,相应的List方法必须有一个show_deleted字段,以便客户端发现已删除的资源。
validate_only bool 如果为true,则表示给定的请求仅需要被检验,而不是被执行。

3. 参考资料

Google API Design Guide (谷歌API设计指南)中文版

Edgar

Edgar
一个略懂Java的小菜比