RESTful API 设计入门

4,128 阅读4分钟

目前前后端对接其实主要是面向 API 文档开发,而 API 的设计中,有一种 RESTful API 的设计,具有规范,从某一种角度,我觉得 RESTful API 可以很好的把后端 API 从繁杂的业务中抽象出来,更好地进行管理和编写,同时也具有良好的可读性。

对于一些现代化的 MVC 框架,在脚手架阶段可能就会自动生成 RESTful 风格的 Controller。

资源的拆分

路由中 URI 中的资源都是名词,即一个个实体,对于代码而言,可以看做一个个类到 URI 的映射,比如:

  1. GET /repos/:owner/:repo/stargazers
  2. GET /organizations

HTTP 动词

对于 RESTful API 中,常用的动词有以下几种:

GET(SELECT):从服务器取出资源(一项或多项)。
POST(CREATE):在服务器新建一个资源。
PUT(UPDATE):在服务器更新资源(客户端提供改变后的完整资源)。
PATCH(UPDATE):在服务器更新资源(客户端提供改变的属性)。
DELETE(DELETE):从服务器删除资源。

PUT 和 PATCH 的区别主要在于更新整个资源还是更新局部资源。

版本

当 API 可能出现重大变更,无法向后兼容时,RESTful API 提供了版本花的概念,可以保证旧版和新版的 API 的使用,有三种方法存放版本号:

  • 在uri中放版本信息:GET /v1/users/1
  • Accept Header:Accept: application/json+v1
  • 自定义 Header:X-Api-Version: 1

没有版本号的 API 并不是一个好的 RESTful API(对不起我又设计了辣鸡的 API)。

过滤

API 应该提供一定的筛选条件,比如:

?limit=10:指定返回记录的数量
?offset=10:指定返回记录的开始位置。
?page=2&per_page=100:指定第几页,以及每页的记录数。
?sortby=name&order=asc:指定返回结果按照哪个属性排序,以及排序顺序。
?animal_type_id=1:指定筛选条件

状态码

服务器返回的状态码应该复合 HTTP 的规范,比如:

200 OK - [GET]:服务器成功返回用户请求的数据,该操作是幂等的(Idempotent)。
201 CREATED - [POST/PUT/PATCH]:用户新建或修改数据成功。
202 Accepted - []:表示一个请求已经进入后台排队(异步任务)
204 NO CONTENT - [DELETE]:用户删除数据成功。
400 INVALID REQUEST - [POST/PUT/PATCH]:用户发出的请求有错误,服务器没有进行新建或修改数据的操作,该操作是幂等的。
401 Unauthorized - [
]:表示用户没有权限(令牌、用户名、密码错误)。
403 Forbidden - [] 表示用户得到授权(与401错误相对),但是访问是被禁止的。
404 NOT FOUND - [
]:用户发出的请求针对的是不存在的记录,服务器没有进行操作,该操作是幂等的。
406 Not Acceptable - [GET]:用户请求的格式不可得(比如用户请求JSON格式,但是只有XML格式)。
410 Gone -[GET]:用户请求的资源被永久删除,且不会再得到的。
422 Unprocesable entity - [POST/PUT/PATCH] 当创建一个对象时,发生一个验证错误。
500 INTERNAL SERVER ERROR - [*]:服务器发生错误,用户将无法判断发出的请求是否成功。

返回 JSON

RESTful API 应该尽可能的返回 JSON,对于错误的请求,需要为用户提供错误的信息。

  1. {
  2. "code": 1234,
  3. "message": "Something bad happened :-(",
  4. "description": "More details about the error here"
  5. }

不进行无意义的包装

body 只需要直接返回数据,不需要进行包装比如:

  1. {
  2. "success": true,
  3. "data": {"id":1,"name":"xiaotuan"},
  4. }

不止于 RESTful

尽管 RESTful API 的设计规范清晰可读,但是针对一些特殊的需求,我们可能也不一定要强制遵守 RESTful API 的设计规范。比如批量删除,DELETE 在 HTTP 规范中是没有参数的,这就给批量删除接口带来了一定的麻烦,可以考虑改用 POST。

参考资料