RESTful架构,一种互联网软件架构。它结构清晰、符合标准、易于理解、扩展方便,所以正得到越来越多网站的采用
起源 REST这个词,是Roy Thomas Fielding在他2000年的博士论文中提出的
Fielding将他对互联网软件的架构原则,定名为REST,即Representational State Transfer的缩写。这个词组的翻译是"表现层状态转化",如果一个架构符合rest原则,我们就称它为restful架构
资源(resources)
rest翻译为表现层状态转化,它没有指名是谁的表现层,缺乏主语,在这里,我们用资源当做主语,即为资源的表现层状态转化。
所谓资源,就是网络上的一个实体,它可以是一张图片,一段文本。。。我们可以用一个url指向它,用户通过url就能访问到这个资源。
普及两个概念 uri与url,uri(统一资源标识符 Uniform Resource Identifier),url(统一资源定位符 Uniform Resource Locator),其中url是uri的子集
表现层(representation)
资源是一种信息实体,它可以有多种外在表现,比如文本可以以txt格式表现,也可以用html,json,xml格式表现,我们把资源具体呈现出的形式叫做它的表现层。
uri指向资源,但不代表资源的形式,http头部中的accept和content-type等表达了资源的形式
状态转化(state transfer)
访问一个uri,就代表客户和服务器发生了一个交互,这个过程会涉及到数据和状态的变化。
互联网通信协议http协议,是无状态的,不能记录资源的各种状态,资源的状态保存在服务器端,如果要操作服务器上的资源,就要通过一些手段,让服务器知道,从而让服务器的资源发生状态转化,这个变化是建立在表现层之上的,就是表现层状态转化。
客户端使用的手段,只能是http协议,http协议里有很多操作方式的动词比如get,post,put,delete,它们对应了四种基本操作,get用来获取资源(查),post用来新建资源(增)或者修改资源(改),put用来更新资源(改),delete用来删除资源(删)。
综上
restfull架构即为
每个url指向一种资源,客户端和服务器之间传递资源的某种表现层,客户通过4个http动词,对服务器资源进行操作,实现服务器资源表现层状态转化
常见误区
url中含有动词,比如/users/update/1,其中update是动词(手段),这个url就不满足restful架构,正确的写法是/user/1,然后用put方式或post方式
url中带有版本号,不同版本,可以理解为同一资源的不同表现形式,可以把版本号放到http头信息中,从url剔除
restful api设计
一、协议
api与用户的通信协议采用http协议
二、域名
尽量将api部署到专用域名下,比如 http://api.test.com。如果api不多且比较简单,不太会进一步扩展,也可以放到主域名下,比如http://test.com/api/...
三、版本(version)
将版本号放到http头信息中,也有说法说版本号放到url中更方便直接,github的是放在http头信息里的
四、路径(endpoint)
路径又称“终点”(endpoint),表示api具体网址,在restful架构中,每个网址代表一种资源(resource),所以网址中不能有动词,比如说一个api提供动物园zoo信息,其中包括各种动物以及雇员信息,符合restful架构的url可如下设计
- http://api.test.com/zoos
- http://api.test.com/animals
- http://api.test.com/employees
- http://api.test.com/zoo/1
五、http动词
对于资源的具体操作类型,由http动词表示,常用的http动词如下
- get(select),从服务器获取资源(一项或多项)
- post(create),在服务器新建一个资源
- put(update),在服务器更新资源(客户端提供改变后的完整资源)
- patch(update),在服务器更新资源(客户端提供改变的属性)比如svn中针对修改打patch操作
- delete(delete),从服务器删除资源
两个不常用http动词
- head,获取资源元数据
- options,获取信息,关于资源的哪些属性是客户端可以修改的
例子如下
- get /zoos,获取所有动物园
- post /zoos,新建一个动物园
- get /zoo/id,获取某个指定动物园的信息
- put /zoo/id,更新某个指定动物园信息(提供该动物园修改后的完整信息)
- patch /zoo/id,更新某个指定动物园信息(提供该动物园部分信息)
- delete /zoo/id, 删除某个动物园
- get /zoos/id/animals,获取指定动物园的所有动物
- delete /zoos/id/anamal/id,删除指定动物园的指定动物
六、信息过滤(filter)
如果资源数量过多,服务器不好一次性全部返回给用户,api应该提供参数,过滤返回结果,比如指定筛选条件,排序,分页,限制返回数量等
- ?animalType=1,指定筛选条件
- ?sort=age&order=desc,排序
- ?page=2&perPage=10,分页
- ?limit=10,限制返回数量
参数设计允许冗余,即允许api路径与url参数偶尔重复,比如 get /zoos/id/animals与 get /animals?zooId=id含义相同
七、状态码(status code)
服务器向用户返回的状态码和提示信息,常见的列表以下
- 200 OK - [get],服务器成功返回用户请求的数据,该操作是幂等的(idempotent)
- 201 CREATED - [post/put/patch],用户新建或修改数据成功
- 202 ACCEPTED - [*],表示请求已进入后台排队(异步任务)
- 204 NO CONTENT - [delete],用户数据删除成功
- 400 INVALID REQUEST - [post/put/patch],用户发出的请求错误,服务器没有进行新建或修改数据的操作,该操作幂等
- 401 Unauthorized - [*],用户没有权限(令牌,用户,密码错误)
- 403 Forbidden - [*],表示用户得到授权(与401错误相对),但是访问是被禁止的
- 404 NOT FOUND - [*],用户发出的请求针对的是不存在的记录,服务器没有进行操作,该操作幂等
- 406 Not Acceptable - [get],用户请求的格式不可得(比如用户请求json格式,但是只有xml格式)
- 410 Gone - [get],用户请求的资源被永久删除,且不会再得到
- 500 INTERNAL SERVER ERROR - [*],服务器发生错误,用户将无法判断发出的请求是否成功
八、错误处理(error handling)
如果状态码是4xx,应该向