RESTful API 规范
RESTful API 规范
RESTful 并不是一个非常明确的规范,在部分细节上,不同人的理解和执行都会有差异。
为了避免团队内部对 RESTful 的使用有歧义,因此有如下规范
Method
-
POST: 创建、新增
-
PUT:更新
-
DELETE: 删除
-
GET: 查询 (虽然 HTTP 协议中 GET 是可以使用 body 的,但是由于部分封装过后的
request lib
默认不支持 body 在 GET 请求中,需要慎用 body,内部服务不受限制)
URI
/<ServiceName>/<Version>/<Resources>
/<ServiceName>/<Version>/<Resources>/<ResourceID>
/<ServiceName>/<Version>/<Resources>/<ResourceID>/<Action>
/<ServiceName>/<Version>/<Resources>/<ResourceID>/<SubResouces>/<SubResouceID>
/<ServiceName>/<Version>/<Resources>/0/<SubResouces>/<SubResouceID>
/<ServiceName>/<Version>/<Resources>?<IndexKey1>=<Value>&<IndexKey2>=<Value>
/<ServiceName>/<Version>/<Resource>?<IndexKey1>=<Value>&<IndexKey2>=<Value>
-
URI 的第一段为服务名称,为了便于做流量分发
-
URI 的第二段为版本号,为了便于平滑的升级不兼容的接口
-
其余段落为 Resources 规则
-
Resource 的名称应为
snake_case
-
URI 的奇数段为 Resource 类型,偶数段为 Resource ID (务必为业务 ID,若无,则为较为稳定的 unique index)
-
Resource 类型名应为单词复数
-
对于单一索引,应满足上述条件
-
对于复合索引,Resource 为单数,通过 query 来设定条件
-
单复数同形换替代单词
-
-
当无须指定一个资源类型的 ID 时,使用 0 占位
-
由于 METHOD 的表达能力有限,所以当对同一个资源存在两种不同类型的更新操作时,允许 URI 的最后一个段可以为一个对某资源的操作。
-
样例:
-
Create
-
POST http://example.com/user/v0/users
创建用户
-
-
Update
-
PUT http://example.com/user/v0/users/:userID
更新某个用户的信息 -
PUT http://example.com/user/v0/users/:userID/ban
禁用某个用户 -
PUT http://example.com/user/v0/users/:userID/promote
给某个用户提升权限
-
-
Delete
-
DELETE http://example.com/user/v0/users/:userID
删除用户 -
DELETE http://example.com/user/v0/user?username=xxx
通过用户名删除用户
-
-
Find
-
GET http://example.com/user/v0/users/:userID
查询某个用户的信息 -
GET http://example.com/user/v0/users/:userID/car?carNo=川Axxx
通过车牌查询某个用户的某个车辆 -
GET http://example.com/user/v0/user?mobile=123467890
通过手机号查询用户信息 -
GET http://example.com/user/v0/user?username=xxx
通过用户名查询用户信息
-
-
Listing
-
GET http://example.com/user/v0/users/:userID/cars
查询某个用户的车辆信息 -
GET http://example.com/user/v0/users[?filter=xx]
查询多个用户的信息
-
Authorization
除了 AccessKey 的验签鉴权方式,对外服务将采用 Authorization 对每一个接口进行权限校验。
但由于我们最终服务可能嵌入到不同的客户端中(手机管车,微信), 可能需要对每个请求进行多系统的权限校验,因此扩展 HTTP Header Authorization。
Authorization: <type> <credentials>[; <type> <credentials>]
-
多段 Authorization 以
;
分隔, 也意味着,credentials
不应该出现;
- 解析时,
<type> <credentials>
需要 trim 空字符
- 解析时,
-
主系统 type
-
Bearer <access_token>
https://tools.ietf.org/html/rfc6750#section-2.1 -
Basic base64(<username>:<password>)
https://tools.ietf.org/html/rfc7617#section-2
-
-
额外验证
-
PayPassword <encoded_passsword>
-
PicAuthCode <auth_code>
-
-
旁系统 type 以对应系统加入前缀
- 微信
WechatBearer <token>
- 微信
-
对于直接只能通过简单 URL 获取的资源,比如图片,需要用 query 代替 header
?authorization=encodeURIComponent(xxx)
- 对于 BFF,务必提供这种传验证的方式(便于构造简单请求,可以避免多个 OPTIONS 的发送,https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#Simple_requests)
Demos
Authorization: Bearer xxxxxxx
Authorization: Bearer xxxxxxx; CentreBearer xxxxxx
# base64(aladdin:opensesame)
Authorization: Basic YWxhZGRpbjpvcGVuc2VzYW1l
Refs
HTTP Code
-
200:正常返回数据
-
201:创建(POST) 成功后的返回
-
204:无数据的正常返回
-
400:传入的参数有问题等
-
401:登录、授权等权限验证失败
-
403:访问了不属于此用户的资源或其他不允许其访问
-
404:访问了不存在的资源
-
409:重复创建或更新的冲突等
-
429:请求太多
-
500:内部处理发生错误,如请求超时等
列表返回
-
第一层必须包含 total 和 data 两个字段
-
total 表示总共有多少条记录,方便前端计算分页
字段命名
都以小驼峰的格式来命名,比如:userProfile