RESTful接口规范

什么是RESTful

REST(Representational State Transfer)是一种轻量级的Web Service架构风格,能够翻译成“表述性状态转移”,实现和操做明显比SOAP和XML-RPC更为简洁,能够彻底经过HTTP协议实现,还能够利用缓存Cache来提升响应速度,性能、效率和易用性上都优于SOAP协议.html

通俗来说就是:资源在网络中以某种表现形式进行状态转移,RESTful即这种设计的风格前端

用一句话概述即:URL定位资源,用HTTP动词描述操做算法

REST架构遵循了CRUD原则,CRUD原则对于资源只须要四种行为就能够完成对其操做和处理:数据库

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

REST把HTTP对一个URL资源的操做限制在GET、POST、PUT和DELETE这四个以内。这种针对网络应用的设计和开发方式,能够下降开发的复杂性,提升系统的可伸缩性.json

更多REST API背景知识能够参考这篇 RESTful API 设计指南api

分URI规范,Action操做规范,参数规范,状态码规范数组

设计流程

  1. 肯定一个API提供什么类型的资源
  2. 肯定资源之间的依赖关系
  3. 基于类型和依赖关系肯定资源的命名
  4. 肯定资源的结构
  5. 为资源添加最少的方法

【强制】浏览器

【推荐】缓存

【参考】安全

说明:

正例:

反例:

URI 规范

1.【强制】已肯定/发布的接口禁止修改请求方法/URI/参数名/返回值结构/内容,禁止删除接口/参数/返回值中的属性。

说明:

若有上述变动,请新启用一个接口
容许新增参数,但该参数不能为必填,如必填需提供缺省值兼容旧的调用

2.【强制】URI 中只容许用小写字母,不用大写。
正例:

https://example.com/api/gaoshou/v1/users
https://example.com/api/gaoshou/v1/mails:

反例:

https://example.com/api/GaoShou/V1/Users
https://example.com/api/gaoshou/V1/Mails

3.【强制】URI 中用中杠 - 分割单词不用下划杠 _

正例:

https://example.com/api/gaoshou/v1/user-mails

反例:

https://example.com/api/gaoshou/v1/user_mails

4.【强制】URI 不能以"/"结尾。

正例:

/gaoshou/v1/users

反例:

/gaoshou/v1/users/

5.【强制】URI 中不能包含空格。

6.【强制】URI 不能以文件后缀结尾。

7.【推荐】将 API 的版本号放入 URI 中, 因为一个项目多个 APP 或微服务因此使用如下风格, 将版本号放到 APP 后面

https://example.com/api/:app:/:version:/:resource:

正例:

https://example.com/api/gaoshou/v1/users
https://example.com/api/assets/v1/assets/1

8.【强制】每一个 URI 表明一种资源,因此不能有动词,只能有名词(特殊状况可使用动词),并且所用的名词每每与数据库的表格名对应,名词必须是清晰简洁的英文单词,不容许用拼音替代。

正例:

/gaoshou/v1/users

反例:

/gaoshou/v1/get-users

9.【推荐】通常来讲, 数据库中的表都是同种记录的"集合"(Collection), 因此 API 中的名词也应该使用复数(若是没有复数形式,应使用单数)。举例来讲数据库中的 Users 列表, Courses 列表。

正例:

/gaoshou/v1/users
/assets/v1/assets/1

10.【推荐】避免使用笼统的表示,例如objects、values、types

11.【推荐】URI 中的可变部分, 通常用来传递该 API 操做的核心实体对象的惟一ID。若是没有惟一ID的单一对象则以单数单词做为对象ID。

正例:

/assets/1 [GET, PUT, DELETE]
/materials/wood [GET, PUT, DELETE]

12.【强制】URI 中指定5个之内资源对象的操做id能够在URI路径上用逗号,分割。更多则以batch结尾,相关参数在请求体中。

正例:

/assets/1,2,3 [GET, PUT, DELETE] //id为1,2,3的资源
/assets/batch [POST, PUT]

13.【参考】避免层级过深的 URI。在 URI 中表达层级,用于按实体关联关系进行对象导航,通常根据id导航。
过深的导航容易致使 URI 膨胀,不易维护,尽可能使用查询参数代替路径中的实体导航。建议不超过3个层级。

正例:

/assets/1?area=2&act=3

反例:

/assets/1/area/2/act/3

14.【推荐】若是有除id外更多的参数须要提供, GET 方法请使用 URL Parameter(例如:"?clientId=xxxxx&appId=xxxxxx"), PUT/POST/DELETE 方法请使用请求体传递参数。

15.【强制】URI 传递参数列表要ENCODE,特别是UNICODE字符必定要ENCODE。

16.【强制】URI 映射应避免 /{xx}/{xx} 的使用。

说明:

相似该路径,效率低,并且不容易理解路径
例如:/{uid}/{lable}
建议修改成/user/{uid}/lable/{lableId}
修改后直接能够根据路径理解该API意义(ID为lableId的用户的标签)

Action操做规范

1.【强制】经过标准HTTP方法对资源CRUD。

说明:

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

2.【参考】正常状况下全部R(获取数据)操做都使用 GET 方法,查询内容参数使用QueryParams(仅容许在查询请求参数很是多的状况下,如参数数量大于10个,才可使用POST)。

3.【强制】GET 查询从服务器取资源一项必须提供资源id,多项必须是资源集合的 URI,即复数结尾。

正例:

/assets/1
/assets

4.【强制】状况须要R(获取数据)操做使用POST 方法的 URI 必须以 query (一项)或 list (多项)结尾。

正例:

/assets/query [POST]
/assets/list [POST]

5.【推荐】获取单个对象应该返回整个对象,获取多个对象应该返回一些可选项属性。

6.【强制】全部C(建立资源)操做都使用 POST 方法。C操做通常向”资源集合“型URI发起。必须传递一个资源对象(不是属性),这样即便对象的结构发生变化,也不须要去更新方法或者对象结构,那些弃用的字段则须要标识为“只读”。

正例:

/assets [POST]   // 新增资源
/zoos/1/employees [POST] //为id为1的动物园雇佣员工

7.【强制】若是只支持一个完整对象的更新,U(更新资源)操做必须使用 PUT 方法。

正例:

/animals/1 [PUT] // 更新id为1的动物

8.【推荐】若是只更新一个对象的部分属性,U(更新资源)操做使用 PATCH 方法。

9.【强制】全部D(删除资源)操做都使用 DELETE 方法。

正例:

/zoos/1/employees/2 [DELETE] // 删除id为1的动物园内id为2的雇员
/zoos/1/employees/2,4,5 [DELETE] // 删除id为1的动物园内id为2,4,5的雇员
/zoos/1/animals  // 删除id为1的动物园内的全部动物

10.【强制】DELETE 方法没有请求体,接口上必须不能包含RequestBody。

11.【推荐】若是是当即删除,应该返回空;若是是启动一个删除操做,应该返回一个删除操做;若是只是标识某个资源是“被删除的”,应该返回一个更新后的资源;若是多个删除请求删除同一资源,那么只有第一个请求才应该成功,其余的返回404(not found)。

12.【参考】各Action操做须要保证操做的安全性和幂等性。

说明:

  • 安全性 :不会改变资源状态,能够理解为只读的;
  • 幂等性 :执行1次和执行N次,对资源状态改变的效果是等价的。
Action 安全性 幂等性
READ
CREATE
UPDATE
DELETE

安全性和幂等性均不保证反复请求能拿到相同的响应。以 DELETE 为例,第一次 DELETE 返回 200 表示删除成功,第二次返回 404 提示资源不存在,这是容许的。

13.【强制】自定义操做方法应该用于基本方法不能实现的功能性方法。可能须要一个任意请求并返回一个任意的响应,也多是流媒体请求和响应。

14.【强制】自定义方法应该使用 POST/PUT/PATCH 方法。

15.【强制】自定义方法批量(超5个id)应该遵循如下规范。

| 自定义方法 | 方法 | URI 结尾 | 请求体 | 响应 |
|---|---|---|---|
| 批量多id查询 | POST | list | JSON 资源id数组,如[1,2,3,4,5,6] | JSON 资源列表数组 |
| 批量添加 | POST | batch-create | JSON 资源列表数组 | JSON 资源id数组 |
| 批量删除 | POST | batch-delete | JSON 资源id数组 | 空JSON对象, {} |
| 批量修改 | PUT | batch-update | JSON 资源列表数组 | 空JSON 资源列表数组 |
| 批量修改某属性 | PATCH | batch-update | JSON 资源列表数组 | JSON 资源列表数组 |

16.【强制】自定义方法查询集合数量的 URI 应该以 count 结尾,返回体为JSON对象 {"count": ""}

17.【强制】自定义方法对资源执行某一动做(好比发送消息,启用什么功能),若是是针对资源的,则 URI 以动做为动词结尾,若是是针对资源属性的,则 URI 以动做为动词结尾,属性做为参数。

正例:

描述 动做 HTTP Mapping 请求体 响应体
对资源执行某一动做 customVerb /custom-verb [POST]
取消某种操做 cancel /cancel [POST] N/A {"result": 0/1}
从回收站中恢复一个资源 undelete /projects/1/undelete [POST] N/A {"result": 0/1}
检查项目是否重名 checkName /projects/1/check?name= [POST] N/A {"result": 0/1}

18.【推荐】比较复杂的接口不能肯定是使用 POST 仍是 PUT 时,要看具体的业务层代码,看看接口产生的结果是否幂等,若是幂等用 PUT,相反用 POST。

参数规范

1.【强制】接口请求体和响应体接受参数格式均为JSON("application/json")。请求头为 Content-Type:application/json;charset=UTF-8

2.【强制】Query和JSON中参数中用驼峰命名。

3.【推荐】默认将Date的输入输出转为Long型时间戳。

4.【强制】对象和方法命名语义需与内部保持一致,不容许自行创造。好比不要把Member叫作Person。

5.【强制】全部批量查询接口均须要分页。

6.【推荐】常见参数约定,查询能够捎带如下参数。

描述 示例 备注
过滤条件 ?type=1&age=16 容许必定的 URI 冗余,如 /projects/1 与 /projects?id=1
排序 ?sort=age&orde=asc 指定返回结果按照哪一个属性排序,以及排序顺序
投影 ?whiteList=id,name,email 指定返回字段
分页 ?page=2&limit=100 指定第几页,以及每页的记录数
分页 ?offset=10 指定返回记录的开始位置,若是NoSql能够是游标
搜索 ?keyword=localhost 模糊搜索

7.【推荐】常用的、复杂的查询能够标签化,这样能够下降维护成本。

正例:

/trades?status=closed&sort=created,desc [GET]

快捷方式:

/trades#recently-closed [GET]
或者
/trades/recently-closed [GET]

8.【强制】全部的接口都会上传一部分基本信息,方便后台认证和统计信息,这部分信息会在每一个接口的Head里。
HEAD要求添加内容以下:

HEAD KEY Value 描述
t ${token} (可选)若是已经登陆的接口须要传用户的Token,未登陆接口不须要
a ${app} (必填)APPID,不一样应用区分不一样的应用id,用以数据隔离,不准私自定义,须要申请
v ${version} (必填)应用版本号,纯数字格式,按照排期统一规划,用以不一样版本数据隔离
ev ${version} (可选)运行应用环境版本号,纯数字格式,可用于Web页面统计原生环境版本号,通常由客户端经过url传入
n ${versionName} (可选)应用版本名, 字符串
en ${versionName} (可选)运行应用环境版本名, 字符串,可用于Web页面统计原生环境版本名,通常由客户端经过url传入
p ${platform} (必填)平台,Android为 1;IOS为 2;Web为 3
ep ${platform} (可选)运行应用环境平台,Android为 1;IOS为 2,通常由客户端经过url传入
m ${model} (可选)设备描述信息,如MI 2,iPhone 4,Web页面通常由客户端经过url传入
s ${sdk} (可选)系统SDK版本, Web页面通常由客户端经过url传入
u ${uuid} (必填)设备惟一标识, Web页面通常由客户端经过url传入
d ${time} (必填)时间戳, 请求接口当前时间戳。说明:每次请求都带上当前时间的时间戳, 服务器收到请求后对比时间差,超过必定时长(如5分钟),则认为请求失效。时间戳超时机制是防护DOS攻击的有效手段。
r ${random} (可选)随机字符串, 每一个请求生成的随机字符串。说明:每次请求都带上客户端随机字符串, 服务器收到请求后对比是否请求过, 若是之前请求过, 则认为请求失效。用以防止重放攻击。
c ${md5-check} (可选)校验信息。说明:不一样的接口能够选择不一样程度的校验算法。请参考签名算法为时间戳+[token
h ${channel} (可选)渠道
o ${origin} (可选)来源,可用于标注通常第三方调用
i ${activity} (可选)活动,可用于标注活动
Referer ${Referer} (可选)请求接口来自的页面
User-Agent ${User-Agent} (可选)浏览器信息

应用Id对应表

Code 应用
0 后台专用
1 超级万学
2 考研高手
3 创世界
4 超级万学-创新创业
5 创新创业
12 神龙考研

9.【推荐】正常返回体应该包含HTTP请求状态码和服务器响应时间戳。结果以 result 为关键字返回。

正例:

{
		"status": "返回成功状态码,成功即为200",
		"timestamp": "响应时间戳",
		"result": "返回的数据"
	}
key type desc
status int 返回成功状态码,成功即为200
timestamp long 响应时间戳
result Object 返回的数据

10.【强制】禁止采用前端 URI 传递的当前用户Id,必须从Header中取Token,经过Token获取当前用户Id。

状态码规范

1.【强制】接口调用成功时返回HTTP状态码为200,返回数据结果为标准Json格式。如调用错误会返回除200以外的其余HTTP状态码,返回数据结果也为标准Json格式。

2.【推荐】随着系统发展,总有一些API失效或者迁移,对失效的API,返回404 not found 或 410 gone;对迁移的API,返回 301重定向。

3.【推荐】服务器向用户返回的状态码和提示信息, 常见的有如下一些。

HTTP CODE 含义 方法 描述
200 OK [GET] 服务器成功返回用户请求的数据, 该操做是幂等的(Idempotent)。
201 Created,被建立 [POST/PUT/PATCH] 用户新建或修改数据成功。
202 Accepted,被采纳 [*] 表示一个请求已经进入后台排队(异步任务)。
204 No Content,被采纳 [DELETE] 用户删除数据成功。
206 Partial Content,部份内容 [GET] 通常为分片下载内容
301 Moved Permanently,永久移动 [GET] 请求的资源已被永久的移动到新URI,返回信息会包括新的URI,请求会自动定向到新URI。从此任何新的请求都应使用新的 URI 代替
302 Found,找到 [GET] 与301相似。但资源只是临时被移动。客户端应继续使用原有 URI
304 Not Modified,未修改 [GET] 所请求的资源未修改,服务器返回此状态码时,不会返回任何资源。客户端一般会缓存访问过的资源,经过提供一个头信息指出客户端但愿只返回在指定日期以后修改的资源
400 Bad Request,错误请求 [POST/PUT/PATCH] 用户发出的请求有错误, 服务器没有进行新建或修改数据的操做, 该操做是幂等的。经常使用于参数校验。
401 Unauthorized,未受权 [*] 表示用户没有权限(令牌、用户名、密码错误)。常见于未登陆须要登陆,若是登陆后尚未权限应该返403。
403 Forbidden,拒绝请求 [*] 表示用户获得受权(与401错误相对), 可是访问是被禁止的。
404 Not Found,未找到 [*] 用户发出的请求针对的是不存在的记录, 服务器没有进行操做, 该操做是幂等的。
405 Method Not Allowed,方法不容许 [*] 请求中的方法未找到或被禁止。
406 Not Acceptable,不被采纳 [GET] 用户请求的格式不可得(好比用户请求JSON格式, 可是只有XML格式)。
409 Conflict,资源冲突 [PUT] 完成 PUT 请求时可能返回此代码,服务器处理请求时发生了冲突。
410 Gone,资源已经不存在 [GET] 用户请求的资源被永久删除, 且不会再获得的。410不一样于404,若是资源之前有如今被永久删除了可以使用410代码。
422 Unprocesable entity,非法对象 [POST/PUT/PATCH] 当建立一个对象时, 发生一个验证错误。
500 Internal Server Error,服务器内部错误 [*] 服务器发生错误, 用户将没法判断发出的请求是否成功。非业务异常,通常由框架抛出。
501 Not Implemented,未实现 [*] 服务器不支持请求的功能,没法完成请求。
503 Service Unavailable,服务不可用 [*] 因为超载(接口被限流)或系统维护,服务器暂时的没法处理客户端的请求。延时的长度可包含在服务器的Retry-After头信息中。

4.【强制】不要发生了错误但给2xx响应,客户端可能会缓存成功的 HTTP 请求。

5.【参考】正确设置 HTTP 状态码,不要自定义。

6.【参考】对非业务类异常,线上能够统一文案如"服务器端错误,请稍后再试"。

响应规范

1.【强制】若是状态码是4xx, 就应该向用户返回出错信息。出错信息格式以下。

{
  "status":400,	
  "error": "自定义错误码",
  "msg": "错误描述",
  "timestamp": 123456,
  "exception": "报错Exception类型",
  "show":1	
}
Key Type 描述
status Int (可选)同 HTTP 状态码,通常为方便日志统计
error String (必填)自定义错误码,能够经过错误码定位到具体错误,通常全系统惟一
msg String (必填)错误具体描述
timestamp Long (可选)服务器时间戳
exception String (可选)报错Exception类型, 如IOException,通常不面向前端
show Int (可选)0: 前端不需展现; 1: 前端可Toast展现; 2: 前端可对话框展现; 默认 0

2.【强制】若是状态码是2xx,服务器向用户返回的结果应该将 reslut 做为键名, 返回对象做为键值。通常格式以下。

{
  "status": "返回状态码",
  "timestamp": "时间戳",
  "result": "返回的对象"
}
Key Type 描述
status Int (可选)同 HTTP 状态码,通常为方便日志统计
timestamp Long (可选)服务器时间戳
result Object 返回的对象

2.【强制】针对不一样操做, 服务器向用户返回的结果应该符合如下规范。

Key Type 描述
GET /assets 返回资源对象的列表(数组)
GET /assets/resource 返回单个资源对象
POST /assets 返回新生成的资源对象
PUT /assets/resource 返回完整的资源对象
PATCH /assets/resource 返回完整的资源对象
DELETE /assets/resource 返回一个空文档

签名算法

按照不一样接口的功能,能够把接口安全级别分为明文模式、参数校验模式、RSA签名校验模式。

明文模式

明文模式,的校验信息生成规则为: 时间戳+[random_str]+[token|uuid]+[url]+app盐 取md5值。

协议中包含字段random_str,主要保证签名不可预测。推荐生成随机数算法以下:调用随机数函数生成,将获得的值转换为字符串。

[token|uuid]: 若是有token则传token,若是没有则传设备uuid,若是都没有则不传。

[url]: 为完整的接口连接。

参数校验模式

参数校验模式,是在明文模式基础上对RequestBody的参数进行签名,校验信息生成规则为: 时间戳+[random_str]+[token|uuid]+[url]+[请求RequestBody字典排序串]+app盐 取md5值。

设全部发送或者接收到的数据为集合M,将集合M内非空参数值的参数按照参数名ASCII码从小到大排序(字典序),使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串stringA。

特别注意如下重要规则:

  • 参数名ASCII码从小到大排序(字典序);
  • 若是参数的值为空不参与签名;
  • 若是参数的值为对象,则默认设置为空对象{}
  • 参数名区分大小写;
  • 接口可能增长字段,验证签名时必须支持增长的扩展字段;

RSA签名校验模式

RSA签名校验模式,是在参数校验模式基础上对生成的签名信息RSA加密。此模式通常用于第三方服务器之间的高安全要求校验。原则就是RSA密钥保存是可靠安全的。

文章来源:刘俊涛的博客 欢迎关注公众号、留言、评论,一块儿学习。

如有帮助到您,欢迎点击推荐,您的支持是对我坚持最好的确定(_)

相关文章
相关标签/搜索