RESTful API 设计规范

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

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

RESTFul 使用的协议

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

域名及API版本

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

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

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

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

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

//之前版本
api/users/analysis

//第二版 analysis 接口
api/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)的信息。

// 123为用户id
GET /api/users/123
PUT /api/user/123

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

// 通常使用查询字符串(Query Param), 123为process记录(对象)的id
GET /api/processes/123?categories=1

// process的表单相关操作 - 获取其表单数据
GET /api/processes/123/form-data

// process的表单相关操作 - 删除其表单数据
DELETE /api/processes/123/form-data

// process的表单相关操作 - 对该表单数据进行分析操作
GET /api/processes/123/form-data/analysis

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

image.png

互联网公司是如何使用的

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

// 用户相关操作接口1 -- 用户其他信息
"current_user_url":       "https://api.github.com/user",
"emails_url":             "https://api.github.com/user/emails",
"followers_url":          "https://api.github.com/user/followers",
"following_url":          "https://api.github.com/user/following{/target}",
"keys_url":               "https://api.github.com/user/keys",
"starred_url":            "https://api.github.com/user/starred{/owner}{/repo}",
"user_org_url":           "https://api.github.com/user/orgs",
"cur_user_repos_url":     "https://api.github.com/user/repos{?type,page,per_page,sort}",

// 用户相关操作接口2 -- 对用户表相关的操作
"user_url":               "https://api.github.com/users/{user}",
"user_repos_url":         "https://api.github.com/users/{user}/repos{?type,page,per_page,sort}",

//搜索接口 -- 各种类别的搜索
"user_search_url":        "https://api.github.com/search/users?q={query}{&page,per_page,sort,order}",
"code_search_url":        "https://api.github.com/search/code?q={query}{&page,per_page,sort,order}",
"commit_search_url":      "https://api.github.com/search/commits?q={query}{&page,per_page,sort,order}",
"issue_search_url":       "https://api.github.com/search/issues?q={query}{&page,per_page,sort,order}",
"label_search_url":       "https://api.github.com/search/labels?q={query}&repository_id={repository_id}{&page,per_page}",
"repos_search_url":       "https://api.github.com/search/repositories?q={query}{&page,per_page,sort,order}",

// 组织操作接口
"org_url":                "https://api.github.com/orgs/{org}",
"org_repos_url":          "https://api.github.com/orgs/{org}/repos{?type,page,per_page,sort}",
"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。下面是一个例子。

// Rquest
GET /api/user/123 HTTP/1.1
Accept: application/json

// Response
HTTP/1.1 200 OK
{
    "code":200,
    "message":"OK",
    "data":{}
}

服务端响应体封装

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

常见的响应体封装如下:

{
    "code":200,
    "message":"OK",
    "data":{}
}

服务端提供接口使用信息

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

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

一些实践

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

参考资料、其他资料

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×