什么是REST
REST是RoyThomas Fielding在他2000年的博士论文中提出的, Fielding将他对互联网软件的架构原则,定名为REST,即Representational State Transfer(常见的翻译是“表现层状态转化”)的缩写。
REST结构风格约束
1.客户端-服务器端。即客户端发起请求,服务端响应或拒绝,如出错客户端处理异常。
2.无状态。通信会话状态由客户端维护,也就是在请求中添加必要的信息。若在服务器端维护,则必须保证会话在同一服务器上进行或建立供集群内服务器共同访问的会话存储。
3.缓存。为解决无状态带来的重复请求的影响,请求只在第一次接受是被执行,后续请求可使用已完成结果直接响应。
4.统一接口。程序的整体URI保持一种通用架构,接口可读性强。
5.分层系统。按层划分负责处理一类功能,通常可分为三层:
(1)应用层:负责返回JSON数据和其他业务逻辑
(2)服务层:为应用层提供服务支持。
(3)数据访问层:提供数据访问和存储的服务。
REST就是这一系列设计约束的集合,如果一个架构符合REST原则,就称它为RESTful架构。
RESTful API设计指南
1.URI中不出现动词原则。
2.合理的请求头。当服务端只能返回json格式数据,如客户端Accept字段要求返回application/xml,则视为不合理返回406错误
3.合理使用请求方法和状态码。
方法 | 语义 |
---|---|
OPTIONS | 用于获取资源支持的所有HTTP方法 |
HEAD | 用于只获取请求某个资源返回的头信息 |
GET | 用于从服务器获取某个资源的信息:1.完成请求后,返回状态码200 OK 2.完成请求后,需要返回被请求的资源详细信息 |
POST | 用于创建新资源:1.创建完成后,返回状态码201 Created 2.完成请求后,需要返回被创建的资源详细信息 |
PUT | 用于完整的替换资源或者创建指定身份的资源,比如创建id为123的某个资源:1.如果是创建了资源,则返回201 Created2.如果是替换了资源,则返回200 OK |
PATCH | 用于局部更新资源:1.完成请求后,返回状态码200 OK 2.完成请求后,需要返回被修改的资源详细信息 |
DELETE | 用于删除某个资源,完成请求后返回状态码204 No Content |
4.正确地使用REST
- 使用“201 Created”响应时,应该带Location,指向新建资源的地址
- 使用“405 Method Not Allowed”响应时,应该带有Allow头,告诉客户端
对该资源有效的HTTP方法
5.不要做出错误的提示
当返回结果中包含错误原因,不应返回200作为状态码,避免客户端可能会缓存成功的HTTP请求
6.合理使用嵌套对象序列化,尽可能将关联信息内联起来
7.版本区分
- 保存在URI中,如https://api.swagger.com/api/v2,极力推荐
- 放在请求头中。比如GitHub的用法:“Accept:application/vnd.github.v3+json”
- 自定义请求头。比如,“X-Api-Version:1”
8.URI失效和迁移
对失效的API,应该返回“404not found”或“410 gone”;对迁移的API,返回301重定向
9.信息过滤
URL通常最好越简短越好,对结果过滤、排序和搜索相关的功能都应该通过参数实现。
参数 | 含义 |
---|---|
offset=0&limit=10 | offset开始位置,limit返回数量 |
page=2&per_page=100 | page第几页,per_page每页数量 |
sortby=name&order=asc | sortby按照什么属性排序,order排序顺序 |
sort=age,desc | 多个排序条件组合 |
10.速度限制
为了避免请求泛滥HTTP状态码429(too many requests),给API设置速度限制很重要。可参考GitHub返回头:
- X-RateLimit-Limit:当前时间段允许的并发请求数。
- X-RateLimit-Remaining:当前时间段保留的请求数。
- X-RateLimit-Reset:当前时间段剩余的秒数。
11.并发控制
缺少并发控制的PUT和PATCH请求可能导致“更新丢失”。这个时候可以使用
Last-Modified和ETag头来实现条件请求。具体原则如下:
- 客户端发起的请求如果没有包含If-Unmodified-Since或者If-Match头,就返回状态码“403 Forbidden”,在响应正文中解释为何返回该状态码
- 客户端发起的请求所提供的If-Unmodified-Since或者If-Match头与服务器记录的实际修改时间或ETag值不匹配时,返回状态码“412 Precondition Failed”
- 客户端发起的请求所提供的If-Unmodified-Since或者If-Match头与服务器记录的实际修改时间或ETag的历史值匹配,但资源已经被修改过时,返回状态码“409 Conflict”
- 客户端发起的请求所提供的条件符合实际值,就更新资源,响应“200 OK”或者者“204 No Content”,并且包含更新过的Last-Modified和/或ETag头,同时包含Content-Location头,其值为更新后的资源URI