RESTful API 设计规范介绍

#RESTful [字体 ··]

RESTful 是目前流行的 API 设计规范,遵守这套规范设计出的 API 可以较好的适用不同类型的客户端,例如:PC/Mobile/Pad…

RESTful 表现层状态转换(英语:Representational State Transfer,缩写:REST)是 Roy Thomas Fielding 博士于 2000 年在他的博士论文[1]中提出来的一种万维网软件架构风格,目的是便于不同软件/程序在网络(例如互联网)中互相传递信息。

RESTFul 使用的协议

API 内容的传输总是基于HTTP 协议。 在线上产品通常使用安全的 HTTP 协议,即 HTTPS。

域名及 API 版本

如果这套 API 是提供第三方服务的,通常要用单独的域名。如果项目不专注于第三方服务或中小型项目可以在域名后加 api 来标识。

1// 单独域名
2http://api.domain.com
3// 中小型项目,前后端共用域名
4http://domain.com/api

版本号通常以 v1/v2 来标识,默认第一版不加路径中不加 v1,当接口有新版本后加版本标识,例如第二版 API 可以为:

1http://api.domain.com/v2
2http://domain.com/api/v2

如果只有部分接口出现第二版,如果第二版的 user 接口,通常只在 /users 后加版本号。

1//之前版本
2api/users/analysis
3
4//第二版 analysis 接口
5api/users/v2/analysis

路径 (Endpoint)

访问一个 API 要有一个确定的地址,这个地址即路径(Endpoint)。

在 RESTful 中每个路径都表示一个资源,这个资源可以是音视频、图片、文本(XML/JSON)。通常接口返回的是 JSON 数据,如一个用户的信息、一个用户列表。

接口的地址通常使用名词复数,表示这个资源的集合(Collection),例如关于用户的接口可能是这样的开头 /api/users,关于图片相关的接口 /api/photos,以上这些路径标识了这套 API 中某类资源。

在设计 RESTful API 时可以把这些路径想象为一个树形分支,可以把 api 当做根路径,之后的名词(users、photos)是跟节点(api)的分支,如果做成脑图它是这样的。

image.png

在操作系统中(win、unix、linux)文件都是按目录组织的,这些目录都是树型(在 unix/linux 及其明显),访问一个文件都是一个具体的目录加上一个文件名,API 接口区分不同资源也是这种方式。

集合中的某个对象的具体操作

常见 CRUD 操作通过 HTTP 动词区分,针对具体的某个对象操作在其集合(users、photos)加 id 然后在拼接上操作名称。

查询、修改某个用户(id:123)的信息。

1// 123为用户id
2GET /api/users/123
3PUT /api/user/123

按照 process 本身的属性进行筛选对 process 进行筛选;获取 process 流程相关的表单相关的数据。

 1// 通常使用查询字符串(Query Param), 123为process记录(对象)的id
 2GET /api/processes/123?categories=1
 3
 4// process的表单相关操作 - 获取其表单数据
 5GET /api/processes/123/form-data
 6
 7// process的表单相关操作 - 删除其表单数据
 8DELETE /api/processes/123/form-data
 9
10// process的表单相关操作 - 对该表单数据进行分析操作
11GET /api/processes/123/form-data/analysis

通过以上 API 路径可以形成如下树型脑图:

image.png

互联网公司是如何使用的

这里以 Github 为例,Github 开放 API 接口: https://api.github.com,下面是整理后的接口。

 1// 用户相关操作接口1 -- 用户其他信息
 2"current_user_url":       "https://api.github.com/user",
 3"emails_url":             "https://api.github.com/user/emails",
 4"followers_url":          "https://api.github.com/user/followers",
 5"following_url":          "https://api.github.com/user/following{/target}",
 6"keys_url":               "https://api.github.com/user/keys",
 7"starred_url":            "https://api.github.com/user/starred{/owner}{/repo}",
 8"user_org_url":           "https://api.github.com/user/orgs",
 9"cur_user_repos_url":     "https://api.github.com/user/repos{?type,page,per_page,sort}",
10
11// 用户相关操作接口2 -- 对用户表相关的操作
12"user_url":               "https://api.github.com/users/{user}",
13"user_repos_url":         "https://api.github.com/users/{user}/repos{?type,page,per_page,sort}",
14
15//搜索接口 -- 各种类别的搜索
16"user_search_url":        "https://api.github.com/search/users?q={query}{&page,per_page,sort,order}",
17"code_search_url":        "https://api.github.com/search/code?q={query}{&page,per_page,sort,order}",
18"commit_search_url":      "https://api.github.com/search/commits?q={query}{&page,per_page,sort,order}",
19"issue_search_url":       "https://api.github.com/search/issues?q={query}{&page,per_page,sort,order}",
20"label_search_url":       "https://api.github.com/search/labels?q={query}&repository_id={repository_id}{&page,per_page}",
21"repos_search_url":       "https://api.github.com/search/repositories?q={query}{&page,per_page,sort,order}",
22
23// 组织操作接口
24"org_url":                "https://api.github.com/orgs/{org}",
25"org_repos_url":          "https://api.github.com/orgs/{org}/repos{?type,page,per_page,sort}",
26"organization_teams_url": "https://api.github.com/orgs/{org}/teams"

总结:

  • 使用路径变量(Path Value)使接口很有层次感
  • 接口清晰易懂,一看就了解接口的作用

路径命令规范

  • 通常常在路径中使用名词复数表示一类资源,如:users、photos
  • 路径中的动词通常要变成名词,通常可在动词后加 ing,如:api/processes/publishing
  • 如果路径中存在多个单词,中间使用 “-” 号分隔,如:api/processes/123/form-data
  • 避免多级 URL,不利于扩展
    • bad:GET api/users/123/type/2
    • good: GET api/users/123?type=2

错误的路径命名:

  • /user/getAllUsers
  • /user/createNewUser
  • /user/deleteUser

HTTP 动词

RESTful API 的一大特点是使用 HTTP 动词来区分资源集合(users,photos,departments)的 CRUD,并且有不同的状态码,

这些是常用的动词。

  • GET 请求用于查询(Read)
  • POST 请求用于新增(Create)
  • PUT 请求用于修改(Update)
  • DELETE 请求用于删除(Delete)
  • PATCH 更新(Update),通常是部分更新,不常用

动词返回状态码

这些返回值,与 200 状态码的含义密切相关。 虽然 201 204 都表示成功,但开发业务中通常都用 200 这个状态码表示。

  • GET: 200 OK
  • POST: 201 Created
  • PUT: 200 OK
  • DELETE: 204 No Content
  • PATCH: 200 OK

状态码

客户端每次请求,服务器都必须给出响应。响应分为两个部分:状态码和数据。

每次响应应严格遵守 HTTP 状态码,这样便于服务端和浏览器的交互。

状态码分类:

  • 1xx:相关信息
  • 2xx:操作成功
  • 3xx:重定向
  • 4xx:客户端错误
  • 5xx:服务器错误

详细 HTTP 状态码

业务中常用状态码
状态码(status)说明备注
200正常
401未登录
403权限不足
404访问资源不存在
500不可控的服务器异常可控制的业务逻辑异常使用 code 代表

服务端响应

服务端响应另一部分是数据。数据可是 xml、json 格式,如果是图片、视频文件在响应体中是二进制数据。

通常在 RESTful API 接口是以 JSON 格式数据交互的,因此客户端 HTTP 的请求头(header)中应携带 Acceptapplication/json,同时服务端响应应携带 Content-Typeapplication/json。下面是一个例子。

 1// Rquest
 2GET /api/user/123 HTTP/1.1
 3Accept: application/json
 4
 5// Response
 6HTTP/1.1 200 OK
 7{
 8    "code":200,
 9    "message":"OK",
10    "data":{}
11}

服务端响应体封装

因为业务的复杂性,HTTP 状态码并不能完全标识特殊业务信息,因此在业务响应体中通常带有 code 标识业务状态码,业务状态码基于 HTTP 状态码扩展。

常见的响应体封装如下:

1{
2    "code":200,
3    "message":"OK",
4    "data":{}
5}

服务端提供接口使用信息

API 的使用者未必知道,URL 是怎么设计的。一个解决方法就是,在回应中,给出相关链接,便于下一步操作。这样的话,用户只要记住一个 URL,就可以发现其他的 URL。这种方法叫做 HATEOAS。

api.github.com 就是一个很好的实践。用户只要访问这个接口就可得到接口信息。

一些实践

  • 如果一个接口返回数据包含一组图片或视频,那么这些数据应该以完整的 URL 形式返回,而不是只有名字
  • 一个好用的 API 在抛出业务异常是通常给出这个错误异常的 QA 链接

参考资料、其他资料


博客没有评论系统,可以通过 邮件 评论和交流。 Top↑