REST并没有明确的设计标准,可以说RESTful是一种设计风格的规范化。在RESTful API设计中,不同的组织可能还存在不同的设计风格规范,但是整体上RESTful的风格规范是一致的。
也正是因为有了一致的风格规范,让读API的人更好地理解API,甚至不用阅读文档,就知道API要实现的某个资源的某种“状态转化”。根据Github开放API或者微博开放API的设计风格。下面是我总结的RESTful API的相关风格规范,今后我将使用此规范进行API开发。
3.1 协议
客户端与服务器之间使用HTTP或者HTTPS协议进行通信。
3.2 域名
应当尽量将API程序部署到专有的域名之下,如:
https://api.demo.com
如果API比较简单,或者不考虑进行扩展,应当放在项目的子模块中,如:
https://demo.com/api/
3.3 API版本
应当将API版本放在URL中,如微博开放API就将版本号放在URL中:
http://api.weibo.com/2/
如果我们把版本号理解成资源的不同表述形式的话,API版本应放在HTTP请求头Accept字段中,如github中的开放API
Accept: application/vnd.github.v3
可能github考虑很多因素,所以把请求的API版本放到HTTP请求头里了。实际上,如果我们想要快速的开发一个API程序,使用第一种形式会更加直观与方便。
3.4 路径
对于不同的资源,都有一个唯一的URL地址,每一个URL地址代表一种资源,所以网址中应当是名称,不能是动词,而且名词应当与数据库表名对应。一般来说,数据库中保存的是数据集合,所以URL中对应的资源应当是名词复数。
如Github开放API中,列出一个组织的项目集合
https://api.github.com/orgs/:org/projects
在上面URL中,orgs代表组织集合,而:org代表集体的组织名,projects代表具体的资源
3.5 HTTP动词
对于资源的某种具体操作类型,需要客户端发送不同的HTTP动作来完成。
常用的五个HTTP动词已经对应操作如下:
- GET(Retrieve):从服务器取出资源(一项或多项);
- POST(CREATE):在服务器新建一个资源;
- PUT(UPDATE):在服务器更新资源(客户端提供改变后的完整资源);
- PATCH(UPDATE):在服务器更新资源(客户端提供改变的属性);
- DELETE(DELETE):从服务器删除资源。
实际上,最常用的额HTTP动词原先只有4个,即GET、POST、PUT、DELETE,PATCH方法是新引入的,是对PUT方法的补充,用来对已知资源进行局部更新。
有时候,只需要修改一个属性,开发者通常(为图省事)把一个包含了修改后完整信息传给后端,做完整更新。但实际上如果需要考虑性能优化,是有必要做局部更新的。
3.6 过滤
在获取服务器资源的时候,大部分情况是需要进行过滤的,而不是获取数据库中的完整集合。这时候需要设置过滤条件,我们可以将过滤条件作为参数拼接到URL中。如下:
?limit=10 # 指定获取10条信息集合
?page=1&limit=10 # 指定每页10条信息,获取第1页信息集合
?limit=10&deleted=true # 获取数据库中已经标志为删除的10条信息集合
3.7 返回
使用相应的HTTP状态码,将结果告知客户端,以下是常用的HTTP状态码以及状态描述:

- 正常:如果正常返回数据,应当使用msg或者其他关键字作为键名返回给客户端,如下
{
"data":[
"user_id":1,
"name":"张三",
"token":"csdcnsdvndsijudsao",
],
"message":"OK",
"code":200
}
- 错误:如果发生错误,应当使用error作为错误信息的键名返回给客户端
{
"error":"Unauthorized",
"code":401
}
针对不同操作,服务器向用户返回的结果应该符合以下规范:
- GET /collection:返回资源对象的列表(数组)
- GET /collection/resource:返回单个资源对象
- POST /collection:返回新生成的资源对象
- PUT /collection/resource:返回完整的资源对象
- PATCH /collection/resource:返回完整的资源对象
- DELETE /collection/resource:返回一个空文档
3.8 Hypermedia API
RESTful API最好做到Hypermedia,即超媒体,在返回结果中提供链接,连向其他API方法或者一些文档,使得用户不查文档,也知道下一步应该做什么。如Github就做到了Hypermedia,使用GET方式请求 https://api.github.com ,会返回一系列的链接地点:
{
"current_user_url": "https://api.github.com/user",
"current_user_authorizations_html_url": "https://github.com/settings/connections/applications{/client_id}",
"authorizations_url": "https://api.github.com/authorizations",
"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}",
.....