[Design]-API设计指南


本篇摘选自《Google API Design Guide》。

面向资源设计

API设计要遵循简单、一致、易用的原则。

在REST架构中资源与方法可视为API的动词名词;在HTTP REST API中,资源名称对应于URL,而方法对应于HTTP中的GET/POST/PUT/PATCH/DELETE

REST API

一组REST API被建模为一组可独立寻址的资源,并通过资源名称被引用,通过一组方法来操作。

设计流程

面向资源的API设计可使用以下步骤:

  • 确定API提供什么类型的资源;
  • 确定资源间的关系;
  • 根据资源类型和关系确定资源命名方案;
  • 明确资源的schema;
  • 给资源添加最少的方法集;

资源

面向资源的API通常被建模为一个资源层次结构;每个节点可以是一个简单资源或一组资源。资源组为:

  • 资源组包含相同类型的一系列资源;
  • 资源有相同的状态,可以有零个或多个子资源。

方法

典型的面向资源的API通过少量方法暴露大量资源;常用的有List/Get/Create/Update/Delete

资源命名

资源名称是资源的标识符,每个资源必须有其唯一的资源名称。资源名称由资源ID本身、父资源的ID和资源对应的API服务名称组成。

资源组是一种特殊的资源,它包含一组相同类型的子资源。资源名称使用组ID和资源ID分层组织,以斜杠/分割。

如一个存储服务有一组bucket,每一个bucket有一组objects

API资源名称组ID资源ID组ID资源ID
//storage.googleapis.com/bucketsbucket-idobjectsobject-id

资源ID

资源ID也会出现在客户端库里,需满足以下要求:

  • 必须是有效的C/C++标识符;
  • 必须是驼峰命名的(组资源名称要使用复数形式),首字母小写;
  • 必须使用清晰建模的英文词语;
  • 避免或者限定过于笼统的词语:如未限定的Element、Item、Value、Type等。

标准方法

标准方法映射为REST方法:

方法HTTP 方法映射HTTP 请求体HTTP 返回体
ListGET <集合URL>资源* 列表
GetGET <资源URL>资源*
CreatePOST <集合URL>资源资源*
UpdatePUT or PATCH <资源URL>资源资源*
DeleteDELETE <资源URL>空**

List

List方法接受一个集合名,零或多个参数,根据输入返回相应的资源列表;适用于数量有限且无缓存的单一集合数据查询。更广泛的应用,应自定义方法Search

批量获取(接受多个资源ID,并返回对应的每个对象)应使用自定义方法BatchGet,且映射为HTTP Get方法。

自定义

自定义方法命名(非标准方法不能满足要求时,要使用一些常见或有用的自定义方法):

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

标准字段

标准消息字段定义:

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

错误

当API方式错误时,返回一个错误状态给客户端:

message Status {
  // A simple error code that can be easily handled by the client. 
  int32 code = 1;
  // A developer-facing human-readable error message. It should
  // both explain the error and offer an actionable resolution to it.
  string message = 2;
  // Additional error information that the client code can use to handle
  // the error, such as retry delay or a help link.
  repeated google.protobuf.Any details = 3;
}

错误代码应统一定义。

错误消息

错误消息应帮助用户方便、快速地理解和解决API错误,编写错误消息时,一般应遵循:

  • 不要假定用户是API专家:用户可能是客户端开发人员、操作人员、IT人员或程序最终用户;
  • 不要假定用户了解服务实现或错误上下文;
  • 若可能,应构造错误消息,以便技术用户可以响应错误并更正;
  • 保持错误消息的简洁:需要时可提供链接,帮助用户反馈或获取更新信息。

HTTP映射

HTTP的错误使用以下JSON格式表示:

{
  "error": {
    "code": 401,
    "message": "Request had invalid credentials.",
    "status": "UNAUTHENTICATED",
    "details": [{
      "@type": "type.googleapis.com/google.rpc.RetryInfo",
      ...
    }]
  }
}
字段描述
error用于向后兼容Google API客户端库的额外层。 它使用JSON来标示以便人类阅读。
codeStatus.code的HTTP状态代码映射
message这对应于Status.message
status这对应于Status.status
details这对应于Status.details

状态码

常见错误码与其原因简短说明:

HTTPRPC描述
200OK没有错误
400INVALID_ARGUMENT客户端指定了无效的参数。 检查错误消息和错误详细信息以获取更多信息。
400FAILED_PRECONDITION请求不能在当前系统状态下执行,例如删除非空目录。
400OUT_OF_RANGE客户端指定了无效的范围。
401UNAUTHENTICATED由于遗失,无效或过期的OAuth令牌而导致请求未通过身份验证。
403PERMISSION_DENIED客户端没有足够的权限。这可能是因为OAuth令牌没有正确的范围,客户端没有权限,或者客户端项目尚未启用API。
404NOT_FOUND找不到指定的资源,或者该请求被未公开的原因(例如白名单)拒绝。
409ABORTED并发冲突,例如读-修改-写冲突。
409ALREADY_EXISTS客户端尝试创建的资源已存在。
429RESOURCE_EXHAUSTED资源配额达到速率限制。 客户端应该查找google.rpc.QuotaFailure错误详细信息以获取更多信息。
499CANCELLED客户端取消请求
500DATA_LOSS不可恢复的数据丢失或数据损坏。 客户端应该向用户报告错误。
500UNKNOWN未知的服务器错误。 通常是服务器错误。
500INTERNAL内部服务错误。 通常是服务器错误。
501NOT_IMPLEMENTED服务器未实现该API方法。
503UNAVAILABLE暂停服务。通常是服务器已经关闭。
504DEADLINE_EXCEEDED已超过请求期限。如果重复发生,请考虑降低请求的复杂性。

命名约定

为提供一致的开发体验,所有命名都应:

  • 简单:为简化可使用广泛接受的短语或缩写;
  • 直观:尽量使用直观、熟悉的术语;
  • 一致:使用正确的英语;同一概念使用相同的名称,不同概念使用不同名称;

命名一致性示例:

API 名称示例
产品名称Google Calendar API
服务名称calendar.googleapis.com
包名称google.calendar.v3
接口名称google.calendar.v3.CalendarService
源代码目录//google/calendar/v3
API 名称calendar

服务名称

服务名称应当符合DNS命名的语法规范,确保它可以被解析成一个或多个网络地址。

如果一个API是由多个服务组成,那么他们的命名应当更容易被发现:一种方法是所有服务名称共享一个公共前缀。

包名称

包名称应当与产品名称和服务名称保持一致,同时必须包含版本信息:

// Google Calendar API
package google.calendar.v3;

方法名称

方法名称应当使用首字母小写驼峰体的名词:

动词名词方法名称请求响应
ListBookListBooksListBooksRequestListBooksResponse
GetBookGetBookGetBookRequestBook
CreateBookCreateBookCreateBookRequestBook
UpdateBookUpdateBookUpdateBookRequestBook
RenameBookRenameBookRenameBookRequestRenameBookResponse
DeleteBookDeleteBookDeleteBookRequestgoogle.protobuf.Empty
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值