RESTful API 设计
RESTFUL架构
RESTful架构,就是目前最流行的一种互联网软件架构,定名为REST,即Representational State Transfer的缩写,可译为"表现层状态转化”。
Restful是一种软件架构风格,设计风格而不是标准,只是提供了一组设计原则和约束条件。它主要用于客户端和服务器交互类的软件。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。
RESTful风格的服务,由于可以直接以json或xml为载体承载数据,以HTTP方法为统一接口完成数据操作,客户端的开发不依赖于服务实现的技术,移动终端也可以轻松使用服务,REST成为web service的主导。
RESTful API
RESTful API是目前比较成熟的一套互联网应用程序的API设计理论。首先看一下,优秀的RESTful API应该是什么样子的
- 尽可能的遵守有关 WEB 规范和常见约定;
- 调用接口简单明了,可读性强,没有歧义;
- 不同 API 风格保持一致,调用规则,传入参数和返回数据有统一的标准;
- 能够为客户端提供简单灵活的数据访问方式;
- 有一定的容错性和防止非法参数功能;
- 高效,安全可靠,容易扩展。
版本
应该将API的版本号放入URL。
https://api.example.com/v1/
路由
表示API的具体网址。
RESTful API 中的url是指向资源的,而不是描述行为的,因此设计API时,应使用名词而非动词来描述语义,否则会引起混淆和语义不清。
# Bad APIs
/api/getArticle/1/
/api/updateArticle/1/
/api/deleteArticle/1/
上面四个url都是指向同一个资源的,虽然一个资源允许多个url指向它,但不同的url应该表达不同的语义,上面的API可以优化为:
# Good APIs
/api/Article/1/
article 资源的获取、更新和删除分别通过 GET
, PUT
和 DELETE方法请求API即可
。试想,如果url
以动词来描述,用PUT
方法请求 /api/deleteArticle/1/
会感觉多么不舒服。
在看一个比较糟糕的设计
/getAllUser
/setUserComments
/DeleteUserForId
之所以糟糕,不仅仅是它们显得拖沓冗长,最重要的是,使用这样的风格和名字没有固定的形式,不同的开发者往往需要阅读你的文档才能开始使用,也没有充分利用HTTP Method,何况使用自己的动词可能会产生和HTTP Method冲突的情况。使用 REST 风格的优秀设计应该像下面这些:
-
GET /users
获取所用户 -
GET /user/1234
获取ID为1234的用户 -
POST /users
创建一个新用户 -
PUT /users/1234
更新ID为1234的用户 -
PATCH /users/1234
更新ID为1234的用户的部分内容 -
DELETE /users/1234
删除ID为1234的用户
这些API所有的操作只有一个节点 /users,显得简洁明了,如果熟悉 HTTP Method 的开发者,一眼看上去就能猜到应该如何使用。
注:
GET和HEAD方法必须始终是安全的。例如,有这样一个不规范的API:
# The following api is used to delete articles
# [GET]
/api/deleteArticle?id=1
API中资源命名都是用复数形式
URI需要区分大小写
URI结尾建议以 '/'结束
单词的链接符应该用g'-'替换'_'
HTTP动词
对于资源的具体操作类型,由HTTP动词表示。常用的HTTP动词有下面五个(括号里是对应的SQL命令)。
GET(SELECT):从服务器取出资源(一项或多项)。返回 200,即SUCCESS;失败是返回 404
POST(CREATE):在服务器新建一个资源。返回 201,即CREATED
PUT(UPDATE):在服务器更新资源(客户端提供改变后的完整资源)。返回 200,即SUCCESS
PATCH(UPDATE):在服务器更新资源(客户端提供改变的属性)。返回 200,即SUCCESS
DELETE(DELETE):从服务器删除资源。返回 204,即SUCCESS
GET /zoos:列出所有动物园
POST /zoos:新建一个动物园
GET /zoos/ID:获取某个指定动物园的信息
PUT /zoos/ID:更新某个指定动物园的信息(提供该动物园的全部信息)
PATCH /zoos/ID:更新某个指定动物园的信息(提供该动物园的部分信息)
DELETE /zoos/ID:删除某个动物园
GET /zoos/ID/animals:列出某个指定动物园的所有动物
DELETE /zoos/ID/animals/ID:删除某个指定动物园的指定动物
过滤信息
如果记录数量很多,服务器不可能都将它们返回给用户。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 - [*]:服务器发生错误,用户将无法判断发出的请求是否成功。
错误处理
如果状态码是4xx,就应该向用户返回出错信息。一般来说,返回的信息中将error作为键名,出错信息作为键值即可。
{
error: "Invalid API key"
}
返回结果
针对不同操作,服务器向用户返回的结果应该符合以下规范。
GET /collection:返回资源对象的列表(数组)
GET /collection/resource:返回单个资源对象
POST /collection:返回新生成的资源对象
PUT /collection/resource:返回完整的资源对象
PATCH /collection/resource:返回完整的资源对象
DELETE /collection/resource:返回一个空文档