RESETful API 设计规范
为什么选择 RESTful
我认为一套接口应该尽量满足以下几个原则:
- 安全可靠,高效,易扩展。
- 简单明了,可读性强,没有歧义。
- API 风格统一,调用规则,传入参数和返回数据有统一的标准。
我们当然可以根据自己的经验,或者参考知名公司的接口总结设计出一套满足要求的接口,但是每个人对接口的理解不同,设计出来的接口也会有所不同,接口的命名,请求参数的格式,响应的结果,错误响应的错误码,等等很多地方都会有不一样的实现。当你去寻求一种设计理念来帮助我们设计出满足要求的接口,一定会发现 RESTful。
RESTful 的设计理念基于 HTTP 协议,因为 Roy Fielding 就是 HTTP 协议(1.0版和1.1版)的主要设计者。它是一种设计风格,没有规定我们一定如何实现,但是为我们提供了很好的设计理念。风格的统一,使得我们不需要过多的解释,就能让使用者明白该如何使用,同时也会有很多现成的工具来帮助我们实现 RESTful 风格的接口。
RESTful 设计原则
1. HTTPS
HTTPS 为接口的安全提供了保障,可以有效防止通信被窃听和篡改。而且现在部署 HTTPS 的成本也越来越低,你可以通过 cerbot 等工具,方便快速的制作免费的安全证书,所以生产环境,请务必使用 HTTPS。
另外注意,非 HTTPS 的 API 调用,不要重定向到 HTTPS,而要直接返回调用错误以禁止不安全的调用。
2. domian
应当尽可能的将 API 与其主域名区分开,可以使用专用的域名,访问我们的 API
如果你的应用很庞大或者你预计它将会变的很庞大,那
应该
将API
放到子域下。这种做法可以保持某些规模化上的灵活性。
例如:https://api.vxndy.com
或者可以放在主域名下,例如:https://www.vxndy.com/api
3. Version
随着业务的发展,需求的不断变化,API 的迭代是必然的,很可能当前版本正在使用,而我们就得开发甚至上线一个不兼容的新版本,为了让旧用户可以正常使用,为了保证开发的顺利进行,我们需要控制好 API 的版本。
所有的 API
必须保持向后兼容,你 必须
在引入新版本 API
的同时确保旧版本 API
仍然可用。所以 应该
为其提供版本支持。
通常情况下,有两种做法:
- 将版本号直接加入 URL 中
https://api.vxndy.com/v1
https://api.vxndy.com/v2
- 使用 HTTP 请求头的 Accept 字段进行区分
https://api.larabbs.com/
Accept: application/prs.vxndy.v1+json
Accept: application/prs.vxndy.v2+json
Github Api 虽然默认使用了第一种方法,但是其实是推荐并实现了第二种方法的,我们同样也尽量使用第二种方式。
4. Endpoints
在 RESTful 的架构中,所有的一切都表示资源,每一个 URL 都代表着一种资源,资源应当是一个名词,而且大部分情况下是名词的复数,尽量不要在 URL 中出现动词。
端点就是指向特定资源或资源集合的 URL
。在端点的设计中,你 必须
遵守下列约定:
- URL 的命名
必须
全部小写 - URL 中资源(
resource
)的命名必须
是名词,并且必须
是复数形式 必须
优先使用Restful
类型的 URL- URL 中不能出现
-
,必须
用下划线_
代替 - URL
必须
是易读的 - URL
一定不可
暴露服务器架构
来看一个反例
- https://api.example.com/getUserInfo?userid=1
- https://api.example.com/getusers
- https://api.example.com/sv/u
- https://api.example.com/cgi-bin/users/get_user.php?userid=1
再来看一个正列
- https://api.example.com/zoos
- https://api.example.com/animals
- https://api.example.com/zoos/{zoo}/animals
- https://api.example.com/animal_types
- https://api.example.com/employees
5.HTTP 动词
对于资源的具体操作类型,由 HTTP
动词表示。常用的 HTTP
动词有下面五个(括号里是对应的 SQL
命令)。
- GET(SELECT):从服务器取出资源(一项或多项)。
- POST(CREATE):在服务器新建一个资源。
- PUT(UPDATE):在服务器更新资源(客户端提供改变后的完整资源)。
- PATCH(UPDATE):在服务器更新资源(客户端提供改变的属性)。
- DELETE(DELETE):从服务器删除资源。
其中
1 删除资源 必须
用 DELETE
方法
2 创建新的资源 必须
使用 POST
方法
3 更新资源 应该
使用 PUT
方法
4 获取资源信息 必须
使用 GET
方法
针对每一个端点来说,下面列出所有可行的 HTTP
动词和端点的组合
请求方法 | URL | 描述 |
---|---|---|
GET | /zoos | 列出所有的动物园(ID和名称,不要太详细) |
POST | /zoos | 新增一个新的动物园 |
GET | /zoos/{zoo} | 获取指定动物园详情 |
PUT | /zoos/{zoo} | 更新指定动物园(整个对象) |
PATCH | /zoos/{zoo} | 更新动物园(部分对象) |
DELETE | /zoos/{zoo} | 删除指定动物园 |
GET | /zoos/{zoo}/animals | 检索指定动物园下的动物列表(ID和名称,不要太详细) |
GET | /animals | 列出所有动物(ID和名称)。 |
POST | /animals | 新增新的动物 |
GET | /animals/{animal} | 获取指定的动物详情 |
PUT | /animals/{animal} | 更新指定的动物(整个对象) |
PATCH | /animals/{animal} | 更新指定的动物(部分对象) |
GET | /animal_types | 获取所有动物类型(ID和名称,不要太详细) |
GET | /animal_types/{type} | 获取指定的动物类型详情 |
GET | /employees | 检索整个雇员列表 |
GET | /employees/{employee} | 检索指定特定的员工 |
GET | /zoos/{zoo}/employees | 检索在这个动物园工作的雇员的名单(身份证和姓名) |
POST | /employees | 新增指定新员工 |
POST | /zoos/{zoo}/employees | 在特定的动物园雇佣一名员工 |
DELETE | /zoos/{zoo}/employees/{employee} | 从某个动物园解雇一名员工 |
6.Filtering
如果记录数量很多,服务器不可能都将它们返回给用户。API
应该
提供参数,过滤返回结果。下面是一些常见的参数。
- ?limit=10:指定返回记录的数量
- ?offset=10:指定返回记录的开始位置。
- ?page=2&per_page=100:指定第几页,以及每页的记录数。
- ?sortby=name&order=asc:指定返回结果按照哪个属性排序,以及排序顺序。
- ?animal_type_id=1:指定筛选条件
所有 URL
参数 必须
是全小写,必须
使用下划线类型的参数形式。
经常使用的、复杂的查询 应该
标签化,降低维护成本。如
GET /trades?status=closed&sort=sortby=name&order=asc
# 可为其定制快捷方式
GET /trades/recently_closed
7.Authentication
应该
使用 OAuth2.0
的方式为 API 调用者提供登录认证。必须
先通过登录接口获取 Access Token
后再通过该 token
调用需要身份认证的 API
。
Oauth 的端点设计示列
- RFC 6749 /token
- Twitter /oauth2/token
- Fackbook /oauth/access_token
- Google /o/oauth2/token
- Github /login/oauth/access_token
- Instagram /oauth/authorize
客户端在获得 access token
的同时 必须
在响应中包含一个名为 expires_in
的数据,它表示当前获得的 token
会在多少 秒
后失效。
{
"access_token": "token....",
"token_type": "Bearer",
"expires_in": 3600
}
客户端在请求需要认证的 API
时,必须
在请求头 Authorization
中带上 access_token
。
Authorization: Bearer token...
当超过指定的秒数后,access token
就会过期,再次用过期/或无效的 token
访问时,服务端 应该
返回 invalid_token
的错误或 401
错误码。
HTTP/1.1 401 Unauthorized
Content-Type: application/json
Cache-Control: no-store
Pragma: no-cache
{
"error": "invalid_token"
}
Laravel 开发中,
应该
使用 JWT 来为管理你的 Token,并且一定不可
在api
中间件中开启请求session
。
响应规范
restful 接口返回遵循统一格式, 设计参考类 Optional 遵循函数式编程规范
普通格式
{
"data": "waht",
"msg": null,
"state": 1,
"is_redirect": true,
"redirect_url": "http://baidu.com",
"token": null
}
带页码的格式
{
"data": {
"list": null,
"pagebar": {
"page": 1,
"total": 2,
"limit": 10
}
},
"msg": "error",
"state": 0,
"is_redirect": true,
"redirect_url": "http://qq.com",
"token": null
}
参考资料
https://developer.github.com/v3/
https://developer.github.com/v3/guides/traversing-with-pagination/