设计前后端完全分离的应用,可以使用到RESTful API。比如, Backbone 的默认规则最适合的是一个完全 restful 风格的后端接口,如果你的后端系统没有准备好,那就直接覆盖掉吧。restful 不光是前端的事~ 是构架层面上的事情,如果想用Backbone的话,肯定是需要后端重新定义所有的接口了,但是这也是好事,毕竟 restful 逻辑更清晰,以后的更新,维护会更方便。
一、基础
现在的网站没有API都给人落后的印象了,而当下设计API流行的规范便是RESTful。REST全称是Representational State Transfer,中文意思是表述(编者注:通常译为表征)性状态转移。它首次出现在2000年Roy Fielding的博士论文中,Roy Fielding是HTTP规范的主要编写者之一。 他在论文中提到:”我这篇文章的写作目的,就是想在符合架构原理的前提下,理解和评估以网络为基础的应用软件的架构设计,得到一个功能强、性能好、适宜通信的架构。REST指的是一组架构约束条件和原则。” 如果一个架构符合REST的约束条件和原则,我们就称它为RESTful架构。
它涉及到以下这些内容。
1.1 域名
应尽量部署在专用域名之下,可以在前边加个二级头或者域名后添加api路径。
1.2 版本
API经常会变,因此要注意区分版本。一般放入URL中。
1.3 路径
路径又称”终点”(endpoint),表示API的具体网址。
在RESTful架构中,每个网址代表一种资源(resource),所以网址中不能有动词,只能有名词,而且所用的名词往往与数据库的表格名对应。一般来说,数据库中的表都是同种记录的”集合”(collection),所以API中的名词也应该使用复数。
举例来说,有一个API提供动物园(zoo)的信息,还包括各种动物和雇员的信息,则它的路径应该设计成下面这样。
https://api.example.com/v1/zoos
https://api.example.com/v1/animals
https://api.example.com/v1/employees
1.4 HTTP动词
对于资源的具体操作类型,由HTTP动词表示。
常用的HTTP动词有下面五个(括号里是对应的SQL命令)。
- GET(SELECT):从服务器取出资源(一项或多项)
- POST(CREATE):在服务器新建一个资源
- PUT(UPDATE):在服务器更新资源(客户端提供改变后的完整资源)
- PATCH(UPDATE):在服务器更新资源(客户端提供改变的属性)
- DELETE(DELETE):从服务器删除资源
下面是一些例子。
- GET /zoos:列出所有动物园
- POST /zoos:新建一个动物园
- GET /zoos/ID:获取某个指定动物园的信息
- PUT /zoos/ID:更新某个指定动物园的信息(提供该动物园的全部信息)
- PATCH /zoos/ID:更新某个指定动物园的信息(提供该动物园的部分信息)
- DELETE /zoos/ID:删除某个动物园
- GET /zoos/ID/animals:列出某个指定动物园的所有动物
- DELETE /zoos/ID/animals/ID:删除某个指定动物园的指定动物
1.5 过滤信息
如果记录数量很多,服务器不可能都将它们返回给用户。API应该提供参数,过滤返回结果。
下面是一些常见的参数。
- ?limit=10:指定返回记录的数量
- ?offset=10:指定返回记录的开始位置
- ?page=2&per_page=100:指定第几页,以及每页的记录数
- ?sortby=name&order=asc:指定返回结果按照哪个属性排序,以及排序顺序
- ?animal_type_id=1:指定筛选条件
1.6 状态码
服务器向用户返回的状态码和提示信息,常见的有以下一些(方括号中是该状态码对应的HTTP动词)。
- 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 – [*]:用户发出的请求针对的是不存在的记录,服务器没有进行操作,该操作是幂等的
- 405 method not allowed – [*]:该http方法不被允许
- 406 Not Acceptable – [GET]:用户请求的格式不可得(比如用户请求JSON格式,但是只有XML格式)
- 410 Gone -[GET]:用户请求的资源被永久删除,且不会再得到的
- 422 Unprocesable entity – [POST/PUT/PATCH] 当创建一个对象时,发生一个验证错误
- 500 INTERNAL SERVER ERROR – [*]:服务器发生错误,用户将无法判断发出的请求是否成功
1.7 错误处理
如果状态码是4xx,就应该向用户返回出错信息。一般来说,返回的信息中将error作为键名,出错信息作为键值即可。
|
|
1.8 返回结果
针对不同操作,服务器向用户返回的结果应该符合以下规范。
- GET /collection:返回资源对象的列表(数组)
- GET /collection/resource:返回单个资源对象
- POST /collection:返回新生成的资源对象
- PUT /collection/resource:返回完整的资源对象
- PATCH /collection/resource:返回完整的资源对象
- DELETE /collection/resource:返回一个空文档
二、最佳实践
2.1 Slim框架的使用
推荐一个轻量版PHP RESTful框架:Slim ,有兴趣的同学可以参考其文档:http://docs.slimframework.com/
下面以一个网上的教程给大家说明,主要是应用前端框架AngularJS 和 后端PHP框架Slim搭设的一个简易图书管理系统为例。
代码实现
主要的工作是在项目根目录下的index.php文件里进行的,第一步需要引入Slim框架
|
|
2.x 测试 - 插件使用
Chrome 插件 Postman:
Chrome插件Json-viewer 和 json-handle
###
三、扩展
3.1 不要默认使用大括号封装,但要在需要的时候支持
json 还是回调,那是个问题:
|
|
or
好的做法是:
- http://example.com/api/xxx?type=jsonp&callback=yourCallBackName
- http://example.com/api/xxx?type=json
- http://example.com/api/xxx?type=xml
就返回对应结构的数据。
3.2 如何使用 Last-Modified 和 Etags 如何帮助提高性能?
开发者会把 Last-Modified 和 ETags 请求的 HTTP 报头一起使用,这样可利用客户端(例如浏览器)的缓存。因为服务器首先产生 Last-Modified/Etag 标记,服务器可在稍后使用它来判断页面是否已经被修改。本质上,客户端通过将该记号传回服务器要求服务器验证其缓存是否过期。
HTTP 协议规格说明定义 ETag
为“被请求变量的实体值”。 服务器单独负责判断记号是什么及其含义,并在 HTTP 响应头中将其传送到客户端,以下是服务器端返回的格式:
ETag: “d41d8cd98f00b204e9800998ecf8427e”
客户端的查询更新格式是这样的:
If-None-Match: W/“d41d8cd98f00b204e9800998ecf8427e”
如果ETag没改变,则返回状态304,内容为空,这也和Last-Modified一样。下面再扔些php的例子看看:
|
|
补充:对于前端部分网上的一些做法是:Gulp对所有的静态资源进行预处理,生成一份manifest,标明了预处理前后文件之间的对应关系。DEMO, 另外腾讯前端团队的一篇关于web缓存系列文章大家也可以查阅下:直通车
总结
技术的变革一般都是为了提高生产力的,restful的初衷也是。它提倡简单(理论上讲只要业务实体抽象的好就够了),纯粹(每个资源就四种操作)的 API 设计思想,需要使用者坚持信仰(坚持基本原则),适度灵活。
— 来自SF.gg
Q&A
1. 务器返回的数据格式,应该使用JSON还是使用XML?
推送使用JSON,如果提供的服务对象较多,可以设置兼容XML
2. REST能应用在什么场景?
REST规范中明确规定,处理的是资源(或者实体),而不是动作。换句话说,REST处理的是books或者animals这种东西,而login之类的业务逻辑是动作,不适用REST。
restful 可以看做 orm 的 web api 形式,也就是说,资源指的是数据库里面的表(或者表的连接),或者是你nosql数据库里面的对象。当调用者需要并且有权直接操作它们,或者是以表的粒度操作数据库,才需要使用 restful。
3. 统计能使用REST吗?
4. 兴趣探讨Vue.js、ReactJS、AngularJS
5. 扩展:API Cookie加密
6. php crud 和resetful的相似之处
参考
简单版:
高阶版:
UPS:
- https://segmentfault.com/a/1190000004038353
- https://segmentfault.com/a/1190000002690813
- https://zhujun24.github.io/2014/12/10/AngularJS%E5%85%A5%E9%97%A8%E7%9A%84%E5%B0%8FDemo/
- https://zhujun24.github.io/2015/03/19/%E7%94%A8Slim%E8%BD%BB%E5%9E%8BPHP%E6%A1%86%E6%9E%B6%E5%86%99RESTful%20APIs/
- https://segmentfault.com/a/1190000004690182