什么是 REST?
REST 即表述性状态传递(英文:Representational State Transfer,简称REST)是Roy Fielding博士在2000年他的博士论文中提出来的一种软件架构风格(http://www.ics.uci.edu/~field…)。它是一种针对网络应用的设计和开发方式,可以降低开发的复杂性,提高系统的可伸缩性。
六个约束:
统一接口(Uniform Interface)
无状态(Stateless)
缓存(Cacheable)
客户-服务器(Client-Server)
分层系统(Layered System)
按需代码(Code on Demand)
统一接口(Uniform Interface)
使REST 架构风格区别于其他基于网络的架构风格的核心特征是,它强调组件之间要有一个统一的接口。通过在组件接口上应用通用性的软件工程原则,整体的系统架构得到了简化,交互的可见性也得到了改善。实现与它们所提供的服务是解耦的,这促进了独立的可进化性。然而,付出的代价是,统一接口降低了效率,因为信息都使用标准化的形式来转移,而不能使用特定于应用的需求的形式。REST 接口被设计为可以高效地转移大粒度的超媒体数据,并针对Web的常见情况做了优化,但是这也导致了该接口对于其他形式的架构交互并不是最优的。
无状态(Stateless)
通信必须在本质上是无状态的,因此从客户到服务器的每个请求都必须包含理解该请求所必需的所有信息,不能利用任何存储在服务器上的上下文,会话状态因此要全部保存在客户端。
缓存(Cacheable)
为了改善网络的效率。缓存约束要求一个请求的响应中的数据被隐式地或显式地标记为可缓存的或不可缓存的。如果响应是可缓存的,那么客户端缓存就可以为以后的相同请求重用这个响应的数据。
客户-服务器(Client-Server)
通过分离用户接口和数据存储这两个关注点,我们改善了用户接口跨多个平台的可移植性;同时通过简化服务器组件,改善了系统的可伸缩性。然而,对于 Web来说,最重要的是这种关注点的分离允许组件独立地进化,从而支持多个组织领域的Internet规模的需求。
分层系统(Layered System)
分层系统风格通过限制组件的行为(即,每个组件只能“看到”与其交互的紧邻层),将架构分解为若干等级的层。通过将组件对系统的知识限制在单一层内,为整个系统的复杂性设置了边界,并且提高了底层独立性。我们能够使用层来封装遗留的服务,使新的服务免受遗留客户端的影响,通过将不常用的功能转移到一个共享的中间组件中,从而简化组件的实现。中间组件还能够通过支持跨多个网络和处理器的负载均衡,来改善系统的可伸缩性。
按需代码(Code on Demand)
通过减少必须被预先实现的功能的数目,简化了客户端的开发。允许在部署之后下载功能代码也改善了系统的可扩展性。然而,这也降低了可见性,因此它只是 REST 的一个可选的约束。
HTTP 动作
GET
HTTP GET 用于检索(读取)资源。正确的情况返回JSON
与200 HTTP
响应码,在错误的情况下他们通常返回404(NOT FOUND)
或400(BAD REQUEST)
。
示例
GET http://www.example.com/custom…
GET http://www.example.com/custom…
GET http://www.example.com/bucket…
通过GET
它应该永远不会修改服务器上的任何资源。
POST
HTTP POST 通常用于创建资源。正确的情况返回201 HTTP
响应码及Location header
(资源 URI)。
示例
POST http://www.example.com/customers
POST http://www.example.com/custom…
PUT
HTTP PUT 通常用于更新资源。将请求正文内容替换已知资源的原始数据。
示例
PUT http://www.example.com/custom…
PUT http://www.example.com/custom…
DELETE
HTTP DELETE 用于删除由URI
标识的资源。成功删除返回200 HTTP
及响应正文或没有正文响应204 HTTP(NO CONTENT)
。
示例
DELETE http://www.example.com/custom…
DELETE http://www.example.com/custom…
DELETE http://www.example.com/bucket…
下表是 URI 结合 HTTP METHOD 建议的返回值
HTTP Verb(Method) | /customers | /customers/{id} |
GET | 200 (OK)。客户列表,数据量大可使用分页排序筛选 | 200 (OK)。单个客户。404 (Not Found) ID客户不存在,400 (BAD REQUEST) ID不合法 |
POST | 201 (Created),’Location’ header 为 /customers/{id} 包含新的资源ID | 404 (Not Found) |
PUT | 404 (Not Found) | 200 (OK)或者204 (No Content)。404 (Not Found) ID客户不存在,400 (BAD REQUEST) ID不合法 |
DELETE | 404 (Not Found) | 200 (OK)或者204 (No Content)。404 (Not Found) ID客户不存在,400 (BAD REQUEST) ID不合法 |
资源命名
一切在工艺软件开发的命名是成功的关键。
除了适当的应用 HTTP Verb(Method),资源命名可以说是最受争议和最重要的概念。当资源被命名好时,API 是直观和易于使用的。做得太差,同样的 API 能感觉太表面化和难以使用和理解。下面是一些提示,让你去当创建资源 URI 为您新的 API。
资源 URI 应使用名词而不是动词命名。一个 RESTful URI 应该指一种资源,而不是采取行动。名词具有属性而动词没有。
服务套件中每个资源至少有一个 URI 标识它。URI 应遵循一种可预见,分层结构,以增加可理解性,从而提高可用性。
在一个订单系统与客户、订单、行项目的资源设计:
创建一个新的客户
POST http://www.example.com/customers
读取客户 ID 为 33245
GET http://www.example.com/custom…
相同的 URI 将用于更新(PUT)与删除(DELETE)客户
这里为产品设计的 URI:
POST http://www.example.com/products
创建一个新的产品
GET|PUT|DELETE http://www.example.com/produc…
读取、更新、删除 ID 为 66432 的产品为
现在变得很有趣,我们如何为客户创建新的订单?
一种选择是
POST http://www.example.com/orders
毫无疑问它是可以工作的,但它却在客户的上下文之外下面的 URI 更清晰
POST http://www.example.com/custom…
现在我们知道这个订单是为客户 33245 创建的获取 33245 客户订单使用如下 URI
GET http://www.example.com/custom…
现在,我们继续来看分层的 URI 设计。如下:
POST http://www.example.com/custom…
这会将行项目添加到订单 #8769(这是客户 #33245),获取该 URI 资源会返回订单下所有的行项目,如果行项目毫无意义或者在客户的上下文以外的地方能感觉到我们会提供这样一个 URI
POST www.example.com/orders/8769/lineitems
看看一些广泛使用的 API 来得到资源命名窍门和利用你的队友来完善您的 API 资源。
Twitter: https://dev.twitter.com/docs/api
Facebook: http://developers.facebook.co…
LinkedIn: https://developer.linkedin.co…
GitHub: https://developer.github.com/v3/
Response Body
简单响应
示例
{ "url":"https://api.github.com/gists/20c98223d9b59e1d48e5", "id":"1", "description":"description of gist", "public":true, "user":{ "login":"octocat", "id":1, "avatar_url":"https://github.com/images/error/octocat_happy.gif", "gravatar_id":"somehexcode", "url":"https://api.github.com/users/octocat" }, "comments":0, "comments_url":"https://api.github.com/gists/19d18b30e8af75090307/comments/", "html_url":"https://gist.github.com/1", "git_pull_url":"git://gist.github.com/1.git", "git_push_url":"git@gist.github.com:1.git", "created_at":"2010-04-14T02:15:15Z" }
分页响应
total_count
总记录数items
数据项
示例
{ "total_count":40, "items":[ { "id":3081286, "name":"Tetris", "full_name":"dtrupenn/Tetris", "owner":{ "login":"dtrupenn", "id":872147, "type":"User" }, "private":false, "html_url":"https://github.com/dtrupenn/Tetris", "description":"A C implementation of Tetris using Pennsim through LC4", "fork":false, "url":"https://api.github.com/repos/dtrupenn/Tetris", "created_at":"2012-01-01T00:31:50Z", "updated_at":"2013-01-05T17:58:47Z", "pushed_at":"2012-01-01T00:37:02Z" } ] }
错误响应
code
错误码message
错误信息
示例
{ "code": 12345, "message": "错误描述" }
参考资源
http://www.restapitutorial.com/
https://www.oschina.net/trans…