在先后端分离的 Web 应用架构中,前端专一于页面,同时与后端进行数据交互;然后端则专一于提供 API 接口。在这样的结构下,REST 是一个很流行的先后端交互形式的约定。这只是一套约定,并非某个技术标准,因此在实际的应用中,对器实现程度彻底取决于后端开发者;一些号称 RESTful 的接口并无那么RESTful。前端
在我所见过的 RESTful 接口的实现中,以 GitHub 最让人惊叹。我第一次如此强烈得感觉到 REST 接口的美妙,彻底知足了我所期待的「接口的形式美感」,简直就是对 REST 规范实现的最佳范本。我以为每个后端开发者都应该看一看 GitHub 的 REST 接口文档,感觉一下循规蹈矩的美妙。git
本文选取了几个点来简要介绍,一个让前端开发者用起来舒服的 RESTful 接口是什么样子。github
以防有些观众刚刚打开电梯,仍是有必要简单介绍一下 REST 这个概念。后端
REST 是一个术语的缩写,REpresentational State Transfer,中文直译「表征状态转移」,这是个很拗口的词。个人建议是先不要强行理解,直接看怎么作,等对实施细节有一些了解后,再来看名字会有更深入的理解。REST 是一套风格约定,RESTful 是它的形容词形式;好比一套实现了 REST 风格的接口,能够称之为 RESTful 接口。api
REST 用来规范应用如何在 HTTP 层与 API 提供方进行数据交互;在现阶段,你应该已经很熟悉 GET 和 POST 请求;甚至有可能由于受限于后端框架限制等缘由,你的整个应用全都是用这两种 HTTP 方法来完成的。这样无疑浪费了 HTTP 协议的潜力,而 REST 则充分利用了 HTTP 规范中的方法,达到接口描述的语义化。安全
REST 描述了 HTTP 层里客户端和服务器端的数据交互规则;客户端经过向服务器端发送 HTTP(s)请求,接收服务器的响应,完成一次 HTTP 交互。这个交互过程当中,REST 架构约定两个重要方面就是 HTTP 请求的所采用方法,以及请求的连接。服务器
在请求层面,REST 规范能够简单粗暴抽象成如下两个规则:restful
1. 请求 API 的 URL 表示用来定位资源;网络
2. 请求的 METHOD 表示对这个资源进行的操做;架构
如下将以这两个规则为基础,描述如何构造一个符合 REST 规范的请求。
1、API 的 URL
URL 用来定位资源,跟要进行的操做区分开,这就意味这 URL 不应有任何动词;
下面示例中的 get、create、search 等动词,都不该该出如今 REST 架构的后端接口路径中。在之前,这些接口中的动名词一般对应后台的某个函数。好比:
/api/getUser /api/createApp /api/searchResult /api/deleteAllUsers
当咱们须要对单个用户进行操做时,根据操做的方式不一样可能须要下面的这些接口:
/api/getUser (用来获取某个用户的信息,还须要以参数方式传入用户 id 信息) /api/updateUser (用来更新用户信息) /api/deleteUser (用来删除单个用户) /api/resetUser (重置用户的信息)
更有甚者,可能在更新用户不一样信息时,提供不一样的接口,好比:
/api/updateUserName /api/updateUserEmail /api/updateUser
这样的弊端在于:首先加上了动词,确定是使 URL 更长了;其次对一个资源实体进行不一样的操做就是一个不一样的 URL,形成 URL 过多难以管理。
其实当你回过头看「URL」 这个术语的定义时,更能理解这一点。URL 的意思是统一资源定位符,这个术语已经清晰的代表,一个 URL 应该用来定位资源,而不该该掺入对操做行为的描述。
在 REST 架构的连接应该是这个样子:
GET /api/teams/123/members/234 表示获取 id 为 123 的小组下,id 为234 的成员信息
按照相似的规则,能够写出以下的接口
/api/teams (对应团队列表) /api/teams/123 (对应 ID 为 123 的团队) /api/teams/123/members (对应 ID 为 123 的团队下的成员列表) /api/teams/123/members/456 (对应 ID 为 123 的团队下 ID 未 456 的成员)
2、API 请求的方法
在不少系统中,几乎只用 GET 和 POST 方法来完成了全部的接口操做;这个行为相似于全用 DIV 来布局。实际上,咱们不仅有GET 和 POST 可用,在 REST 架构中,有如下几个重要的请求方法:GET,POST,PUT,PATCH,DELETE。这几个方法均可以与对数据的 CRUD 操做对应起来。
【Read】,资源的读取,用 GET 请求;好比:
GET /api/users ( 表示读取用户列表)
GET 应当实现为一个安全方法。用于获取数据而不该该产生反作用。
【Created】,资源的建立,用 POST 方法;
POST 是一个非幂等的方法,屡次调用会形成不一样效果;
幂等(Idempotent):若是对服务器资源的屡次请求与一次请求形成的反作用是同样的的话,那这个请求方法能够被认为是幂等。
好比下面的请求会在服务器上建立一个 name 属性为 'John Snow' 的用户;屡次请求就会建立多个这样的用户。
POST /api/users { "name": "John Snow" }
【Update】,资源的更新。用于更新的 HTTP 方法有两个,PUT 和 PATCH。
他们都应当被实现为幂等方法,即屡次一样的更新请求应当对服务器产生一样的反作用。
PUT 和 PATCH 有各自不一样的使用场景:
PUT 用于更新资源的所有信息,在请求的 body 中须要传入修改后的所有资源主体;
而 PATCH 用于局部更新,在 body 中只须要传入须要改动的资源字段。
设想服务器中有如下用户资源 /api/users/123
{ "id": 123, "name": "Original", "age": 20 }
当咱们日后台发送更新请求时,PATCH 和 PUT 形成的效果是不同。
PUT /api/users/123 { "name": "PUT Update" }
上述 PUT 请求操做后的内容是:
{ "id": 123, "name": "PUT Update" }
能够观察到,资源原有的 age 字段被清除掉了。
而若是改用 PATCH 的话,
PATCH /api/users/123 { "name": "PATCH Update" }
更新后的内容是:
{ "id": 123, "name": "PATCH Update", "age": 20 }
请求中指定的 name 属性被更新了,而原有的 age 属性则保持不变。
PATCH 的做用在于若是一个资源有不少字段,在进行局部更新时,只须要传入须要修改的字段便可。不然在用 PUT 的状况下,你不得不将整个资源模型全都发送回服务器,形成网络资源的极大浪费。
【Delete】,资源的删除,相应的请求 HTTP 方法就是 DELETE。这个也应当被实现为一个幂等的方法。如:
DELETE /api/users/123
用于删除服务器上 ID 为 123 的资源,屡次请求产生反作用都是,是服务器上 ID 为 123 的资源不存在。
3、分页、过滤
REST 风格的接口地址,表示的多是单个资源,也多是资源的集合;当咱们须要访问资源集合时,设计良好的接口应当接受参数,容许只返回知足某些特定条件的资源列表。
好比支持以 offset 和 limit 参数来进行分页;
GET /api/users?offset=0&limit=20
支持提供关键词进行搜索,以及排序
GET /api/users?keyword=john&sort=age
支持根据字段进行过滤
GET /api/users?gender=male
设计合适的 API URL,以及选择合适的请求方法,能够语义化的描述一个 HTTP 请求的操做。
当咱们都熟悉且遵循这样的规范后,基本能够看到一个 REST 风格的接口就知道如何使用这个接口进行 CRUD 操做了。好比下面这面这个接口就表示搜索 ID 为 123 的图书馆的书,而且书的信息里包含关键字「game」,返回前十条知足条件的结果。
GET /api/libraries/123/books?keyword=game&sort=price&limit=10&offset=0
一样,下面这个请求的意思也就很明显了吧。
PATCH /api/companies/123/employees/234 { "salary": 2300 }
总结
限于篇幅限制,本文仅从请求的角度选取了几个重点描述了实现 RESTful 接口须要知足的基本要求。关于 REST 的更多详细规范,能够参考这个仓库。