RESTful服务至上实践。RESTful服务至上实践。

本文主要读者

正文主要读者

引言

引言

REST是什么

REST是什么

  合接口

  合并接口

    依据资源

    依据资源

    经特征来操作资源

    透过特色来操作资源

    起描述的音

    自从描述的音信

    超媒体即采用状态引擎(HATEOAS)

    超媒体即以状态引擎(HATEOAS)

  无状态

  无状态

  可缓存

  可缓存

  C-S架构

  C-S架构

  分段系统

  分层系统

  按需编码(可选)

  按需编码(可选)

REST快速提示

REST快速提示

  使HTTP动词表示有意义

  下HTTP动词表示有意思

  理所当然之资源名

  合理的资源名

  XML和JSON

  XML和JSON

  缔造适当粒度的资源

  始建适当粒度的资源

  设想连通性

  设想连通性

定义

定义

  幂等性

  幂等性

  安全

  安全

HTTP动词

HTTP动词

  GET

  GET

  PUT

  PUT

  POST

  POST

  PUT和POST的创办于

  PUT和POST的创造于

  DELETE

  DELETE

资源命名

资源命名

  资源URI示例

  资源URI示例

  资源命名的反例

  资源命名的反例

  复数

  复数

返表征

返表征

  资源通过链接的只是发现性(HATEOAS续)

  资源通过链接的不过发现性(HATEOAS续)

    绝小化链接推荐

    太小化链接推荐

    链接格式

    链接格式

  包裹响应

  包装响应

  拍卖跨域问题

  处理跨域问题

    支持CORS

    支持CORS

    支持JSONP

    支持JSONP

查询,过滤与分页

询问,过滤跟分页

  结果限制

  结果限制

    就此范围标记进行限

    因而范围标记进行界定

    因此字符串查询参数进行限定

    故而字符串查询参数进行界定

    依据范围的响应

    基于范围之应

  分页

  分页

  结果的过滤与排序

  结果的过滤和排序

    过滤

    过滤

    排序

    排序

劳动版本管理

劳版本管理

  经过内容商支持版本管理

  透过内容商支持版本管理

  当没点名版本时,返回什么版本?

  当没点名版本时,返回什么版本?

  求不支持之版

  要不支持之本子

  嘿时候该创建一个初本子?

  哟时候理应创建一个初本子?

    破坏性的修改

    破坏性的改动

    非破坏性的改动

    非破坏性的改

  版本控制应在啊级别出现?

  版本控制应以啊级别出现?

  运用Content-Location来增长响应

  行使Content-Location来增强响应

  带有Content-Type的链接

  带有Content-Type的链接

  寻来支持之版

  找有支持之本子

    本人该又支持小个本子?

    自己应该而且支持小个版本?

    弃用

    弃用

    自身争告客户端给弃用的资源?

    自我怎么告客户端给弃用的资源?

日子/时间处理

日期/时间拍卖

  Body内容中之日期/时间序列化

  Body内容被之日子/时间序列化

  HTTP
Headers中之日子/时间序列化

  HTTP
Headers中之日子/时间序列化

保护服务的平安

护卫服务之安

  身份验证

  身份验证

  传安全

  传输安全

  授权

  授权

  应用程序安全

  应用程序安全

缓存和可伸缩性

缓存和可伸缩性

  ETag Header

  ETag Header

HTTP状态码(前10)

HTTP状态码(前10)

外加资源

叠加资源

  书籍

  书籍

  网站

  网站

 

 

正文主要读者

  该最佳实践文档适用于对RESTful
Web服务感兴趣之开发人员,该服务吗超过多独服务之零部件提供了于高的可靠性与一致性。按照本文的点拨,可速、广泛、公开地也内外部客户使用。

  本文中之指点标准一致适用于工程师等,他们愿意用这些根据最佳实践标准开发之劳动。虽然他们愈发关注缓存、代理规则、监听与安全等连锁方,但是该文档能作为一如既往卖包含所有品种服务之总指南。

  另外,通过打这些点标准,管理人员了解及创建公共的、提供高稳定的劳动所用花的鼎力,他们为只是从中受益。

 

本文主要读者

  该最佳实践文档适用于对RESTful
Web服务感兴趣之开发人员,该服务吗超越多只劳务之组件提供了较高之可靠性和一致性。按照本文的点拨,可速、广泛、公开地为内外部客户以。

  本文中的指点原则一致适用于工程师们,他们愿意用这些根据最佳实践标准开发的劳务。虽然她们更加关心缓存、代理规则、监听与康宁等有关方,但是该文档能作为一如既往份包含所有品种服务的总指南。

  另外,通过打这些点原则,管理人员了解及开创公共的、提供高稳定性的劳务所欲花的大力,他们为只是从中受益。

 

引言

  现今已发出雅量关于RESTful
Web服务至上实践的相关资料(详见本文最后之相干文献有)。由于撰文的年月不同,许多材料被的内容是矛盾的。此外,想使经查文献来了解这种服务的腾飞是匪绝长之。为了打探RESTful这无异定义,至少要查阅三顶五依照有关文献,而本文将能帮助你加快这同一历程——摒弃多余的讨论,最大化地提炼出REST的顶尖实践与正规。

  与其说REST是同等效标准,REST更如是平栽口径的聚众。除了六单主要之规格外就从未有过其余的规范了。实际上,虽然有所谓的“最佳实践”和业内,但这些事物还与宗教斗争一样,在连地演变。

  本文围绕REST的广问题提出了观及仿食谱式的讨论,并由此介绍部分简短的背景知识对创建真实处境下之优先生产条件遭到平等的REST服务提供文化。本文收集了来自外渠道的信息,经历了一次次之破产后不断改进。

  但于REST模式是否必然比SOAP好用本有比较生争(反之亦然),也许在好几情况下按欲创造SOAP服务。本文在提及SOAP时并未花较生篇幅来讨论她的对立优点。相反由于技术同行业在不断进步,我们用延续坚持我们的使–REST是当时设计web服务的最佳方法。

  第一部分概述REST的义、设计则与其的与众不同之远在。第二有列举了有的略贴士来记忆REST的服务理念。之后的一部分则会重复尖锐地吧web服务创建人员提供一些细节之支持及议论,来实现一个能明白展示在生养环境中之高质量REST服务。

 

引言

  现今早就生恢宏关于RESTful
Web服务至上实践的系材料(详见本文最后的相干文献有)。由于撰文的流年各异,许多资料遭受之情节是矛盾的。此外,想只要经过查文献来打听这种劳动之前进是免太长的。为了了解RESTful这等同定义,至少需查阅三暨五遵循有关文献,而本文将能帮您加速这同一过程——摒弃多余的议论,最大化地提炼出REST的最佳实践以及业内。

  与其说REST是均等套标准,REST更如是相同栽口径的汇。除了六独重要之基准外即从来不其余的标准了。实际上,虽然有所谓的“最佳实践”和专业,但这些东西都和宗教斗争一样,在频频地演变。

  本文围绕REST的大面积问题提出了意见跟仿食谱式的讨论,并由此介绍部分简练的背景知识对创建真实处境下的事先生产条件遭到千篇一律的REST服务提供文化。本文收集了来自外渠道的信息,经历了一次次之败后不断改进。

  但对于REST模式是否必然比SOAP好用本有于生争(反之亦然),也许在少数情况下仍待创造SOAP服务。本文在提及SOAP时并未花较生篇幅来讨论她的对立优点。相反由于技术同行业在不断进步,我们将继承坚持我们的只要–REST是就设计web服务的最佳艺术。

  第一有的概述REST的含义、设计则与它的特种之远在。第二片列举了有些稍贴士来记忆REST的服务意见。之后的一些则会另行尖锐地为web服务创建人员提供一些细节的支持和议论,来实现一个能公开展示在生养条件中之高质量REST服务。

 

REST是什么?

  REST架构方式讲述了六种设计则。这些用于架构的筹划则,最早是由Roy
Fielding在他的博士论文中提出并定义了RESTful风格。(详见http://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm)

  六只规划则分别是:

  • 联合接口
  • 无状态
  • 可缓冲
  • C-S架构
  • 支行系统
  • 按需编码

  以下是这些规划则的详实讨论:

REST是什么?

  REST架构方式讲述了六种植设计则。这些用于架构的规划则,最早是由于Roy
Fielding在他的博士论文中提出并定义了RESTful风格。(详见http://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm)

  六个规划则分别是:

  • 合接口
  • 无状态
  • 可缓冲
  • C-S架构
  • 分层系统
  • 按需编码

  以下是这些规划则的详细谈论:

联合接口

  统一接口准则定义了客户端和服务端之间的接口,简化和分手了框架结构,这样一来每个片都只是单独演化。以下是接口统一之季只标准化:

合并接口

  统一接口准则定义了客户端和服务端之间的接口,简化和分手了框架结构,这样一来每个有还只是单独演化。以下是接口统一的季独规格:

  基于资源

  不同资源要为此URI来唯一标识。返回给客户端的特点和资源本身在概念上有所不同,例如服务端不见面一直传送一个数据库资源,然而,一些HTML、XML或JSON数据能亮部分数据库记录,如用芬兰语来表述要用UTF-8编码则要基于请求和服务器实现之底细来控制。

  基于资源

  不同资源要用URI来唯一标识。返回给客户端的表征和资源本身在概念上有所不同,例如服务端不会见直接传送一个数据库资源,然而,一些HTML、XML或JSON数据可知显示部分数据库记录,如用芬兰语来抒发还是用UTF-8编码则只要因请求和服务器实现的底细来决定。

  通过特征来操作资源

  当客户端收到包含元数据的资源的特征时,在闹权力的景况下,客户端都掌握的够用的信,可以本着劳务端的资源进行删改。

  通过特色来操作资源

  当客户端收到包含元数据的资源的特色时,在有权力的状下,客户端都控制的足的信息,可以针对服务端的资源拓展删改。

  自描述的音信

  每条信息都蕴涵足够的数额用于确认信息该如何处理。例如要出于网络媒体类型(已清楚的如果MIME类型)来确认要调用哪个解析器。响应同样为标志了它们的缓存能力。

  自描述的音讯

  每条消息还包含足够的数用于确认信息该怎么处理。例如要出于网络媒体类型(已领略的比方MIME类型)来认可要调用哪个解析器。响应同样为标志了它们的缓存能力。

  超媒体即采用状态引擎(HATEOAS)

  客户端通过body内容、查询串参数、请求头和URI(资源名称)来传送状态。服务端通过body内容,响应码和响应头传送状态为客户端。这项技术被叫作超媒体(或超文本链接)。

  除了上述内容他,HATEOS也意味,必要之时节链接也只是叫含有在回到的body(或头部)中,以提供URI来索对象自我要涉对象。下文将对准斯进行重新详尽的阐释。

  统一接口是每个REST服务计划时之必需准则。

  超媒体即用状态引擎(HATEOAS)

  客户端通过body内容、查询串参数、请求头和URI(资源名称)来传送状态。服务端通过body内容,响应码和响应头传送状态让客户端。这项技艺让称为超媒体(或超文本链接)。

  除了上述情节外,HATEOS也表示,必要之上链接也可是于含有在返回的body(或头部)中,以提供URI来搜寻对象自我或干对象。下文将本着是展开双重详实的论述。

  统一接口是每个REST服务统筹时之不可或缺准则。

无状态

  正如REST是REpresentational State
Transfer的缩写,无状态十分重点。本质上,这标志了处理要所急需的状态已经包含在伸手我里,也发或是URI的均等组成部分、查询串参数、body或头部。URI能够唯一标识每个资源,body中为蕴藏了资源的转态(或转态变更情况)。之后,服务器将开展处理,将相关的状态或资源通过头部、状态和响应body传递给客户端。

  从事我们当下同样行当之多数人口还习惯以容器来编程,容器中产生一个“会话”的概念,用于在差不多单HTTP请求下保持状态。在REST中,如果如当多个请求下维持用户状态,客户端必须概括客户端的有着信息来成功请求,必要常常更发送请求。自从服务端不需保障、更新或传递会话状态后,无状态性得到了双重怪的延展。此外,负载均衡器无需担心与管状态系统里面的对话。

  所以状态及资源中发生啊区别?服务器对状态,或者说是应用状态,所关注的点是在时下对话或要被若到位请求所用的数据。而资源,或者说是资源状态,则是概念了资源特点的数目,例如存储于数据库被的数额。由此可见,应用状态是是就客户端与要的改变而改变之数量。相反,资源状态对于发出请求的客户端的话是无转换的。

  于网络以之某某同特定岗位上摆一个回来按钮,是为其仰望您可知随一定之逐一来操作为?其实是盖她违反了无状态的口径。有许多不遵循无状态原则的案例,例如3-Legged
OAuth,API调用速度限制等。但要么要尽可能确保服务器受到不需要以差不多只请求下保持利用状态。

无状态

  正如REST是REpresentational State
Transfer的缩写,无状态不行关键。本质上,这标志了拍卖要所要的状态都包含在求我里,也产生或是URI的一致有的、查询串参数、body或头部。URI能够唯一标识每个资源,body中呢蕴含了资源的转态(或转态变更情况)。之后,服务器将进行拍卖,将有关的状态或资源通过头部、状态与应body传递让客户端。

  从事我们顿时同一业的大部分口且习惯使用容器来编程,容器被发出一个“会话”的定义,用于在差不多个HTTP请求下保持状态。在REST中,如果要于差不多独请求下保持用户状态,客户端必须概括客户端的具有消息来就请求,必要时再次发送请求。自从服务端不需要保持、更新或传递会话状态后,无状态性得到了又不行之延展。此外,负载均衡器无需担心和无状态系统里面的对话。

  所以状态和资源间发生什么差别?服务器对状态,或者说是应用状态,所关心之触发是以时对话或请被设到位请求所待的数目。而资源,或者说是资源状态,则是概念了资源特色的多少,例如存储在数据库被之数据。由此可见,应用状态是凡趁客户端以及请的更动如果变更的数目。相反,资源状态对于发出请求的客户端的话是无换的。

  于网络下的某某平等一定岗位及摆放一个归按钮,是为她愿意而能按自然的各个来操作也?其实是因它违反了随便状态的法。有很多无遵循无状态原则的案例,例如3-Legged
OAuth,API调用速度限制等。但要么如硬着头皮保证服务器受到莫待以差不多单请求下保持利用状态。

可缓存

  以万维网上,客户端可缓存页面的响应内容。因此应都许诺隐式或显式的定义也而缓存的,若不足缓存则只要避客户端在反复央后用原来数据要污染数据来响应。管理得当的复苏存会部分地要全地除了客户端以及服务端之间的互动,进一步改善性与延展性。

可缓存

  以万维网上,客户端可缓存页面的响应内容。因此应都应隐式或显式的定义也而缓存的,若不足缓存则只要避客户端在数告后就此原数据要污染数据来响应。管理得当的复苏存会部分地还是全地除了客户端以及服务端之间的互动,进一步改善性与延展性。

C-S架构

  统一接口使得客户端和服务端相互分开。关注分离意味什么?打个假设,客户端不需仓储数据,数据还预留在服务端内部,这样叫客户端代码的可移植性得到了晋升;而服务端不需考虑用户接口和用户状态,这样一来服务端将更为简便易行容易拓展。只要接口不移,服务端和客户端好单独地拓展研发以及替换。

C-S架构

  统一接口使得客户端与服务端相互分开。关注分离意味什么?打只假设,客户端不待仓储数据,数据还留给于服务端内部,这样令客户端代码的可移植性得到了晋级;而服务端不需要考虑用户接口及用户状态,这样一来服务端将越发简便易行容易拓展。只要接口不转移,服务端和客户端可独立地开展研发及替换。

分系统

  客户端通常无法表明自己是一直或间接与端服务器进行连接。中介服务器可以由此启用负载均衡或提供共享缓存来提升系统的延展性。分层时同要考虑安全策略。

分系统

  客户端通常无法表明自己是一直或者间接与端服务器进行连接。中介服务器可以通过启用负载均衡或供共享缓存来提升系统的延展性。分层时同如果考虑安全策略。

按需编码(可选)

  服务端通过传输可尽逻辑给客户端,从而也夫现拓展与定制功能。相关的例证有编译组件Java
applets和客户端脚本JavaScript。

  遵从上述标准,与REST架构风格保持一致,能为各种分布式超媒体系统具有梦想之自然属性,比如高性能,延展性,简洁,可变性,可视化,可移植性和可靠性。

  提示:REST架构中的统筹则遭到,只有按照需要编码为而挑选项。如果有服务违反了其他随意一宗则,严格意思上无可知称之为RESTful风格。

 

按需编码(可选)

  服务端通过传输可尽逻辑给客户端,从而也该现拓展与定制功能。相关的例证有编译组件Java
applets和客户端脚本JavaScript。

  遵从上述标准,与REST架构风格保持一致,能给各种分布式超媒体系统所有梦想之自然属性,比如高性能,延展性,简洁,可变性,可视化,可移植性和可靠性。

  提示:REST架构中的计划性则遭到,只有按照需要编码为而卜项。如果有服务违反了外随意一宗则,严格意思上无可知称之为RESTful风格。

 

REST快速提示

  (根据上面提到的六只尺码)不管在技术上是未是RESTful的,这里出一些近似REST概念的建议。遵循其,可以兑现再好、更实用之劳动:

REST快速提示

  (根据上面提到的六个规格)不管在技术上是免是RESTful的,这里有一部分接近REST概念的提议。遵循其,可以实现还好、更实用之服务:

下HTTP动词表示有意义

  任何API的使用者能发送GET、POST、PUT和DELETE请求,它们非常死程度显著了所受要的目的。同时,GET请求不能够改变任何秘密的资源数量。测量与跟仍可能有,但仅仅会更新数据要未见面更新由URI标识的资源数量。

使用HTTP动词表示有意思

  任何API的使用者能发送GET、POST、PUT和DELETE请求,它们非常可怜程度显而易见了所让要的目的。同时,GET请求不克改变任何秘密的资源数量。测量和跟踪仍可能产生,但才见面更新数据而不会见更新由URI标识的资源数量。

理所当然之资源名

  合理的资源名称或路径(如/posts/23要无是/api?type=posts&id=23)可以再次简明一个告的目的。使用URL查询串来过滤数据是死好之艺术,但未应用于固定资源名称。

  适当的资源名称为服务端请求提供上下文,增加服务端API的可理解性。通过URI名称分层地翻资源,可以让使用者提供一个温馨之、容易理解的资源层次,以当她们之应用程序上采取。资源名称应当是名词,避免为动词。使用HTTP方法来指定要的动作有,能吃工作越来越的不可磨灭。

客观之资源名

  合理之资源名称或路径(如/posts/23而无是/api?type=posts&id=23)可以再明显一个央的目的。使用URL查询串来过滤数据是格外好之艺术,但未应用于固定资源名称。

  适当的资源名称为服务端请求提供上下文,增加服务端API的可理解性。通过URI名称分层地翻资源,可以于使用者提供一个融洽之、容易掌握的资源层次,以当她们之应用程序上行使。资源名称应当是名词,避免为动词。使用HTTP方法来指定要的动作有,能给工作越的不可磨灭。

XML和JSON

  建议默认支持json,并且,除非花费很震惊,否则便同时支持json和xml。在美妙图景下,让使用者仅通过转移扩展名.xml和.json来切换类型。此外,对于支撑ajax风格的用户界面,一个被包裹的应是甚有赞助的。提供一个为卷入的响应,在默认的抑发生独立放展名的图景下,例如:.wjson和.wxml,表明客户端请求一个深受卷入的json或xml响应(请参见下的包装响应)。

  “标准”中针对json的求非常少。并且这些需求单是语法性质的,无关内容格式和布局。换句话说,REST服务端调用的json响应是协商的如出一辙局部——在业内中无相关描述。更多关于json数据格式可以在http://www.json.org/上找到。

  关于REST服务遭遇xml的以,xml的业内和约定除了以语法正确的价签及文本外没有外的来意。特别地,命名空间不是吧非该是叫下以REST服务端的前后文中。xml的回重新近乎于json——简单、容易看,没有模式及命名空间的底细展现——仅仅是数码和链接。如果它比当下再度扑朔迷离的话,参看本节的率先段子——使用xml的工本是惊人的。鉴于我们的涉,很少有人用xml作为响应。在它们为完全淘汰之前,这是终极一个但吃定的地方。

XML和JSON

  建议默认支持json,并且,除非花费很震惊,否则就是又支持json和xml。在良好图景下,让使用者仅经过改变扩展名.xml和.json来切换类型。此外,对于支持ajax风格的用户界面,一个于卷入的应是异常有救助的。提供一个受包裹的应,在默认的或者来独立放展名的景象下,例如:.wjson和.wxml,表明客户端请求一个为包的json或xml响应(请参见下的包装响应)。

  “标准”中针对json的渴求很少。并且这些要求才是语法性质的,无关内容格式和布局。换句话说,REST服务端调用的json响应是商的平部分——在专业中绝非有关描述。更多关于json数据格式可以以http://www.json.org/上找到。

  关于REST服务中xml的运,xml的正规和约定除了利用语法正确的标签以及文本外没有其他的打算。特别地,命名空间不是也非应该是给用于REST服务端的左右文中。xml的归来重新近乎于json——简单、容易看,没有模式及命名空间的底细展现——仅仅是多少和链接。如果她于当下又扑朔迷离的话,参看本节的首先段子——使用xml的血本是触目惊心的。鉴于我们的阅历,很少有人用xml作为响应。在它们深受完全淘汰之前,这是最终一个可是叫定的地方。

创办适当粒度的资源

  同开始,系统面临模仿底层应用程序域或数据库架构的API更易于被创造。最终,你晤面期待将这些劳务还成到一起——利用基本上起底层资源减少通信量。在创建独立的资源之后再度创更不行粒度的资源,比打再甚之一块集中创建于充分粒度的资源越是便于有。从部分不怎么的易定义之资源开始,创建CRUD(增删查改)功能,可以假设资源的始建变得再易。随后,你可以创建这些根据用例和压缩通信量的资源。

创立适当粒度的资源

  同开始,系统中拟底层应用程序域或数据库架构的API更爱被创造。最终,你晤面期待用这些劳务还做到共同——利用基本上起底层资源减少通信量。在创建独立的资源之后重新创更充分粒度的资源,比打再要命之联合集中创建于充分粒度的资源更是便于有。从有有点的容易定义之资源开始,创建CRUD(增删查改)功能,可以假设资源的创变得重爱。随后,你可创造这些根据用例和减少通信量的资源。

考虑连通性

  REST的法则之一即是并通性——通过超媒体链接实现。当于应中回到链接时,api变的更具有从描述性,而在未曾它经常服务端依然可用。至少,接口本身可以为客户端提供什么样寻找数据的参照。此外,在经POST方法创建资源时,还好动用头位置包含一个链接。对于响应中支持分页的集聚,”first”、
“last”、”next”、和”prev”链接至少是充分管用的。

 

设想连通性

  REST的规律之一就是是并通性——通过超媒体链接实现。当在响应中回到链接时,api变的复有着从描述性,而以尚未其常服务端依然可用。至少,接口本身可以吧客户端提供哪些寻找数据的参阅。此外,在经过POST方法创建资源时,还足以行使头位置包含一个链接。对于响应中支持分页的集合,”first”、
“last”、”next”、和”prev”链接至少是特别有效之。

 

定义

定义

幂等性

  不要打字面意思来解什么是幂等性,恰恰相反,这跟一些职能紊乱的小圈子无关。下面是发源维基百科的分解:

以微机是中,术语幂等用于更周全地叙述一个操作,一差还是累履行该操作发生的结果是千篇一律的。根据使用的上下文,这说不定发两样的意思。例如,在术还是子例程调用具有副作用的状下,意味着当首先调用之后被改的状态也保障不更换。

  从REST服务端的角度来拘禁,由于操作(或服务端调用)是幂等的,客户端可据此更的调用而产生同样之结果——在编程语言中操作像是一个”setter”(设置)方法。换句话说,就是运用多个相同的伸手和祭单个请求效果同样。注意,当幂等操作以服务器上产生相同的结果(副作用),响应本身也许是例外的(例如当差不多个请求中,资源的状态恐怕会见转移)。

  PUT和DELETE方法让定义也是幂等的。查看http请求中delete动词的警示信息,可以参考下文的DELETE部分。GET、HEAD、OPTIO和TRACE方法从被定义也安之办法后,也被定义也幂等的。参照下关于安全的段落。

幂等性

  不要打字面意思来掌握什么是幂等性,恰恰相反,这跟某些职能紊乱的园地无关。下面是发源维基百科的说明:

于电脑科学中,术语幂等用于更周全地讲述一个操作,一潮还是数实践该操作发生的结果是一律的。根据使用的上下文,这也许来例外之意思。例如,在术要子例程调用拥有副作用的图景下,意味着当率先调用之后于改的状态为保障无换。

  从REST服务端的角度来拘禁,由于操作(或服务端调用)是幂等的,客户端好据此重新的调用而发出相同的结果——在编程语言中操作像是一个”setter”(设置)方法。换句话说,就是利用多个一律之呼吁和利用单个请求效果同样。注意,当幂等操作以服务器上发出同样之结果(副作用),响应本身也许是差之(例如在多独请求中,资源的状态恐怕会见改变)。

  PUT和DELETE方法给定义为凡幂等的。查看http请求中delete动词的告诫信息,可以参考下文的DELETE部分。GET、HEAD、OPTIO和TRACE方法从被定义也平安的法门后,也被定义也幂等的。参照下关于安全之段。

安全

  来自维基百科:

一对艺术(例如GET、HEAD、OPTIONS和TRACE)被定义为安全的法子,这表示她才于用于信息搜索,而未能够改变服务器的状态。换句话说,它们不会见生出副作用,除了相对来说无害的熏陶而日志、缓存、横幅广告要计数服务等。任意的GET请求,不考虑采取状态的上下文,都为认为是平安之。

  总之,安全意味着调用的点子无会见引起副作用。因此,客户端好数用安全之求而无用担心对服务端产生任何副作用。这意味着服务端必须遵守GET、HEAD、OPTIONS和TRACE操作的安概念。否则,除了对消费端产生模糊外,它还会造成Web缓存,搜索引擎和其他活动代理的题目——这将在服务器上闹意想不到的究竟。

  根据定义,安全操作是幂等的,因为它于服务器上产生同样的结果。

  安全的计让实现呢单纯念操作。然而,安全并无意味着服务器必须每次都回到相同之应。

 

安全

  来自维基百科:

局部主意(例如GET、HEAD、OPTIONS和TRACE)被定义也平安的方,这代表她只是受用来信息寻找,而休克更改服务器的状态。换句话说,它们不会见时有发生副作用,除了相对来说无害的熏陶使日志、缓存、横幅广告或计数服务等。任意的GET请求,不考虑采用状态的上下文,都叫看是安全之。

  总之,安全意味着调用的计不会见招副作用。因此,客户端好屡屡使用安全之乞求而休用担心对服务端产生其他副作用。这表示服务端必须信守GET、HEAD、OPTIONS和TRACE操作的安概念。否则,除了对消费端产生模糊外,它还会招致Web缓存,搜索引擎以及另外活动代理的题目——这将以服务器上生意想不到的后果。

  根据定义,安全操作是幂等的,因为它在服务器上发同样之结果。

  安全的办法为实现呢特念操作。然而,安全并无代表服务器必须每次都回去相同的响应。

 

HTTP动词

  Http动词主要按“统一接口”规则,并提供于咱相应的冲名词的资源的动作。最要还是极端常用之http动词(或者称方法,这样叫可能更恰当些)有POST、GET、PUT和DELETE。这些分别指向应于创建、读取、更新与去(CRUD)操作。也时有发生广大其它的动词,但是使用频率比较低。在这些应用比较少的措施吃,OPTIONS和HEAD往往利用得又多。

HTTP动词

  Http动词主要遵循“统一接口”规则,并提供给咱们相应的依据名词的资源的动作。最关键还是最好常用的http动词(或者叫做方法,这样名可能更恰当些)有POST、GET、PUT和DELETE。这些分别针对应于创建、读取、更新与去(CRUD)操作。也时有发生不少任何的动词,但是下频率比较小。在这些下于少的点子吃,OPTIONS和HEAD往往利用得重多。

GET

  HTTP的GET方法用于检索(或读取)资源的数。在对的恳求路径下,GET方法会返回一个xml或者json格式的数额,以及一个200底HTTP响应代码(表示对返回结果)。在错情况下,它便返回404(不存)或400(错误的恳求)。

  例如:

*  GET http://www.example.com/customers/12345*
  GET http://www.example.com/customers/12345/orders
  GET http://www.example.com/buckets/sample

  按照HTTP的设计规范,GET(以及附带的HEAD)请求单用于读取数据而无改多少。因此,这种用办法为看是安全的。也就是说,它们的调用没有多少修改或污染之高风险——调用1软及调用10软还是没有叫调用的效益等同。此外,GET(以及HEAD)是幂等的,这象征使用多只同之求和行使单个的要最终都拥有同等的结果。

  不要通过GET暴露不安全之操作——它应该永远都不克改服务器上的其余资源。

GET

  HTTP的GET方法用于检索(或读取)资源的数额。在科学的求路径下,GET方法会返回一个xml或者json格式的数据,以及一个200底HTTP响应代码(表示对返回结果)。在错情况下,它便返回404(不存在)或400(错误的伸手)。

  例如:

*  GET http://www.example.com/customers/12345*
  GET http://www.example.com/customers/12345/orders
  GET http://www.example.com/buckets/sample

  按照HTTP的设计规范,GET(以及附带的HEAD)请求单用于读取数据而休改多少。因此,这种使用办法于当是安的。也就是说,它们的调用没有数量修改或污染之高风险——调用1赖和调用10潮还是尚未为调用的职能等同。此外,GET(以及HEAD)是幂等的,这意味着使用多个一律之请和用单个的乞求最终都独具同样的结果。

  不要通过GET暴露不安全之操作——它应永远都无克改服务器上之别样资源。

PUT

  PUT通常为用于创新资源。通过PUT请求一个已知晓的资源URI时,需要以恳求的body中包含对原始资源的更新数据。

  不过,在资源ID是由于客服端而未服务端提供的动静下,PUT同样可为用来创造资源。换句话说,如果PUT请求的URI中带有的资源ID值在服务器上无设有,则用来创造资源。同时呼吁的body中务必带有要创的资源的数量。有人当这会起歧义,所以只有真的用,使用这种办法来创造资源应该吃慎用。

  或者我们呢堪在body中提供由客户端定义的资源ID然后使用POST来创造新的资源——假设请求的URI中无含要创建的资源ID(参见下POST的一部分)。

  例如:

*  PUT http://www.example.com/customers/12345*
  PUT http://www.example.com/customers/12345/orders/98765
  PUT http://www.example.com/buckets/secret\_stuff

  当用PUT操作更新成功时,会回到200(或者返回204,表示回去的body中莫带有其他内容)。如果采用PUT请求创建资源,成功返回的HTTP状态码是201。响应的body是可选的——如果提供的话语将会见吃又多的带来富。在开立资源时没有必要通过头部的位置返回链接,因为客户端已安装了资源ID。请参见下的返值部分。

  PUT不是一个安康的操作,因为她会窜(或创)服务器上之状态,但它是幂等的。换句话说,如果您采取PUT创建或者更新资源,然后又调用,资源仍然存在而状态不会见发生变化。

  例如,如果在资源增量计数器中调用PUT,那么是调用方法就不再是幂等的。这种情况有时候会起,且可能可以证明它是匪幂等性的。不过,建议维持PUT请求的幂等性。并强烈建议非幂等性的求使用POST。

PUT

  PUT通常被用于创新资源。通过PUT请求一个早已知道的资源URI时,需要以恳求的body中蕴含对老资源的翻新数据。

  不过,在资源ID是出于客服端而未服务端提供的气象下,PUT同样好于用来创造资源。换句话说,如果PUT请求的URI中涵盖的资源ID值在服务器上无有,则用于创造资源。同时要的body中得带有要创的资源的数量。有人以为这会生歧义,所以只有真的用,使用这种方式来创造资源应该吃慎用。

  或者我们为得以以body中提供由客户端定义之资源ID然后使用POST来创造新的资源——假设请求的URI中不含有要创建的资源ID(参见下POST的片段)。

  例如:

*  PUT http://www.example.com/customers/12345*
  PUT http://www.example.com/customers/12345/orders/98765
  PUT http://www.example.com/buckets/secret\_stuff

  当用PUT操作更新成功时,会回去200(或者返回204,表示回去的body中莫分包其他内容)。如果使用PUT请求创建资源,成功返回的HTTP状态码是201。响应的body是可选的——如果提供的讲话将会见消耗又多的牵动富。在创建资源时从没必要通过头部的职务返回链接,因为客户端已设置了资源ID。请参见下的归来值部分。

  PUT不是一个安全的操作,因为她会窜(或创办)服务器上之状态,但它是幂等的。换句话说,如果您以PUT创建或者更新资源,然后重新调用,资源还是存在而状态不会见发生变化。

  例如,如果当资源增量计数器中调用PUT,那么这个调用方法就不再是幂等的。这种情况有时候会起,且可能得验证她是休幂等性的。不过,建议维持PUT请求的幂等性。并强烈建议非幂等性的求使用POST。

POST

  POST请求时被用于创造新的资源,特别是深受用来创造于属于资源。从属于资源就属于任何资源(如大资源)的资源。换句话说,当创建一个新资源时,POST请求发送给父资源,服务端负责用新资源与爸爸资源拓展关联,并分配一个ID(新资源的URI),等等。

  例如:

  POST http://www.example.com/customers
  POST http://www.example.com/customers/12345/orders

  当创建成功时,返回HTTP状态码201,并顺便一个职务头信息,其中涵盖指向最先创建的资源的链接。

  POST请求既非是平安之而非是幂等的,因此它们为定义为非幂等性资源要。使用简单只同之POST请求很可能会见招致创建两个饱含相同信息的资源。

POST

  POST请求时给用来创造新的资源,特别是受用来创造于属于资源。从属于资源就属于外资源(如爸爸资源)的资源。换句话说,当创建一个新资源时,POST请求发送给父资源,服务端负责用新资源与大资源开展关联,并分配一个ID(新资源的URI),等等。

  例如:

  POST http://www.example.com/customers
  POST http://www.example.com/customers/12345/orders

  当创建成功时,返回HTTP状态码201,并顺便一个职务头信息,其中含指向最先创建的资源的链接。

  POST请求既未是安全的同时不是幂等的,因此她给定义为非幂等性资源要。使用简单单相同的POST请求很可能会见导致创建两独带有相同信息之资源。

PUT和POST的始建于

  总之,我们建议利用POST来创造资源。当由客户端来支配新资源有何等URI(通过资源名称或者ID)时,使用PUT:即如果客户端知道URI(或资源ID)是呀,则指向该URI使用PUT请求。否则,当由服务器或劳务端来控制创造的资源的URI时虽以POST请求。换句话说,当客户端在开立之前未亮(或无法掌握)结果的URI时,使用POST请求来创造新的资源。

PUT和POST的创办于

  总之,我们建议下POST来创造资源。当由客户端来决定新资源有着什么样URI(通过资源名称或者ID)时,使用PUT:即如客户端知道URI(或资源ID)是什么,则针对该URI使用PUT请求。否则,当由服务器或劳动端来支配创造的资源的URI时则利用POST请求。换句话说,当客户端在开立之前不明白(或无法知晓)结果的URI时,使用POST请求来创造新的资源。

DELETE

  DELETE很轻了解。它被用来冲URI标识删除资源。

  例如:

  DELETE http://www.example.com/customers/12345
  DELETE http://www.example.com/customers/12345/orders
  DELETE http://www.example.com/buckets/sample

  当去成功时,返回HTTP状态码200(表示是),同时会顺便一个应体body,body中或者带有了去除项之数码(这会占用部分网络带来富),或者封装的应(参见下的返回值)。也得以返回HTTP状态码204(表示无论是内容)表示没有响应体。总之,可以回去状态码204代表没有响应体,或者返回状态码200并且附带JSON风格的响应体。

  根据HTTP规范,DELETE操作是幂等的。如果你对一个资源开展DELETE操作,资源就深受移除了。在资源达成往往调用DELETE最终导致的结果都如出一辙:即资源被移除了。但如若用DELETE的操作用于计数器(资源间),则DETELE将不再是幂等的。如前方所陈述,只要数据没有给更新,统计与测量的用法依然只是让当是幂等的。建议非幂等性的资源要使用POST操作。

  然而,这里有一个有关DELETE幂等性的警告。在一个资源达成第二破调动用DELETE往往会回来404(未找到),因为该资源曾为移除了,所以找不顶了。这使得DELETE操作不再是幂等的。如果资源是于数据库中剔除而未是让略去地记为去,这种情景要适度让步。

  下表总结发生了至关重要HTTP的不二法门以及资源URI,以及推荐的返回值:

HTTP请求

/customers

/customers/{id}

GET

200(正确),用户列表。使用分页、排序和过滤大导航列表。

200(正确),查找单个用户。如果ID没有找到或ID无效则回404(未找到)。

PUT

404(未找到),除非您想当总体集合中更新/替换每个资源。

200(正确)或204(无内容)。如果没找到ID或ID无效则回404(未找到)。

POST

201(创建),带有链接到/customers/{id}的职位头信息,包含新的ID。

404(未找到)

DELETE

404(未找到),除非你想去所有集合——通常不让允许。

200(正确)。如果没找到ID或ID无效则回404(未找到)。

 

DELETE

  DELETE很轻了解。它被用来冲URI标识删除资源。

  例如:

  DELETE http://www.example.com/customers/12345
  DELETE http://www.example.com/customers/12345/orders
  DELETE http://www.example.com/buckets/sample

  当去成功时,返回HTTP状态码200(表示对),同时会顺便一个应体body,body中或者带有了去除项之数码(这会占用部分网络带来富),或者封装的应(参见下的返回值)。也得以回来HTTP状态码204(表示无论是内容)表示没有响应体。总之,可以回状态码204意味着没有响应体,或者返回状态码200并且附带JSON风格的响应体。

  根据HTTP规范,DELETE操作是幂等的。如果您对一个资源开展DELETE操作,资源就给移除了。在资源上数调用DELETE最终致的结果都平等:即资源被移除了。但如若用DELETE的操作用于计数器(资源间),则DETELE将不再是幂等的。如前方所陈述,只要数据没有给更新,统计与测量的用法依然只是被认为是幂等的。建议非幂等性的资源要使用POST操作。

  然而,这里有一个关于DELETE幂等性的警告。在一个资源达成第二赖调动用DELETE往往会回去404(未找到),因为该资源都于移除了,所以寻找不顶了。这使DELETE操作不再是幂等的。如果资源是打数据库中去除而休是深受简单地记为除去,这种情景要适度让步。

  下表总结发生了严重性HTTP的主意以及资源URI,以及推荐的返回值:

HTTP请求

/customers

/customers/{id}

GET

200(正确),用户列表。使用分页、排序和过滤大导航列表。

200(正确),查找单个用户。如果ID没有找到或ID无效则回404(未找到)。

PUT

404(未找到),除非您想以任何集合中创新/替换每个资源。

200(正确)或204(无内容)。如果没找到ID或ID无效则回404(未找到)。

POST

201(创建),带有链接到/customers/{id}的位置头信息,包含新的ID。

404(未找到)

DELETE

404(未找到),除非你想去所有集合——通常不给允许。

200(正确)。如果无找到ID或ID无效则归404(未找到)。

 

资源命名

  除了当地采取HTTP动词,在开创一个足以知道的、易于使的Web服务API时,资源命名可以说凡是极端具有争议和最好要之概念。一个好的资源命名,它所对应之API看起重直观并且爱使。相反,如果命名不好,同样的API会于人感觉到十分傻而难以掌握以及使用。当您要吗卿的新API创建资源URL时,这里发生部分有些技巧值得借鉴。

  从精神上道,一个RESTFul
API最终还足以给简单地作是同等积聚URI的集合,HTTP调用这些URI以及一些为此JSON和(或)XML表示的资源,它们遭起成百上千带有了互动关系的链接。RESTful的可是寻址能力要借助URI。每个资源且发生好的地点或URI——服务器会提供的诸一个立竿见影之信息都得看作资源来明。统一接口的原则有地经URI和HTTP动词的结缘来化解,并符合利用专业与预约。

  于决定你系统受一旦采用的资源时,使用名词来命名这些资源,而未是故动词或动作来命名。换句话说,一个RESTful
URI应该提到到一个切实的资源,而无是关系到一个动作。另外,名词还装有部分动词没有的性质,这为是外一个家喻户晓的元素。

  一些资源的例子:

  • 系的用户
  • 学员登记的课
  • 一个用户帖子的年华轴
  • 体贴入微其他用户的用户
  • 同样篇关于骑马的篇章

  服务套件中的每个资源最少有一个URI来标识。如果此URI能表示必定之含义并且能尽描述她所代表的资源,那么其就是一个极度好之命名。URI应该负有可预测性和分结构,这将推向加强其的可理解性和可用性的:可预测指的凡资源应该同称号保持一致;而分指的是数颇具涉达到的结构。这并非REST规则或标准,但是其加重了针对性API的概念。

  RESTful
API是供被消费端的。URI的名目与布局应当用她所发表的意思传达给买主。通常我们蛮为难了解数码的分界是啊,但是于您的数码及而该非常有或夺品味找到要回来给客户端的多寡是什么。API是吧客户端而规划的,而未是为公的数目。

  假设我们本一旦描述一个包客户、订单,列表项,产品等作用的订单系统。考虑一下我们该如何来讲述在此服务被所涉嫌到之资源的URIs:

资源命名

  除了当地动HTTP动词,在开创一个得领略的、易于使的Web服务API时,资源命名可以说凡是极致具争议与极致要的定义。一个好之资源命名,它所对应的API看起更直观并且爱使。相反,如果命名不好,同样的API会给人倍感特别傻而难以理解和采取。当您需要呢您的新API创建资源URL时,这里有一部分有点技巧值得借鉴。

  从精神上言语,一个RESTFul
API最终都可为简单地作为是千篇一律积URI的集纳,HTTP调用这些URI以及部分就此JSON和(或)XML表示的资源,它们吃出许多含了交互关联的链接。RESTful的不过寻址能力主要因URI。每个资源还生自己的地址或URI——服务器会提供的各级一个立竿见影的音信都得以用作资源来明。统一接口的准有地由此URI和HTTP动词的做来缓解,并可利用专业及约定。

  于决定你系统遭到设采取的资源时,使用名词来定名这些资源,而无是用动词或动作来定名。换句话说,一个RESTful
URI应该提到到一个切实可行的资源,而非是关乎到一个动作。另外,名词还拥有局部动词没有底性能,这为是任何一个显而易见的因素。

  一些资源的例子:

  • 网的用户
  • 学生注册之学科
  • 一个用户帖子的时日轴
  • 关注其他用户的用户
  • 同篇有关骑马的文章

  服务套件中之每个资源最少发生一个URI来标识。如果是URI能表示肯定的意义并且会尽描述其所表示的资源,那么它们就是一个极好的命名。URI应该具备可预测性和支行结构,这将力促增强它们的可理解性和可用性的:可预测指的是资源应该与称保持一致;而分指的凡多少有涉达到之构造。这并非REST规则或规范,但是其加重了对API的定义。

  RESTful
API是提供被消费端的。URI的称呼与组织应该拿其所发挥的含义传达给买主。通常我们大为难理解数据的界限是什么,但是自您的数额及而应当格外有或去品味找到要赶回给客户端的数据是呀。API是吗客户端而规划之,而无是啊而的数码。

  假设我们本设讲述一个包括客户、订单,列表项,产品相当功效的订单系统。考虑一下我们该怎么来讲述在这服务遭遇所关联到的资源的URIs:

资源URI示例

  为了以网中插入(创建)一个新的用户,我们得行使:

  POST http://www.example.com/customers

 

  读取编号吧33245之用户信息:

  GET http://www.example.com/customers/33245

  使用PUT和DELETE来请求相同之URI,可以创新和去数据。

 

  下面是针对产品有关的URI的有建议:

  POST http://www.example.com/products

  用于创造新的成品。

 

  GET|PUT|DELETE http://www.example.com/products/66432

  分别用于读取、更新、删除编号吧66432的产品。

 

  那么,如何也用户创建一个初的订单也?

  一栽方案是:

  POST http://www.example.com/orders

  这种办法得以据此来创造订单,但少相应的用户数据。

  

  以咱们纪念吧用户创建一个订单(注意之间的关联),这个URI可能未足够直观,下面这个URI则重复清楚一些:

  POST http://www.example.com/customers/33245/orders

  现在我们掌握它是也编号33245之用户创建一个订单。

 

  那下面这要返回的凡呀也?

  GET http://www.example.com/customers/33245/orders

  可能是一个号也33245底用户所创办或者具备的订单列表。注意:我们可屏蔽对该URI进行DELETE或PUT请求,因为她的操作对象是一个会合。

 

  继续深入,那下面是URI的乞求又代表什么吗?

  POST http://www.example.com/customers/33245/orders/8769/lineitems

  可能是(为编号33245之用户)增加一个号也8769的订单条目。没错!如果下GET方式呼吁是URI,则会返回这个订单的保有条条框框。但是,如果这些章与用户信息无关,我们拿会供POST
www.example.com/orders/8769/lineitems
这个URI。

  从返回的这些章来拘禁,指定的资源或会见有差不多单URIs,所以我们也许吗需而供这样一个URI
GET
http://www.example.com/orders/8769
,用来当无掌握用户ID的状况下基于订单ID来查询订单。

 

  更进一步:

  GET http://www.example.com/customers/33245/orders/8769/lineitems/1

  可能才回去跟个订单中的率先独章。

  现在若当清楚什么是分开层结构了。它们并无是严厉的条条框框,只是为确保在您的服务中这些强制的结构会还易吃用户所掌握。与所有软件开发中之技巧一样,命名是马到成功的要。

  

  多看有的API的示范并学会控制这些技巧,和汝的队友一起来完善而API资源的URIs。这里发出局部APIs的事例:

  • Twitter: https://dev.twitter.com/docs/api
  • Facebook: http://developers.facebook.com/docs/reference/api/
  • LinkedIn: https://developer.linkedin.com/apis

资源URI示例

  为了当系遭到插入(创建)一个新的用户,我们得以应用:

  POST http://www.example.com/customers

 

  读取编号也33245底用户信息:

  GET http://www.example.com/customers/33245

  使用PUT和DELETE来请求相同之URI,可以创新和去数据。

 

  下面是对活有关的URI的一对提议:

  POST http://www.example.com/products

  用于创造新的出品。

 

  GET|PUT|DELETE http://www.example.com/products/66432

  分别用于读取、更新、删除编号也66432底活。

 

  那么,如何为用户创建一个初的订单也?

  一种植方案是:

  POST http://www.example.com/orders

  这种方法可据此来创造订单,但少相应的用户数据。

  

  为咱们纪念呢用户创建一个订单(注意之间的涉),这个URI可能无足够直观,下面是URI则再次清楚一些:

  POST http://www.example.com/customers/33245/orders

  现在咱们理解它是啊编号33245的用户创建一个订单。

 

  那下面是请返回的凡什么呢?

  GET http://www.example.com/customers/33245/orders

  可能是一个号码为33245之用户所创建或者富有的订单列表。注意:我们好屏蔽对拖欠URI进行DELETE或PUT请求,因为她的操作对象是一个聚。

 

  继续深入,那下面这URI的乞求又象征什么吧?

  POST http://www.example.com/customers/33245/orders/8769/lineitems

  可能是(为编号33245的用户)增加一个号码为8769之订单条目。没错!如果采用GET方式要是URI,则会回这个订单的具备条条框框。但是,如果这些章与用户信息无关,我们拿会供POST
www.example.com/orders/8769/lineitems
这个URI。

  从返回的这些章来拘禁,指定的资源或会见发生差不多单URIs,所以我们或也待而供这样一个URI
GET
http://www.example.com/orders/8769
,用来以匪亮堂用户ID的景况下基于订单ID来查询订单。

 

  更进一步:

  GET http://www.example.com/customers/33245/orders/8769/lineitems/1

  可能只是回去跟个订单中的首先独章。

  现在而该理解什么是劈层组织了。它们并无是严格的平整,只是以确保以你的劳动被这些强制的结构会更易受用户所了解。与所有软件开发中之技能一样,命名是成的要紧。

  

  多看有些API的示范并学会控制这些技能,和而的队友一起来完善而API资源的URIs。这里来一对APIs的例证:

  • Twitter: https://dev.twitter.com/docs/api
  • Facebook: http://developers.facebook.com/docs/reference/api/
  • LinkedIn: https://developer.linkedin.com/apis

资源命名的反例

  前面我们就讨论了有当的资源命名的例证,然而有时有反面的事例也很有教育意义。下面是一些请勿极端有RESTful风格的资源URIs,看起较散乱。这些都是不当的事例! 

  首先,一些serivices往往用单一的URI来指定服务接口,然后经查询参数来指定HTTP请求的动作。例如,要创新编号12345底用户信息,带有JSON
body的伸手或是这样:

  GET
http://api.example.com/services?op=update\_customer&id=12345&format=json

  尽管地方URL中之”services”的斯节点是一个名词,但以此URL不是打说的,因为对持有的求而言,该URI的层级结构都是均等的。此外,它使用GET作为HTTP动词来施行一个更新操作,这简直就是相反人类(甚至是危在旦夕的)。

  下面是另外一个创新用户之操作的事例:

  GET http://api.example.com/update\_customer/12345

  以及她的一个变种:

  GET http://api.example.com/customers/12345/update

  你见面常见到于任何开发者的劳务套件中出好多这样的用法。可以见到,这些开发者试图去创造RESTful的资源名称,而且早已有矣部分提高。但是若依然会分辨出URL中之动词短语。注意,在这个URL中我们无需”update”这个词,因为咱们好凭借HTTP动词来形成操作。下面这个URL正好说明了当时一点:

  PUT http://api.example.com/customers/12345/update

  这个请又设有PUT和”update”,这会针对顾客产生迷惑!这里的”update”指的是一个资源为?因此,这里我们费些口舌也是想而能够解……

资源命名的反例

  前面我们已经讨论了有宜的资源命名的事例,然而有时有反面的例子吗蛮有教育意义。下面是有的无极端具有RESTful风格的资源URIs,看起较散乱。这些都是错的例子! 

  首先,一些serivices往往利用单一的URI来指定服务接口,然后通过询问参数来指定HTTP请求的动作。例如,要更新编号12345的用户信息,带有JSON
body的请或是这样:

  GET
http://api.example.com/services?op=update\_customer&id=12345&format=json

  尽管地方URL中之”services”的这节点是一个名词,但以此URL不是自说的,因为对具有的乞求而言,该URI的层级结构都是一律的。此外,它用GET作为HTTP动词来施行一个翻新操作,这简直就是倒人类(甚至是危险的)。

  下面是另外一个更新用户之操作的例子:

  GET http://api.example.com/update\_customer/12345

  以及它们的一个变种:

  GET http://api.example.com/customers/12345/update

  你晤面常常来看于另外开发者的劳动套件中生出很多这么的用法。可以看,这些开发者试图去创造RESTful的资源名称,而且已发出了一些向上。但是若仍然能够分辨出URL中之动词短语。注意,在这URL中我们无需”update”这个词,因为咱们可借助HTTP动词来完成操作。下面这URL正好说明了这一点:

  PUT http://api.example.com/customers/12345/update

  这个请又存在PUT和”update”,这会对客有迷惑!这里的”update”指的是一个资源为?因此,这里我们费些口舌也是冀你能够理解……

复数

  让咱们来讨论一下复数和“单数”的争论…还没听说过?但这种争议确实在,事实上它可以概括为这题目……

  在你的层级结构中URI节点是否用吃取名吧单数或复数形式呢?举个例子,你用来索用户资源的URI的命名是否要像下这样:

  GET http://www.example.com/customer/33245

  或者:

  GET http://www.example.com/customers/33245

  两栽办法都不曾问题,但日常我们都见面择使用复数命名,以使得你的API
URI在拥有的HTTP方法中保持一致。原因是冲这样平等种植考虑:customers是服务套件中之一个汇聚,而ID33245的这个用户则是这个集中的中间一个。

  按照这规则,一个利用复数形式之差不多节点的URI会是这么(注意粗体部分):

  GET
http://www.example.com/**customers**/33245/**orders**/8769/**lineitems**/1

  “customers”、“orders”以及“lineitems”这些URI节点都施用的是复数形式。

  这象征你的每个根资源只需要简单个为主的URL就可以了,一个用来创造集合内之资源,另一个为此来冲标识符获取、更新和去资源。例如,以customers为例,创建资源可以动用下的URL进行操作:

  POST http://www.example.com/customers

  而读取、更新与去资源,使用下的URL操作:

  GET|PUT|DELETE http://www.example.com/customers/{id}

  正使前方提到的,给得的资源或来多单URI,但当一个极小的整体的增删改查功能,利用有限个大概的URI来拍卖便够了。

  或许你会问:是否在聊情况下复数没有意义?嗯,事实上是这么的。当没凑概念的时节(此时复数没有意义)。换句话说,当资源就出一个之图景下,使用单数资源名称也是足以的——即一个单一的资源。例如,如果生一个纯净的总体部署资源,你得运用一个单数名称来代表:

  GET|PUT|DELETE http://www.example.com/configuration

  注意这里少configuration的ID以及HTTP动词POST的用法。假设每个用户有一个配备来说,那么是URL会是这样:

  GET|PUT|DELETE
http://www.example.com/customers/12345/configuration

  同令人瞩目这里没点名configuration的ID,以及无被定POST动词的用法。在即时简单只例证中,可能也会有人认为利用POST是立竿见影的。好吧…

 

复数

  让咱来讨论一下复数和“单数”的争论…还没听说过?但这种争议确实在,事实上它可概括为之题材……

  以公的层级结构被URI节点是否要为取名为单数或复数形式吗?举个例,你用来找用户资源的URI的命名是否需要像下这样:

  GET http://www.example.com/customer/33245

  或者:

  GET http://www.example.com/customers/33245

  两种办法都无问题,但普通我们还见面选取使用复数命名,以使你的API
URI在备的HTTP方法中保持一致。原因是冲这样同样种植考虑:customers是服务套件中的一个聚众,而ID33245的斯用户则是这个集中之中间一个。

  按照这规则,一个利用复数形式之差不多节点的URI会是如此(注意粗体部分):

  GET
http://www.example.com/**customers**/33245/**orders**/8769/**lineitems**/1

  “customers”、“orders”以及“lineitems”这些URI节点都应用的凡复数形式。

  这象征你的每个根资源就待少单核心的URL就可以了,一个用来创造集合内的资源,另一个就此来因标识符获取、更新与去资源。例如,以customers为条例,创建资源得以采用下的URL进行操作:

  POST http://www.example.com/customers

  而读取、更新和去资源,使用下的URL操作:

  GET|PUT|DELETE http://www.example.com/customers/{id}

  正而前提到的,给得的资源或发生差不多只URI,但当一个极小的完整的增删改查功能,利用有限单简易的URI来处理便够用了。

  或许你会咨询:是否以稍微情况下复数没有意思?嗯,事实上是如此的。当没有汇概念的时光(此时复数没有意义)。换句话说,当资源只出一个的情状下,使用单数资源名称为是可以的——即一个纯净的资源。例如,如果起一个纯的整体部署资源,你得应用一个单数名称来表示:

  GET|PUT|DELETE http://www.example.com/configuration

  注意这里少configuration的ID以及HTTP动词POST的用法。假设每个用户有一个布局来说,那么这URL会是这样:

  GET|PUT|DELETE
http://www.example.com/customers/12345/configuration

  同令人瞩目这里没有点名configuration的ID,以及没有被定POST动词的用法。在这简单独例证中,可能也会有人认为利用POST是实用之。好吧…

 

回去表征

  正而前提到的,RESTful接口支持多资源特点,包括JSON和XML,以及吃打包的JSON和XML。建议JSON作为默认表征,不过服务端应该允许客户端指定其他表征。

  对于客户端请求的风味格式,我们得以于Accept头通过文件扩展名来展开点名,也可由此query-string等其他方法来指定。理想图景下,服务端可以支持具有这些主意。但是,现在专业更赞成被经过类似于文件扩展名的法门来进展点名。因此,建议服务端至少要支持以文件扩展名的法,例如“.json”,“.xml”以及它的包装版本“.wjon”,“.wxml”。

  通过这种艺术,在URI中指定返回表征的格式,可以增强URL的可见性。例如,GET
http://www.example.com/customers.xml
以回customer列表的XML格式的风味。同样,GET
http://www.example.com/customers.json
以返回一个JSON格式的特点。这样,即使是当极度基础之客户端(例如“curl”),服务使起来呢会见越加便利。推荐使用这种办法。

  此外,当url中从来不含格式说明时,服务端应该归默认格式的风味(假设为JSON)。例如:

  GET http://www.example.com/customers/12345

  GET http://www.example.com/customers/12345.json

  以上两者返回的ID为12345底customer数据均为JSON格式,这是劳动端的默认格式。

  GET http://www.example.com/customers/12345.xml

  如果服务端支持的话,以上要返回的ID为12345底customer数据吧XML格式。如果该服务器无支持XML格式的资源,将回到一个HTTP
404的荒唐。

  使用HTTP
Accept头被周边认为是同一种更优雅的法,并且称HTTP的标准及意义,客户端可通过这种方法来告诉HTTP服务端它们可是支撑之数据类型有什么。但是,为了使Accept头,服务端要以支持封装和不封装的应,你得贯彻由定义之类别——因为这些格式不是规范的类型。这大大增加了客户端与服务端的繁杂。请参见RFC
2616底14.1节关于Accept头的详细信息(http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.1)。使用文件扩展名来指定数量格式是最最简便直接的方式,用最为少之字符就可以做到,并且支持脚本操作——无需动HTTP头。

  通常当我们提到REST服务,跟XML是毫不相关的。即使服务端支持XML,也几乎无人建议在REST中以XML。XML的专业和公约在REST中无绝适用。特别是其并命名空间都未曾,就再度无拖欠在RESTful服务体系中采用了。这才见面使业务变得重新复杂。所以回来的XML看起又如JSON,它概括容易读,没有模式以及命名空间的范围,换句话来说是任标准的,易于解析。

回表征

  正使前方提到的,RESTful接口支持多资源特色,包括JSON和XML,以及被卷入的JSON和XML。建议JSON作为默认表征,不过服务端应该允许客户端指定其他表征。

  对于客户端请求的性状格式,我们好当Accept头通过文件扩展名来拓展点名,也可以经过query-string等其它措施来指定。理想状态下,服务端可以支撑具备这些方式。但是,现在正规更倾向于通过类似于文件扩展名的方来开展点名。因此,建议服务端至少得支持采取文件扩展名的计,例如“.json”,“.xml”以及它们的包版本“.wjon”,“.wxml”。

  通过这种方法,在URI中指定返回表征的格式,可以提高URL的可见性。例如,GET
http://www.example.com/customers.xml
拿赶回customer列表的XML格式的特征。同样,GET
http://www.example.com/customers.json
拿回一个JSON格式的风味。这样,即使是在无比基础的客户端(例如“curl”),服务应用起来为会见愈加便捷。推荐用这种艺术。

  此外,当url中没包含格式说明时,服务端应该归默认格式的特征(假设为JSON)。例如:

  GET http://www.example.com/customers/12345

  GET http://www.example.com/customers/12345.json

  以上两者返回的ID为12345的customer数据全为JSON格式,这是劳务端的默认格式。

  GET http://www.example.com/customers/12345.xml

  如果服务端支持的话,以上要返回的ID为12345之customer数据也XML格式。如果该服务器无支持XML格式的资源,将回来一个HTTP
404底荒谬。

  使用HTTP
Accept头被大面积认为是均等种植更优雅的计,并且可HTTP的专业和意义,客户端可经这种措施来喻HTTP服务端它们可支撑之数据类型有哪些。但是,为了利用Accept头,服务端要而支持封装和无封装的应,你必兑现自定义的路——因为这些格式不是正规的档次。这大大加了客户端以及劳务端的错综复杂。请参见RFC
2616之14.1节关于Accept头的详细信息(http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.1)。使用文件扩展名来指定数量格式是极致简便易行直接的方法,用极少的字符就得就,并且支持脚本操作——无需下HTTP头。

  通常当我们涉REST服务,跟XML是毫不相关的。即使服务端支持XML,也几从不丁建议于REST中使XML。XML的专业与公约在REST中未极端适用。特别是它们并命名空间还不曾,就再不该于RESTful服务体系中运用了。这仅仅见面如工作变得又扑朔迷离。所以回来的XML看起重像JSON,它大概好读,没有模式和命名空间的克,换句话来说是管正规的,易于解析。

资源通过链接的只是发现性(HATEOAS续)

  REST指导标准有(根据联合接口规范)是application的状态通过hypertext(超文本)来导。这便是咱普通所说之Hypertext
As The Engine of Application State
(即HATEOAS,用超文本来当应用程序状态机),我们以“REST是什么”平等节省中吗提到了。

  根据Roy
Fielding在外的博客中之叙述(http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertextdriven),REST接口中极度重点的一对是超文本的应用。此外,他还指出,在为有其它相关的消息之前,一个API应该是可用和可理解的。也就是说,一个API应当可以经其链接导航及数的一一部分。不建议单独回纯数据。

  不过当下底业界先驱们并无经常以这种做法,这反映了HATEOAS仅仅在成熟度模型中之使用率还胜。纵观众多底服务体系,它们大多返回重新多之数额,而返的链接却坏少(或者无)。这是反其道而行之Fielding的REST约定的。Fielding说:“信息之每一个可寻址单元都带一个地方……查询结果应该呈现呢一个分包摘要信息之链接清单,而未是目标往往组。”

  另一方面,简单粗暴地将总体链接集合返回会大大影响网络带来富。在实质上情况遇,根据所待的规范还是使情况,API接口的通信量要依据服务器响应中超文本链接所蕴含的“摘要”数量来抵消。

  同时,充分利用HATEOAS可能会见增加实现的纷繁,并对准劳动客户端起显著的承负,这一定给降低了客户端和劳动器端开发人员的生产力。因此,当务之急是只要平衡超链接服务推行以及现有可用资源中的问题。

  超链接太小化的做法是于无比可怜限度地回落客户端和服务器之间的耦合的又,提高劳动端的可用性、可操纵性和可理解性。这些极其小化建议是:通过POST创建资源并起GET请求返回集合,对于生分页的状后我们见面涉嫌。

资源通过链接的但是发现性(HATEOAS续)

  REST指导原则有(根据统一接口规范)是application的状态通过hypertext(超文本)来导。这就是咱普通所说之Hypertext
As The Engine of Application State
(即HATEOAS,用超文本来当应用程序状态机),我们以“REST是什么”无异于节省中吗关乎了。

  根据Roy
Fielding在他的博客中之描述(http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertextdriven),REST接口中极其着重之片是超文本的下。此外,他尚指出,在被有其他有关的音讯前,一个API应该是可用和而分晓的。也就是说,一个API应当可以经该链接导航及数量的逐一部分。不建议才回纯数据。

  不过当下之业界先驱们连没有经常应用这种做法,这体现了HATEOAS仅仅在成熟度模型中之使用率还胜似。纵观众多之服务体系,它们多返回重新多的数目,而回到的链接却分外少(或者没)。这是违Fielding的REST约定的。Fielding说:“信息之诸一个不过寻址单元都携带一个地点……查询结果应该呈现呢一个含摘要信息的链接清单,而无是目标往往组。”

  另一方面,简单粗暴地用所有链接集合返回会大大影响网络带来富。在实际上状况被,根据所用的标准或采用状况,API接口的通信量要因服务器响应中超文本链接所含有的“摘要”数量来抵消。

  同时,充分利用HATEOAS可能会见增多实现之繁杂,并针对性劳务客户端起强烈的负担,这一定给降低了客户端与劳务器端开发人员的生产力。因此,当务之急是如平衡超链接服务实施及水土保持可用资源之间的题材。

  超链接太小化的做法是以太酷限度地抽客户端和服务器之间的耦合的而,提高服务端的可用性、可操纵性和可理解性。这些最小化建议是:通过POST创建资源并由GET请求返回集合,对于发出分页的动静后我们会涉嫌。

极端小化链接推荐

  以create的用例中,新建资源的URI(链接)应该以Location响应头中回到,且应中心是拖欠的——或者光含新建资源的ID。

  对于自服务端返回的特点集合,每个表征应该在她的链接集合中带一个无比小之“自身”链接属性。为了好分页操作,其它的链接可以置身一个单独的链接集合中归,必要经常好蕴涵“第一页”、“上等同页”、“下同样页”、“最后一页”等信息。

  参照下文链接格式有的例子获取更多信息。

极致小化链接推荐

  以create的用例中,新建资源的URI(链接)应该在Location响应头中回到,且应中心是空的——或者仅含新建资源的ID。

  对于自服务端返回的特色集合,每个表征应该当其的链接集合中携带一个无比小的“自身”链接属性。为了方便分页操作,其它的链接可以置身一个单独的链接集合中归,必要经常好蕴涵“第一页”、“上同一页”、“下一致页”、“最后一页”等信息。

  参照下文链接格式一部分的事例获取更多信息。

链接格式

  参照整个链接格式的正经,建议遵守一些近似Atom、AtomPub或Xlink的品格。JSON-LD也对,但并不曾为广大运用(如果都为用了)。目前正式最广大的章程是采取带有”rel”元素以及带有资源总体URI的”href”元素的Atom链接格式,不包含其他身份验证或询问字符串参数。”rel”元素得以蕴涵标准值”alternate”、”related”、”self”、”enclosure”和”via”,还有分页链接的“第一页”、“上同页”、“下一致页”,“最后一页”。在急需时得由定义并累加应用她。

  一些XML
Atom格式的概念对用JSON格式表示的链接来说是没用的。例如,METHOD属性对于一个RESTful资源来说是免需之,因为于一个加以的资源,在有支持的HTTP方法(CRUD行为)中,资源的URI都是一样的——所以单独列有这些是从未有过必要之。

  让咱们选一些具体的例子来更说明这或多或少。下面是调用创建新资源的呼吁后底应:

  POST http://api.example.com/users

  下面是作应头集合中蕴含创建新资源的URI的Location部分:

HTTP/1.1 201 CREATED 
Status: 201 
Connection: close 
Content-Type: application/json; charset=utf-8 
Location: http://api.example.com/users/12346

  返回的body可以为空,或者隐含一个让包裹的应(见下文封装响应)。

  下面的事例通过GET请求获取一个请勿包含分页的表征集合的JSON响应:

{
  "data": [
    {
      "user_id": "42",
      "name": "Bob",
      "links": [
        {
          "rel": "self",
          "href": "http://api.example.com/users/42"
        }
      ]
    },
    {
      "user_id": "22",
      "name": "Frank",
      "links": [
        {
          "rel": "self",
          "href": "http://api.example.com/users/22"
        }
      ]
    },
    {
      "user_id": "125",
      "name": "Sally",
      "links": [
        {
          "rel": "self",
          "href": "http://api.example.com/users/125"
        }
      ]
    }
  ]
}

  注意,links数组中之各级一样件都蕴涵一个对准“自身(self)”的链接。该数组还可能还蕴含其他关系,如children、parent等。

  最后一个例证是经GET请求获取一个暗含分页的特色集合的JSON响应(每页显示3桩),我们于闹第三页的数量:

{
  "data": [
    {
      "user_id": "42",
      "name": "Bob",
      "links": [
        {
          "rel": "self",
          "href": "http://api.example.com/users/42"
        }
      ]
    },
    {
      "user_id": "22",
      "name": "Frank",
      "links": [
        {
          "rel": "self",
          "href": "http://api.example.com/users/22"
        }
      ]
    },
    {
      "user_id": "125",
      "name": "Sally",
      "links": [
        {
          "rel": "self",
          "href": "http://api.example.com/users/125"
        }
      ]
    }
  ],
  "links": [
    {
      "rel": "first",
      "href": "http://api.example.com/users?offset=0&limit=3"
    },
    {
      "rel": "last",
      "href": "http://api.example.com/users?offset=55&limit=3"
    },
    {
      "rel": "previous",
      "href": "http://api.example.com/users?offset=3&limit=3"
    },
    {
      "rel": "next",
      "href": "http://api.example.com/users?offset=9&limit=3"
    }
  ]
}

  在斯例子中,响应中用于分页的links集合中之每一样宗都带有一个对“自身(self)”的链接。这里或许还见面发有关联到集结的外链接,但还跟分页本身无关。简而言之,这里来个别单地方含有links。一个哪怕是data对象吃所富含的聚集(这个啊是接口要回给客户端的多少表征集合),其中的各级一样项至少要包括一个针对“自身(self)”的links集合;另一个则是一个独的对象links,其中囊括和分页相关的链接,该有的的情适用于整个集合。

  对于经过POST请求创建资源的情况,需要以应头着隐含一个涉嫌新建对象链接的Location

链接格式

  参照整个链接格式的正儿八经,建议遵守一些好像Atom、AtomPub或Xlink的品格。JSON-LD也无可非议,但并从未被大面积使用(如果已被用了)。目前标准最广的点子是下带有”rel”元素与富含资源总体URI的”href”元素的Atom链接格式,不带有其他身份验证或询问字符串参数。”rel”元素得以蕴涵标准值”alternate”、”related”、”self”、”enclosure”和”via”,还有分页链接的“第一页”、“上等同页”、“下一致页”,“最后一页”。在用时可起定义并累加应用她。

  一些XML
Atom格式的定义对用JSON格式表示的链接来说是杯水车薪的。例如,METHOD属性对于一个RESTful资源来说是勿欲的,因为于一个加的资源,在备支持的HTTP方法(CRUD行为)中,资源的URI都是平之——所以单独列有这些是无必要之。

  让咱们选一些实际的事例来尤其证实这或多或少。下面是调用创建新资源的请后的响应:

  POST http://api.example.com/users

  下面是作应头集合中带有创建新资源的URI的Location部分:

HTTP/1.1 201 CREATED 
Status: 201 
Connection: close 
Content-Type: application/json; charset=utf-8 
Location: http://api.example.com/users/12346

  返回的body可以呢空,或者隐含一个让打包的应(见下文封装响应)。

  下面的例证通过GET请求获取一个未带有分页的特性集合的JSON响应:

{
  "data": [
    {
      "user_id": "42",
      "name": "Bob",
      "links": [
        {
          "rel": "self",
          "href": "http://api.example.com/users/42"
        }
      ]
    },
    {
      "user_id": "22",
      "name": "Frank",
      "links": [
        {
          "rel": "self",
          "href": "http://api.example.com/users/22"
        }
      ]
    },
    {
      "user_id": "125",
      "name": "Sally",
      "links": [
        {
          "rel": "self",
          "href": "http://api.example.com/users/125"
        }
      ]
    }
  ]
}

  注意,links数组中的诸一样起都含一个对准“自身(self)”的链接。该数组还可能还蕴含其他关系,如children、parent等。

  最后一个例证是由此GET请求获取一个饱含分页的特点集合的JSON响应(每页显示3件),我们吃有第三页的数额:

{
  "data": [
    {
      "user_id": "42",
      "name": "Bob",
      "links": [
        {
          "rel": "self",
          "href": "http://api.example.com/users/42"
        }
      ]
    },
    {
      "user_id": "22",
      "name": "Frank",
      "links": [
        {
          "rel": "self",
          "href": "http://api.example.com/users/22"
        }
      ]
    },
    {
      "user_id": "125",
      "name": "Sally",
      "links": [
        {
          "rel": "self",
          "href": "http://api.example.com/users/125"
        }
      ]
    }
  ],
  "links": [
    {
      "rel": "first",
      "href": "http://api.example.com/users?offset=0&limit=3"
    },
    {
      "rel": "last",
      "href": "http://api.example.com/users?offset=55&limit=3"
    },
    {
      "rel": "previous",
      "href": "http://api.example.com/users?offset=3&limit=3"
    },
    {
      "rel": "next",
      "href": "http://api.example.com/users?offset=9&limit=3"
    }
  ]
}

  以这个例子中,响应中用于分页的links集合中之各级一样件都饱含一个针对性“自身(self)”的链接。这里恐怕还见面起一部分涉及到集结的其余链接,但犹跟分页本身无关。简而言之,这里发生一定量只地方含有links。一个就算是data对象吃所蕴涵的聚集(这个为是接口要回到给客户端的数目表征集合),其中的各一样起至少要连一个对准“自身(self)”的links集合;另一个虽然是一个独门的对象links,其中包括同分页相关的链接,该有的情适用于全体集合。

  对于经过POST请求创建资源的气象,需要以应头着寓一个干新建对象链接的Location

打包响应

   服务器可以以应中并且返回HTTP状态码和body。有成千上万JavaScript框架没有管HTTP状态响应码返回给最终之开发者,这频繁会招致客户端无法根据状态码来确定具体的所作所为。此外,虽然HTTP规范着生出深多种响应码,但是反复就生个别客户端会关注这些——通常大家只是以乎”success”、”error”或”failture”。因此,将应内容与响应状态码封装于含响应信息的特点着,是生必不可少之。

  OmniTI
实验室有这么一个提议,它吃叫作JSEND响应。更多信息请参见http://labs.omniti.com/labs/jsend。另外一个提案是由Douglas
Crockford提出的,可以查看此http://www.json.org/JSONRequest.html。

  这些提案在实践中并从未完全含所有的情状。基本上,现在不过好的做法是按以下属性封装常规(非JSONP)响应:

  • code——包含一个平头列的HTTP响应状态码。
  • status——包含文本:”success”,”fail”或”error”。HTTP状态响应码在500-599里也”fail”,在400-499次吧”error”,其它都为”success”(例如:响应状态码为1XX、2XX同3XX)。
  • message——当状态值为”fail”和”error”时有效,用于展示错误信息。参照国际化(il8n)标准,它可蕴涵信息号或者编码,可以但含其中一个,或者以含有并就此分隔符隔开。
  • data——包含响应的body。当状态值为”fail”或”error”时,data就含错误原因还是特别名称。

  下面是一个归success的包响应:

{
  "code": 200,
  "status": "success",
  "data": {
    "lacksTOS": false,
    "invalidCredentials": false,
    "authToken": "4ee683baa2a3332c3c86026d"
  }
}

  返回error的包装响应:

{
  "code": 401,
  "status": "error",
  "message": "token is invalid",
  "data": "UnauthorizedException"
}

  这半单包装响应对应的XML如下:

<response>
    <code>200</code>
    <status>success</status>
    <data class="AuthenticationResult">
        <lacksTOS>false</lacksTOS>
        <invalidCredentials>false</invalidCredentials>
        <authToken>1.0|idm|idm|4ee683baa2a3332c3c86026d</authToken>
    </data>
</response>

  和:

<response>
    <code>401</code>
    <status>error</status>
    <message>token is invalid</message>
    <data class="string">UnauthorizedException</data>
</response>

打包响应

   服务器可以以应中并且返回HTTP状态码和body。有诸多JavaScript框架没有管HTTP状态响应码返回给最终之开发者,这频繁会促成客户端无法根据状态码来确定具体的行为。此外,虽然HTTP规范着生出深多种响应码,但是反复就出个别客户端会关注这些——通常大家只是以乎”success”、”error”或”failture”。因此,将应内容及响应状态码封装于含响应信息的特色着,是生必不可少之。

  OmniTI
实验室有诸如此类一个提议,它吃称呼JSEND响应。更多信息请参见http://labs.omniti.com/labs/jsend。另外一个提案是由Douglas
Crockford提出的,可以查看此http://www.json.org/JSONRequest.html。

  这些提案在实践中并无完全含所有的景。基本上,现在最好好的做法是据以下属性封装常规(非JSONP)响应:

  • code——包含一个平头种的HTTP响应状态码。
  • status——包含文本:”success”,”fail”或”error”。HTTP状态响应码在500-599以内也”fail”,在400-499之内吧”error”,其它都为”success”(例如:响应状态码为1XX、2XX跟3XX)。
  • message——当状态值为”fail”和”error”时有效,用于展示错误信息。参照国际化(il8n)标准,它可以蕴涵信息号或者编码,可以但含其中一个,或者以含有并据此分隔符隔开。
  • data——包含响应的body。当状态值为”fail”或”error”时,data就包含错误原因还是生名称。

  下面是一个归success的包裹响应:

{
  "code": 200,
  "status": "success",
  "data": {
    "lacksTOS": false,
    "invalidCredentials": false,
    "authToken": "4ee683baa2a3332c3c86026d"
  }
}

  返回error的包装响应:

{
  "code": 401,
  "status": "error",
  "message": "token is invalid",
  "data": "UnauthorizedException"
}

  这简单单包装响应对应之XML如下:

<response>
    <code>200</code>
    <status>success</status>
    <data class="AuthenticationResult">
        <lacksTOS>false</lacksTOS>
        <invalidCredentials>false</invalidCredentials>
        <authToken>1.0|idm|idm|4ee683baa2a3332c3c86026d</authToken>
    </data>
</response>

  和:

<response>
    <code>401</code>
    <status>error</status>
    <message>token is invalid</message>
    <data class="string">UnauthorizedException</data>
</response>

拍卖跨域问题

   我们还听说了有关浏览器的同源策略要同源性需求。它依靠的是浏览器只能请时着显示的站点的资源。例如,如果手上正显示的站点是www.Example1.com,则该站点不能够针对www.Example.com倡导呼吁。显然这会影响站点访问服务器的计。

  时发出一定量只受大面积接受的支持跨域请求的法门:JSONP和跨域资源共享(CORS)。JSONP或“填充的JSON”是同一栽采取模式,它提供了一个方要来自不同域中的服务器的数。其工作方法是自服务器返回任意的JavaScript代码,而休是JSON。客户端的应由JavaScript解析器进行辨析,而非是一直解析JSON数据。另外,CORS是均等种植web浏览器的技艺专业,它也web服务器定义了同样栽艺术,从而允许服务器的资源可以吃无同域的网页访问。CORS被看作是JSONP的风行替代品,并且可被有现代浏览器支持。因此,不建议采用JSONP。任何情形下,推荐选择CORS。

处理跨域问题

   我们且听说了有关浏览器的同源策略要同源性需求。它凭借的是浏览器只能请时正在显示的站点的资源。例如,如果手上方显示的站点是www.Example1.com,则该站点不可知对www.Example.com提倡呼吁。显然这会影响站点访问服务器的方法。

  时发出有限个被广泛接受的支持跨域请求的计:JSONP和跨域资源共享(CORS)。JSONP或“填充的JSON”是千篇一律种下模式,它提供了一个术要来自不同域中之服务器的数码。其工作章程是打服务器返回任意的JavaScript代码,而休是JSON。客户端的应由JavaScript解析器进行解析,而非是直接解析JSON数据。另外,CORS是同等栽web浏览器的技艺专业,它也web服务器定义了一样种办法,从而允许服务器的资源可以于无同域的网页访问。CORS被看作是JSONP的行替代品,并且可让有着现代浏览器支持。因此,不建议以JSONP。任何情况下,推荐选择CORS。

支持CORS

  以服务端实现CORS很简单,只需要在殡葬响应时顺手HTTP头,例如: 

Access-Control-Allow-Origin: *

  只有当数是公家使用的气象下才会拿造访来源设置也”*”。大多数情况下,Access-Control-Allow-Origin头应该指定哪些域好倡导一个CORS请求。只有用跨域访问的URL才装CORS头。

Access-Control-Allow-Origin: http://example.com:8080
http://foo.example.com

  以上Access-Control-Allow-Origin头中,被设置为就同意让信赖的地方可以拜。

Access-Control-Allow-Credentials: true

  只当需要时才祭方面是header,因为如果用户就报到的话,它会以发送cookies/sessions。

  这些headers可以透过web服务器、代理来拓展布局,或者打服务器本身发送。不引进以服务端实现,因为生不利索。或者,可以采取方面的第二种植方法,在web服务器上部署一个用空格分隔的地面的列表。更多关于CORS的情节可参考这里:http://enable-cors.org/。

支持CORS

  于服务端实现CORS很简短,只需要在殡葬响应时顺手HTTP头,例如: 

Access-Control-Allow-Origin: *

  只有以数据是集体使用的情事下才见面拿造访来源设置也”*”。大多数景下,Access-Control-Allow-Origin头应该指定哪些域好倡导一个CORS请求。只有用跨域访问的URL才装CORS头。

Access-Control-Allow-Origin: http://example.com:8080
http://foo.example.com

  以上Access-Control-Allow-Origin头中,被设置为单纯同意受信赖的地方可以拜。

Access-Control-Allow-Credentials: true

  只当需要经常才使方面这header,因为一旦用户既报到的话,它见面同时发送cookies/sessions。

  这些headers可以透过web服务器、代理来拓展安排,或者从服务器本身发送。不引进以服务端实现,因为生不灵便。或者,可以采用方面的第二种办法,在web服务器上布置一个用空格分隔的地面的列表。更多关于CORS的情节可以参见这里:http://enable-cors.org/。

支持JSONP

  JSONP通过运用GET请求避开浏览器的克,从而实现对所有服务之调用。其行事规律是央求方在伸手的URL上上加一个字符串查询参数(例如:jsonp=”jsonp_callback”),其中“jsonp”参数的价是JavaScript函数称呼,该函数在起响应返回时用会见于调用。

  由于GET请求中绝非含呼吁求体,JSONP在采用时有着严重的局限性,因此数据必须通过字符串查询参数来传递。同样的,为了支持PUT,POST和DELETE方法,HTTP方法要为通过字符串查询参数来传递,类似_method=POST这种形式。像这样的HTTP方法传送方式是休引进用的,这会受服务处于安全风险中。

  JSONP通常以有未支持CORS的老旧浏览器中采取,如果要是改成为支持CORS的,会潜移默化总体服务器的架。或者我们啊可透过代理来促成JSONP。总之,JSONP正在被CORS所取代,我们应尽量地采用CORS。

  为了当服务端支持JSONP,在JSONP字符串查询参数传递时,响应必须要实行以下这些操作:

  1. 响应体必须封装成一个参数传递给jsonp中指定的JavaScript函数(例如:jsonp_callback(“<JSON
    response body>”))。
  2. 镇返回HTTP状态码200(OK),并且用真正的状态作为JSON响应中之一律有些归。

  另外,响应体中时常要包含响应头。这让JSONP回调方法需要基于响应体来确定响应处理方式,因为它自身无法获知真实的响应头和状态值。

  下面的例证是比照上述办法封装的一个回error状态的jsonp(注意:HTTP的应状态是200):

jsonp_callback("{'code':'404', 'status':'error','headers':[],'message':'resource XYZ not
found','data':'NotFoundException'}")

  成功创建后的响应类似于这样(HTTP的应状态仍是200):

jsonp_callback("{'code':'201', 'status':'error','headers':
[{'Location':'http://www.example.com/customers/12345'}],'data':'12345'}")

 

支持JSONP

  JSONP通过动用GET请求避开浏览器的限制,从而实现对拥有服务的调用。其工作原理是求求方在呼吁的URL上上加一个字符串查询参数(例如:jsonp=”jsonp_callback”),其中“jsonp”参数的值是JavaScript函数誉为,该函数在生应返回时以见面吃调用。

  由于GET请求被从来不包含呼吁求体,JSONP在运用时有着严重的局限性,因此数据要透过字符串查询参数来传递。同样的,为了支持PUT,POST和DELETE方法,HTTP方法必须也由此字符串查询参数来传递,类似_method=POST这种样式。像这么的HTTP方法传送方式是不推荐应用的,这会给服务处于安全风险之中。

  JSONP通常在有的未支持CORS的老旧浏览器被使,如果如转化支持CORS的,会影响整服务器的架构。或者我们啊可以经代办来落实JSONP。总之,JSONP正在给CORS所替代,我们该尽可能地行使CORS。

  为了以服务端支持JSONP,在JSONP字符串查询参数传递时,响应必须使实行以下这些操作:

  1. 响应体必须封装成一个参数传递给jsonp中指定的JavaScript函数(例如:jsonp_callback(“<JSON
    response body>”))。
  2. 尽返回HTTP状态码200(OK),并且将忠实的状态作为JSON响应中的相同部分归。

  另外,响应体中时时要含有响应头。这让JSONP回调方法要根据响应体来规定响应处理方式,因为它们本身无法获悉真实的响应头和状态值。

  下面的事例是据上述方法封装的一个回error状态的jsonp(注意:HTTP的响应状态是200):

jsonp_callback("{'code':'404', 'status':'error','headers':[],'message':'resource XYZ not
found','data':'NotFoundException'}")

  成功创建后底应类似于如此(HTTP的应状态仍是200):

jsonp_callback("{'code':'201', 'status':'error','headers':
[{'Location':'http://www.example.com/customers/12345'}],'data':'12345'}")

 

查询,过滤与分页

  对于大数据集,从带宽的角度来拘禁,限制返回的数据量是那个重大的。而由UI处理的角度来拘禁,限制数据量也同至关重要,因为UI通常只能展现大数额集中之等同稍微片段数据。在数据集的增长速度不确定的事态下,限制默认返回的数据量是深有必不可少的。以Twitter为条例,要博取有用户的推文(通过个人主页的日轴),如果无特意指定,请求默认只会回20漫长记下,尽管系统最多足返回200修记下。

  除了限制返回的数据量,我们还索要考虑如何对天意据集进行“分页”或下拉滚动操作。创建数量的“页码”,返回大数据列表的曾解片段,然后标出数据的“前无异页”和“后一样页”——这同样作为为号称分页。此外,我们可能为欲指定响应中将包含如何字段或性能,从而限制返回值的数额,并且我们要最后能透过特定值来展开查询操作,并针对性回到值进行排序。

  有少种植重点的点子来又限定查询结果和履行分页操作。首先,我们得以成立一个目方案,它可为页码为导向(请求被而受起各一样页的记录数及页码),或者为记录也导向(请求被直接吃出第一漫漫记下和结尾一修记下)来确定返回值的开始位置。举个例子,这简单种植方式分别表示:“给出第五页(假设每页有20长记下)的笔录”,或“给有第100及第120漫漫的笔录”。

  服务端将根据运作机制来展开切分。有些UI工具,比如Dojo
JSON会选择模仿HTTP规范使用字节范围。如果服务端支持out of
box(即开箱即用效应),则前端UI工具和后端服务中无需任何移,这样使起来会死便宜。

  下文将介绍一种植方法,既能支持Dojo这样的分页模式(在恳求求头中让闹记录之限),也能够支持以字符串查询参数。这样一来服务端将转移得越来越灵活,既可采取类Dojo一样先进的UI工具集,也得以应用简便直接的链接和标签,而不论是需重新为者多复杂的开销工作。但万一服务不直支持UI功能,可以设想不要以恳求求头中叫起记录范围。

  要专门指出的凡,我们连无引进以有着服务被利用查询、过滤跟分页操作。并无是兼备资源还默认支持这些操作,只有少数特定的资源才支撑。服务与资源的文档应当说明如何接口支持这些扑朔迷离的功能。

询问,过滤与分页

  对于大数据集,从带宽的角度来拘禁,限制返回的数据量是很重大的。而由UI处理的角度来拘禁,限制数据量也同等关键,因为UI通常只能展现大数额汇总之均等有点有数据。在数据集的增长速度不确定的情事下,限制默认返回的数据量是大有必要的。以Twitter为例,要取有用户的推文(通过个人主页的流年轴),如果没特意指定,请求默认只会返回20长条记下,尽管系统最多足回去200漫长记下。

  除了限制返回的数据量,我们尚用考虑如何对命运据集进行“分页”或下拉滚动操作。创建数量的“页码”,返回大数据列表的曾清楚片段,然后标出数据的“前一样页”和“后一致页”——这同一行给号称分页。此外,我们可能吗需指定响应中将包含哪些字段或性质,从而限制返回值的数,并且我们盼望最后会由此特定值来进展询问操作,并针对回值进行排序。

  有点儿栽主要的方法来而限制查询结果与履分页操作。首先,我们得建立一个目录方案,它好因页码为导向(请求中设让闹各个一样页的记录数及页码),或者以记录也导向(请求中直接吃起第一长条记下以及末段一长记下)来规定返回值的原初位置。举个例子,这点儿栽艺术分别代表:“给起第五页(假设每页有20久记下)的笔录”,或“给来第100到第120长长的之笔录”。

  服务端将因运作机制来拓展切分。有些UI工具,比如Dojo
JSON会选择模仿HTTP规范行使字节范围。如果服务端支持out of
box(即开箱即用力量),则前端UI工具及后端服务期间无需外移,这样以起来会老便利。

  下文将介绍一栽艺术,既能够支持Dojo这样的分页模式(在恳求求头中于闹记录的限定),也会支撑下字符串查询参数。这样一来服务端将转移得进一步灵敏,既好下类似Dojo一样先进的UI工具集,也可以使用简易直接的链接和标签,而无需再次为之多复杂的支付工作。但若是服务不直接支持UI功能,可以考虑不要当呼吁求头中吃闹记录范围。

  要特别指出的是,我们并无推荐在备服务中采用查询、过滤与分页操作。并无是兼具资源还默认支持这些操作,只有某些特定的资源才支撑。服务以及资源的文档应当说明什么接口支持这些扑朔迷离的法力。

结果限制

  “给出第3到第55长之笔录”,这种求数据的办法以及HTTP的字节范围规范更平等,因此我们可就此它们来标识Range
header。而“从第2长条记下开始,给出最多20长记下”这种方法又易阅读和喻,因此我们通常会就此字符串查询参数的方式来代表。

  综上所述,推荐既支持用HTTP Range
header,也支持以字符串查询参数——offset(偏移量)和limit(限制),然后在服务端对响应结果开展限定。注意,如果以支持即简单种植方式,那么字符串查询参数的先行级要超越Range
header。

  这里您或许会见来个谜:“这简单种植方法效果相似,但是返的数目不完全一致。这会无会见为人口歪曲呢?”恩…就是片只问题。首先要回答的是,这真的会被丁歪曲。关键是,字符串查询参数看起越清晰易懂,在构建与剖析时更是有利。而Range
header则再度多是由机械来使(偏向于底层),它更是切合HTTP使用专业。

  总之,解析Range
header的做事会多复杂度,相应的客户端在构建请求时为需开展一些处理。而采用单独的limit和offset参数会越加爱理解以及构建,并且不待对开发人员有重新多的渴求。

结果限制

  “给出第3至第55漫漫的记录”,这种求数据的方及HTTP的字节范围规范更平等,因此我们可用它来标识Range
header。而“从第2漫长记下开始,给来极多20漫漫记下”这种方法又爱阅读与掌握,因此我们便会因此字符串查询参数的点子来表示。

  综上所述,推荐既支持用HTTP Range
header,也支撑以字符串查询参数——offset(偏移量)和limit(限制),然后于服务端对响应结果开展限定。注意,如果以支持这简单种方法,那么字符串查询参数的优先级要压倒Range
header。

  这里你或许会见有只疑问:“这有限栽办法效果相似,但是回去的数目未完全一致。这会无见面吃丁歪曲呢?”恩…这是有限独问题。首先使回应的是,这实在会被人口歪曲。关键是,字符串查询参数看起更为清晰易懂,在构建与分析时越方便。而Range
header则再次多是由于机器来采取(偏向于底层),它更是切合HTTP使用专业。

  总之,解析Range
header的工作会增加复杂度,相应的客户端在构建请求时也欲进行部分甩卖。而以单独的limit和offset参数会进一步容易懂与构建,并且不待针对开发人员有双重多之要求。

因而范围标记进行限

  当用HTTP header而休是字符串查询参数来博取记录之克时,Ranger
header应该经过以下内容来指定范围: 

  Range: items=0-24

  注意记录是从0开始的连年字段,HTTP规范中证实了何等运用Range
header来请求字节。也就是说,如果只要请求数据集中的率先长长的记下,范围该从0开始算从。上述的请将见面返回前25单记录,假而数据集中至少发生25修记下。

  而在服务端,通过检查请求的Range
header来确定该归哪些记录。只要Range
header存在,就见面出一个简约的正则表达式(如”items=(\d+)-(\d+)”)对该进行分析,来获得要找的范围值。

据此范围标记进行界定

  当用HTTP header而非是字符串查询参数来取记录的限定时,Ranger
header应该通过以下内容来指定范围: 

  Range: items=0-24

  注意记录是从0开始之总是字段,HTTP规范中证了如何采取Range
header来请求字节。也就是说,如果如呼吁数据汇总之首先修记下,范围应当从0开始算打。上述的请求将见面回去前25只记录,假要数据集中至少有25长记下。

  而在服务端,通过检查请求的Range
header来确定该归哪些记录。只要Range
header存在,就见面出一个略的正则表达式(如”items=(\d+)-(\d+)”)对那个进行辨析,来博取要寻找的范围值。

因此字符串查询参数进行限制

  字符串查询参数为作为Range
header的替代选择,它以offset和limit作为参数称呼,其中offset代表要询问的第一修记下编号(与上述的用来范围标记的items第一独数字同样),limit代表记录的无限要命条数。下面的例证返回的结果跟上述用范围标记的例子一样:

  GET http://api.example.com/resources?offset=0&limit=25

  Offset参数的价值与Range
header中的切近,也是从0开始算。Limit参数的值是回到记录之极度特别数量。当字符串查询参数中无指定limit时,服务端应当被起一个少省之无限老limit值,不过这些参数的运用都急需在文档中开展认证。

据此字符串查询参数进行限制

  字符串查询参数为看作Range
header的替代选择,它以offset和limit作为参数叫,其中offset代表要查询的第一长条记下编号(与上述的用于范围标记的items第一个数字相同),limit代表记录之最好特别条数。下面的例证返回的结果和上述用范围标记的例子一样:

  GET http://api.example.com/resources?offset=0&limit=25

  Offset参数的价值和Range
header中之类似,也是从0开始算计。Limit参数的值是归记录的卓绝深数目。当字符串查询参数中未指定limit时,服务端应当吃来一个缺乏省的最好要命limit值,不过这些参数的使还得以文档中开展验证。

基于范围之应

  对一个因范围之呼吁来说,无论是通过HTTP的Range
header还是经过字符串查询参数,服务端都该出一个Content-Range
header来响应,以标明返回记录之条数和总记录数:

  Content-Range: items 0-24/66

  注意这里的总记录数(如本例中之66)不是从0开始盘算的。如果只要请数据汇总的末尾几乎修记下,Content-Range
header的情节应是如此:

  Content-Range: items 40-65/66

  根据HTTP的正规,如果响应时总记录数未知或不便计算,也得以就此星号(”*”)来顶替(如本例中的66)。本例中响应头也可这般勾画:

  *Content-Range: items 40-65/**

  不过假如留意,Dojo或有旁的UI工具或不支持该符号。

冲范围之应

  对一个因范围之呼吁来说,无论是通过HTTP的Range
header还是经过字符串查询参数,服务端都当产生一个Content-Range
header来响应,以标明返回记录之条数和总记录数:

  Content-Range: items 0-24/66

  注意这里的究竟记录数(如本例中之66)不是从0开始计的。如果要是乞求数据汇总之末尾几乎长条记下,Content-Range
header的情节应当是如此:

  Content-Range: items 40-65/66

  根据HTTP的业内,如果响应时到底记录数未知或难计算,也足以就此星号(”*”)来替(如本例中之66)。本例中响应头也不过这么描绘:

  *Content-Range: items 40-65/**

  不过若是留心,Dojo或有另的UI工具或无支持该符号。

分页

  上述措施通过请求方指定数据集的限定来限制返回结果,从而实现分页功能。上面的事例中总计来66条记下,如果各级页25久记下,要展示第二页数据,Range
header的情如下:

  Range: items=25-49

  同样,用字符串查询参数表示如下:

  GET …?offset=25&limit=25

  服务端会相应地回一组数据,附带的Content-Range header内容如下:

  Content-Range: 25-49/66

  在大部分动静下,这种分页方式还没问题。但有时候会发出这种情况,就是若回来的笔录数据无法直接表示成数据汇总之行号。还有即使是出来数据集的生成很快,不断会出新的数据插入到数量集中,这样定会造成分页出现问题,一些又的数目可能会见起于不同的页中。

  按日期排列的数据集(例如Twitter
feed)就是一样栽常见的事态。虽然你要么得对数据开展分页,但偶尔用”after”或”before”这样的第一字连与Range
header(或者和字符串查询参数offset和limit)配合来兑现分页,看起会愈加简洁易亮。

  例如,要获得给定时间戳的先头20长长的评论:

  GET
http://www.example.com/remarks/home\_timeline?after=&lt;timestamp&gt; 

  Range: items=0-19

  GET
http://www.example.com/remarks/home\_timeline?before=&lt;timestamp&gt; 

*  Range: items=0-19*

  用字符串查询参数表示也:

  GET
http://www.example.com/remarks/home\_timeline?after=&lt;timestamp&gt;&offset=0&limit=20 

*  GET
http://www.example.com/remarks/home\_timeline?before=&lt;timestamp&gt;&offset=0&limit=20*

  有关以不同景象对时间戳的格式化处理,请参见下文的“日期/时间拍卖”。

  如果请时从没点名要返回的数码范围,服务端返回了平组默认数据要限的太深数据集,那么服务端同时为相应以回到结果负富含Content-Range
header来和客户端进行确认。以点个人主页的年华轴为条例,无论客户端是不是指定了Range
header,服务端每次都只回去20条记下。此时,服务端响应的Content-Range
header应该包含如下内容:

  Content-Range: 0-19/4125

  或 *Content-Range: 0-19/**

分页

  上述方法经过请求方指定数据集的限量来限制返回结果,从而实现分页功能。上面的例子中累计有66久记下,如果各国页25长长的记下,要显得第二页数据,Range
header的情节如下:

  Range: items=25-49

  同样,用字符串查询参数表示如下:

  GET …?offset=25&limit=25

  服务端会相应地回来一组数,附带的Content-Range header内容如下:

  Content-Range: 25-49/66

  于大部场面下,这种分页方式都并未问题。但奇迹会来这种状况,就是只要回到的记录数据无法直接代表成数据汇总的行号。还有即使是发生把数据集的成形快,不断会发出新的数插入到数码集中,这样自然会招致分页出现问题,一些再度的多少或许会见产出于不同的页中。

  按日期排列的数据集(例如Twitter
feed)就是同一种植常见的情。虽然你还是得以本着数据开展分页,但奇迹用”after”或”before”这样的根本字连和Range
header(或者与字符串查询参数offset和limit)配合来落实分页,看起会越加简明易亮。

  例如,要收获给定时间戳的前方20长条评论:

  GET
http://www.example.com/remarks/home\_timeline?after=&lt;timestamp&gt; 

  Range: items=0-19

  GET
http://www.example.com/remarks/home\_timeline?before=&lt;timestamp&gt; 

*  Range: items=0-19*

  用字符串查询参数表示也:

  GET
http://www.example.com/remarks/home\_timeline?after=&lt;timestamp&gt;&offset=0&limit=20 

*  GET
http://www.example.com/remarks/home\_timeline?before=&lt;timestamp&gt;&offset=0&limit=20*

  有关以不同状况对日戳的格式化处理,请参见下文的“日期/时间处理”。

  如果请时没有点名要回到的多少范围,服务端返回了同等组默认数据还是限的极度老数据集,那么服务端同时也应当于返结果丁包含Content-Range
header来和客户端进行确认。以地方个人主页的时空轴为例,无论客户端是不是指定了Range
header,服务端每次都只是回20久记下。此时,服务端响应的Content-Range
header应该包含如下内容:

  Content-Range: 0-19/4125

  或 *Content-Range: 0-19/**

结果的过滤与排序

  针对返回结果,还需考虑什么以服务端对数据开展过滤和排,以及怎样以指定的一一对子数据进行搜索。这些操作可以跟分页、结果限制,以及字符串查询参数filter和sort等互动结合,可以实现强大的数据检索功能。

  再强调平等不好,过滤跟排序都是繁体的操作,不需要默认提供给拥有的资源。下文将介绍如何资源要提供过滤与排序。

结果的过滤和排序

  针对返回结果,还需考虑怎么以服务端对数码进行过滤和排,以及怎样仍指定的一一对子数据开展查找。这些操作可以与分页、结果限制,以及字符串查询参数filter和sort等相结合,可以实现强大的数据检索功能。

  再强调平等糟糕,过滤跟排序都是扑朔迷离的操作,不待默认提供于有的资源。下文将介绍如何资源需要提供过滤与排序。

过滤

  以本文中,过滤被定义也“通过一定的格来规定要使回的数码,从而减少返回的多少”。如果服务端支持一效完整的于运算符和错综复杂的准配合,过滤操作以易得一定复杂。不过我们平常会动用一些简单易行的表达式,如starts-with(以…开始)或contains(包含)来进展匹配,以保返回数据的完整性。

  在我们开始谈论过滤的字符串查询参数之前,必须先明了为什么而动单个参数而休是多个字符串查询参数。从根本上来说是以削减参数名称的扑。我们曾出offsetlimitsort(见下文)参数了。如果可能的话语还见面生jsonpformat标识符,或许还会见起afterbefore参数,这些还是于本文遭干了的字符串查询参数。字符串查询中采取的参数越多,就越可能造成参数名称的撞,而采用单个过滤参数则会拿闯的可能降低到低于。

  此外,从服务端也杀易就经过单个的filter参数来判定请求方是否用数过滤效果。如果查询需要的复杂度增加,单个参数将再度具备灵活性——可以协调建平等学功能一体化的询问语法(详见下文OData注释或看http://www.odata.org)。

  通过引入一组大的、公认的分隔符,用于过滤的表达式可以因死直观的形式让应用。用这些分隔符来设置过滤查询参数的值,这些分隔符所创建的参数名/值对能越来越便于地让服务端解析并增强数据查询的性能。目前都有些分隔符包括用来分隔每个过滤短语的竖线(”|”)和用来分隔参数名为与价值的夹冒号(”::”)。这套分隔符足够唯一,并符合大多数情况,同时用她来构建的字符串查询参数为越加容易掌握。下面用为此一个简便的例证来介绍她的用法。假设我们想只要为名吧“Todd”的用户等发送请求,他们已在丹佛,有着“Grand
Poobah”之如。用字符串查询参数实现的乞求URI如下:

  GET
http://www.example.com/users?filter="name::todd|city::denver|title::grand
poobah”

  双冒号(”::”)分隔符将属于性名和价值分开,这样属性值就会包含空格——服务端能再次易于地由属于性值中剖析出分隔符。

  注意查询参数名/值对遭到的性质名要和服务端返回的习性名相匹配。

  简单而使得。有关大小写敏感的题材,要因具体情况来拘禁,但看来,在毫无关心大小写的景况下,过滤效果可以死好地运作。若查询参数名/值对遭受之属性值未知,你吧足以为此星号(”*”)来代替。

  除了简单的表达式和通配符之外,若要进行重新复杂的查询,你必使引入运算符。在这种情景下,运算符本身为是属性值的一致片段,能够为服务端解析,而无是变成属性名的平等有些。当得复杂的query-language-style(查询语言风格)功能时,可参考Open
Data Protocol (OData) Filter System Query
Option说明遭到之询问概念(详见http://www.odata.org/documentation/uriconventions#FilterSystemQueryOption)。

过滤

  以本文中,过滤被定义为“通过特定的条件来确定要要返回的数据,从而减少返回的数量”。如果服务端支持一法完整的比较运算符和复杂性的格相当,过滤操作以移得一定复杂。不过我们司空见惯会使用部分简易的表达式,如starts-with(以…开始)或contains(包含)来展开匹配,以管返回数据的完整性。

  在我们开讨论过滤的字符串查询参数之前,必须先了解为什么而利用单个参数而无是大抵独字符串查询参数。从根本上来说是为了削减参数名称的冲。我们已经有offsetlimitsort(见下文)参数了。如果可能的言语还见面出jsonpformat标识符,或许还会时有发生afterbefore参数,这些还是于本文吃涉及了之字符串查询参数。字符串查询中以的参数越多,就更加可能造成参数名称的冲,而使单个过滤参数则会拿闯之可能降低到低。

  此外,从服务端也殊容易就经过单个的filter参数来判断请求方是否需要多少过滤效果。如果查询需要的复杂度增加,单个参数将还享有灵活性——可以好树立平等效功能完全的询问语法(详见下文OData注释或访问http://www.odata.org)。

  通过引入一组大的、公认的分隔符,用于过滤的表达式可以因老直观的花样让采用。用这些分隔符来设置过滤查询参数的价,这些分隔符所创建的参数名/值对能够更容易地让服务端解析并加强数据查询的性质。目前已经部分分隔符包括用来分隔每个过滤短语的竖线(”|”)和用来分隔参数称作与价值的双冒号(”::”)。这套分隔符足够唯一,并符合大多数场面,同时用她来构建的字符串查询参数为愈发便于掌握。下面用因此一个简单的例子来介绍她的用法。假设我们想只要为名吧“Todd”的用户等发送请求,他们停下在丹佛,有着“Grand
Poobah”之如。用字符串查询参数实现之乞求URI如下:

  GET
http://www.example.com/users?filter="name::todd|city::denver|title::grand
poobah”

  双冒号(”::”)分隔符将属于性名和价值分开,这样属性值就可知包含空格——服务端能更易于地于属于性值中剖析出分隔符。

  注意查询参数名/值对饱受的特性名要和服务端返回的属性名相匹配。

  简单而行。有关大小写敏感的题材,要因具体情况来拘禁,但总的看,在毫无关心大小写的景况下,过滤效果可生好地运行。若查询参数名/值对饱受之属性值未知,你为堪为此星号(”*”)来代替。

  除了简单的表达式和通配符之外,若一旦拓展双重扑朔迷离的查询,你不能不使引入运算符。在这种情景下,运算符本身吗是属性值的一样片段,能够吃服务端解析,而休是成为属性名的一致有些。当用复杂的query-language-style(查询语言风格)功能时,可参看Open
Data Protocol (OData) Filter System Query
Option说明遭到之询问概念(详见http://www.odata.org/documentation/uriconventions#FilterSystemQueryOption)。

排序

  排序决定了由服务端返回的笔录之次第。也就是是针对性响应中之大都长条记下进行排序。

  同样,我们这里仅仅考虑有比较简单的情景。推荐以排序字符串查询参数,它含了平组用分隔符分隔的属性名。具体做法是,默认对每个属性名以升序排列,如果属于性名有前缀”-“,则按照降序排列。用竖线(”|”)分隔每个属性名,这跟前过滤效果受到之参数名/值对之做法一样。

  举个例证,如果我们纪念以用户的姓和名展开升序排序,而针对性雇佣时间进行降序排序,请求将是这么的:

  GET
http://www.example.com/users?sort=last\_name|first\_name|-hire\_date

  再次强调一下,查询参数名/值对受到的性质名要和服务端返回的习性名相匹配。此外,由于排序操作比较复杂,我们无非对用的资源提供排序功能。如果需要的话也可以客户端对有些之资源集进行排。

 

排序

  排序决定了起服务端返回的记录之一一。也不怕是针对响应中之差不多长长的记下进行排序。

  同样,我们这里只考虑有比较简单的状。推荐用排序字符串查询参数,它蕴含了一样组用分隔符分隔的属性名。具体做法是,默认对每个属性名以升序排列,如果属于性名有前缀”-“,则以降序排列。用竖线(”|”)分隔每个属性名,这跟前过滤效果受到之参数名/值对之做法一样。

  举个例子,如果我们纪念按部就班用户的姓和叫展开升序排序,而针对性雇佣时间展开降序排序,请求将是这么的:

  GET
http://www.example.com/users?sort=last\_name|first\_name|-hire\_date

  再次强调一下,查询参数名/值对被的特性名要和服务端返回的性能名相匹配。此外,由于排序操作比较复杂,我们仅仅针对急需的资源提供排序功能。如果需要的话也得以在客户端对小之资源聚集进行排列。

 

服务版本管理

   坦率地开口,一说到本就会见吃人觉着好艰苦,很麻烦,不太容易,甚至会受人觉得难受——因为马上会加API的复杂度,并以可能会见指向客户端有一些影响。因此,在API的统筹被一旦尽量避免多独例外的本。

  不支持版本,不以版本控制作为糟糕的API设计之倚重。如果你当APIs的宏图着引入版本,这迟早还见面被您捉狂。由于返回的数目通过JSON来展现,客户端会由于不同的版本要接受及不同之性质。这样便见面有一些题目,如从内容己以及验证规则者改变了一个就在的性之含义。

  当然,我们无法避免API可能在少数时刻要变更返回数据的格式和内容,而立即为将造成消费端的片段变通,我们应避免进行有重大的调。将API进行版本化管理是免这种重要变化的平种中办法。

服务版本管理

   坦率地谈,一说到本就会见受丁觉得特别不便,很麻烦,不绝好,甚至会见让丁觉着难受——因为及时会增多API的复杂度,并而可能会见指向客户端起局部震慑。因此,在API的宏图受到要尽量避免多只例外之本子。

  不支持版本,不将版本控制作为糟糕之API设计的指。如果您于APIs的计划中引入版本,这晚早还见面为你逮狂。由于返回的多少经过JSON来见,客户端会由于不同之版要接受及不同的特性。这样即便见面有有题目,如由内容己以及认证规则方面改变了一个早已在的习性的意思。

  当然,我们鞭长莫及避免API可能当好几时刻要改返回数据的格式和内容,而立吗用导致消费端的有些转,我们应有避免进行部分要的调动。将API进行版本化管理是免这种根本变动的一律种植中方式。

经过内容商支持版本管理

  以往,版本管理通过URI本身的本号来好,客户端在请的URI中标明要取之资源的版本号。事实上,许多生商家只要Twitter、Yammer、Facebook、Google等不时于他们的URI里使用版本号。甚至像WSO2这样的API管理工具也会以它们的URLs中要求版本号。

  面向REST原则,版本管理技术飞速发展。因为她不含有HTTP规范着放到的header,也未支持就当一个新的资源要概念让引入时才应添加新URI的观——即版本不是表现形式的变迁。另一个反对之理是资源URI是无会见随时间改变之,资源就是资源。

  URI应该能大概地辨认资源——而休是其的“形状”(状态)。另一个即是要指定响应的格式(表征)。还有一对HTTP
headers:Accept 和 Content-Type。Accept
header允许客户端指定所梦想或者能支撑之应的媒体类型(一栽要多)。Content-Type
header可分别于客户端与服务端用来指定要或响应的多寡格式。

  例如,要落一个user的JSON格式的数量:

  #Request:

  GET http://api.example.com/users/12345
  Accept: application/json; version=1

  #Response:

  HTTP/1.1 200 OK
  Content-Type: application/json; version=1

  {“id”:”12345″, “name”:”Joe DiMaggio”}

  现在,我们对相同资源要版本2底数码:

  #Request:

  GET http://api.example.com/users/12345
  Accept: application/json; version=2

  #Response:

  HTTP/1.1 200 OK
  Content-Type: application/json; version=2

  {“id”:”12345″, “firstName”:”Joe”, “lastName”:”DiMaggio”}

  Accept
header被用来表示所盼的应格式(以及示例中的版本号),注意上述两个一律之URI是哪就在不同之本子中分辨资源的。或者,如果客户端需要一个XML格式的数量,可以用Accept
header设置也”application/xml”,如果需要的话也足以带来一个指定的版本号。

  由于Accept
header可以为设置为允许多传媒类型,在响应请求时,服务器将把响应的Content-Type
header设置为最匹配配客户端请求内容的品类。更多信息可参照http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.Html

  例如:

  #Request

  GET http://api.example.com/users/12345

  Accept: application/json; version=1, application/xml; version=1

  上述呼吁被,假设服务器支持JSON
和XML格式的恳求,或者少种植都支持,那么用由服务器来控制最终回到哪种档次的多寡。但无服务器选择哪一样种植,都见面在应中涵盖Content-Type
header。

  例如,如果服务器返回application/xml格式的数码,结果是:

  #Response

  HTTP/1.1 200 OK
  Content-Type: application/xml; version=1

  <user>
    <id>12345</id>
    <name>Joe DiMaggio</name>
  </user>

  为了证明Content-Type在发送数据给服务器时的用途,这里叫起一个所以JSON格式创建新用户之事例:

  #Request

  POST http://api.example.com/users
  Content-Type: application/json;version=1

  {“name”:”Marco Polo”}

  或者,调用版本2底接口:

  #Request

  POST http://api.example.com/users
  Content-Type: application/json;version=2

  {“firstName”:”Marco”, “lastName”:”Polo”}

由此内容商支持版本管理

  以往,版本管理通过URI本身的本子号来成功,客户端在伸手的URI中标明要收获的资源的版本号。事实上,许多百般商家要Twitter、Yammer、Facebook、Google等时以他们的URI里使用版本号。甚至像WSO2这样的API管理工具也会见当其的URLs中求版本号。

  面向REST原则,版本管理技术飞速发展。因为她不含HTTP规范中放置的header,也未支持不过当一个新的资源还是概念叫引入时才当添加新URI的见地——即版本不是表现形式的变化。另一个不予之说辞是资源URI是不见面随时间改变之,资源就是资源。

  URI应该能够简单地识别资源——而未是其的“形状”(状态)。另一个尽管是必须指定响应的格式(表征)。还有部分HTTP
headers:Accept 和 Content-Type。Accept
header允许客户端指定所梦想要能支持之应的传媒类型(一种或多种)。Content-Type
header可分别让客户端和劳动端用来指定要或响应的多寡格式。

  例如,要落一个user的JSON格式的数量:

  #Request:

  GET http://api.example.com/users/12345
  Accept: application/json; version=1

  #Response:

  HTTP/1.1 200 OK
  Content-Type: application/json; version=1

  {“id”:”12345″, “name”:”Joe DiMaggio”}

  现在,我们针对平资源要版本2之数码:

  #Request:

  GET http://api.example.com/users/12345
  Accept: application/json; version=2

  #Response:

  HTTP/1.1 200 OK
  Content-Type: application/json; version=2

  {“id”:”12345″, “firstName”:”Joe”, “lastName”:”DiMaggio”}

  Accept
header被用来表示所盼的应格式(以及示例中的版本号),注意上述两个一律之URI是何等形成在不同之本子中分辨资源的。或者,如果客户端需要一个XML格式的数量,可以以Accept
header设置也”application/xml”,如果需要的话也堪带来一个指定的版本号。

  由于Accept
header可以让设置为允许多传媒类型,在响应请求时,服务器将拿响应的Content-Type
header设置为极端匹配配客户端请求内容之色。更多信息可以参见http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.Html

  例如:

  #Request

  GET http://api.example.com/users/12345

  Accept: application/json; version=1, application/xml; version=1

  上述呼吁被,假设服务器支持JSON
和XML格式的乞求,或者简单栽都支持,那么以出于服务器来决定最终回到哪种档次的多寡。但不论服务器选择哪一样种,都见面在响应中含有Content-Type
header。

  例如,如果服务器返回application/xml格式的数码,结果是:

  #Response

  HTTP/1.1 200 OK
  Content-Type: application/xml; version=1

  <user>
    <id>12345</id>
    <name>Joe DiMaggio</name>
  </user>

  为了证实Content-Type在发送数据给服务器时的用处,这里为出一个所以JSON格式创建新用户之例证:

  #Request

  POST http://api.example.com/users
  Content-Type: application/json;version=1

  {“name”:”Marco Polo”}

  或者,调用版本2之接口:

  #Request

  POST http://api.example.com/users
  Content-Type: application/json;version=2

  {“firstName”:”Marco”, “lastName”:”Polo”}

当没点名版本时,返回什么版本?

  并不需要在各一个呼吁被还指定版本号。由于HTTP
content-negotiation(内容商)遵循类型的“最佳匹配”方式,所以若的API也相应按照这或多或少。根据当时同样条件,当客户端从未点名版本时,API应当返回所支持的不过早版本。

  还是这个事例,获取一个user的JSON格式的多寡:

  #Request

  GET http://api.example.com/users/12345
  Accept: application/json

  #Response

  HTTP/1.1 200 OK
  Content-Type: application/json; version=1

  {“id”:”12345″, “name”:”Joe DiMaggio”}

  相应地,当为POST方式向服务器发送数据常常,如果服务器支持多只不同版本,而告时以无点名版本,和上面的事例一样——服务器会将尽小/最早版本的数目包含在body中。为了进行验证,下面的例证以JSON格式请求一个暗含多版本资源的服务器,来创造一个新用户(预期会回来版本1):

  #Request

  POST http://api.example.com/users
  Content-Type: application/json

  {“name”:”Marco Polo”}

  #Response

  HTTP/1.1 201 OK
  Content-Type: application/json; version=1
  Location: http://api.example.com/users/12345

  {“id”:”12345″, “name”:”Marco Polo”}

当没点名版本时,返回什么版本?

  并不需要在每一个请求被还指定版本号。由于HTTP
content-negotiation(内容商)遵循类型的“最佳匹配”方式,所以您的API也应仍这或多或少。根据当时无异口径,当客户端从未点名版本时,API应当返回所支持之顶早版本。

  还是这个例子,获取一个user的JSON格式的数额:

  #Request

  GET http://api.example.com/users/12345
  Accept: application/json

  #Response

  HTTP/1.1 200 OK
  Content-Type: application/json; version=1

  {“id”:”12345″, “name”:”Joe DiMaggio”}

  相应地,当因为POST方式向服务器发送数据常常,如果服务器支持多个例外版本,而求时同时尚未点名版本,和点的例证一样——服务器会将最为小/最早版本的数包含在body中。为了进行求证,下面的例子以JSON格式请求一个分包多版本资源的服务器,来创造一个新用户(预期会回到版本1):

  #Request

  POST http://api.example.com/users
  Content-Type: application/json

  {“name”:”Marco Polo”}

  #Response

  HTTP/1.1 201 OK
  Content-Type: application/json; version=1
  Location: http://api.example.com/users/12345

  {“id”:”12345″, “name”:”Marco Polo”}

请求不支持之本子

  当求一个休支持的本号时(包含在API生命周期中都不复存在的资源版本),API应当返回一个错误的HTTP状态码406(表示不让受)。此外,API还应当返回一个带有Content-Type:
application/json的响应体,其中饱含一个JSON数组,用于证明该服务器支持的型。

  #Request

  GET http://api.example.com/users/12345
  Content-Type: application/json; version=999

  #Response

  HTTP/1.1 406 NOT ACCEPTABLE 

  Content-Type: application/json

  [“application/json; version=1”, “application/json; version=2”,
“application/xml; version=1”, “application/xml; version=2”]

告不支持之本

  当求一个休支持的本号时(包含在API生命周期中既消失的资源版本),API应当返回一个破绽百出的HTTP状态码406(表示未为领)。此外,API还应返回一个涵盖Content-Type:
application/json的响应体,其中带有一个JSON数组,用于证明该服务器支持的种类。

  #Request

  GET http://api.example.com/users/12345
  Content-Type: application/json; version=999

  #Response

  HTTP/1.1 406 NOT ACCEPTABLE 

  Content-Type: application/json

  [“application/json; version=1”, “application/json; version=2”,
“application/xml; version=1”, “application/xml; version=2”]

哟时应该创建一个新本子?

  API开发中之博方面还见面打破约定,并最终指向客户端起局部不良影响。如果您免确定API的改会带来什么的究竟,保险起见最好考虑使用本控制。当您以设想提供一个新本子是否适用时,或者考虑针对现有的归表征进行改动是否肯定能够满足急需并于客户端所领时,有这般几个要素使考虑。

好家伙时应该创建一个初本子?

  API开发被的群者都见面打破约定,并最后指向客户端有有不良影响。如果你无确定API的改动会带什么的结局,保险起见最好考虑动用本控制。当你以考虑提供一个初本子是否恰当时,或者考虑对现有的返表征进行改动是否必然能满足急需并吃客户端所承受时,有诸如此类几独要素使考虑。

破坏性的改

  • 变更属性名(例如将”name”改成为”firstName”)
  • 去除属性
  • 转属性之数据类型(例如将numeric变为string,
    boolean变为bit/numeric,string 变为 datetime等等)
  • 改变验证规则
  • 每当Atom样式的链接中,修改”rel”的价
  • 当存活的工作流中引入必要资源
  • 更改资源的概念/意图;概念/意图或资源状态的义不同于其原本之含义。例如:
    • 一个content
      type是text/html的资源,之前表示的是有所支持的媒体类型的一个”links”集合,而新的text/html则象征的是用户输入的“web浏览器表单”。
    • 一个含”endTime”参数的API,对资源”…/users/{id}/exams/{id}”表达的意思是生当生时刻付诸试卷,而新的义则是考的预定完毕时间。
  • 通过丰富新的字段来改现有的资源。将鲜个资源集合为一个并弃用原始的资源。
    • 发出这般少只资源”…/users/{id}/dropboxBaskets/{id}/messages/{id}”和”…/users/{id}/dropboxBaskets/{id}/messages/{id}/readStatus”。新要求是管readStatus资源的属性放到单独的message资源被,并弃用readStatus资源。这将促成messages资源遭到指向readStatus资源的链接给移除。

  虽然上面列有底并无圆满,但它被起了有些见面指向客户端起破坏性影响之转类型,这时需要考虑提供一个初资源要新本子。

破坏性的修改

  • 更改属性名(例如将”name”改化”firstName”)
  • 除去属性
  • 转移属性的数据类型(例如将numeric变为string,
    boolean变为bit/numeric,string 变为 datetime等等)
  • 更改验证规则
  • 在Atom样式的链接中,修改”rel”的价值
  • 当现有的工作流中引入必要资源
  • 转资源的定义/意图;概念/意图或资源状态的意义不同让她原有之义。例如:
    • 一个content
      type是text/html的资源,之前表示的凡兼备支持的传媒类型的一个”links”集合,而新的text/html则象征的凡用户输入的“web浏览器表单”。
    • 一个含”endTime”参数的API,对资源”…/users/{id}/exams/{id}”表达的意义是学员以大时刻付诸试卷,而新的含义则是考试的预约完毕时。
  • 通过抬高新的字段来转现有的资源。将少只资源集合为一个并弃用原始的资源。
    • 发生这般点滴个资源”…/users/{id}/dropboxBaskets/{id}/messages/{id}”和”…/users/{id}/dropboxBaskets/{id}/messages/{id}/readStatus”。新要求是把readStatus资源的习性放到单独的message资源被,并丢掉用readStatus资源。这将促成messages资源面临指向readStatus资源的链接给移除。

  虽然上面列有底并无完善,但其给出了有些见面指向客户端起破坏性影响的变类型,这时要考虑提供一个新资源或新本子。

非破坏性的改动

  • 于回到的JSON中补充加新属性
  • 丰富指向任何资源的”link”
  • 添加content-type支持之初格式
  • 添加content-language支持的新格式
  • 由API的缔造者和顾客都要处理不同的casing,因此casing的成形无关紧要

非破坏性的改动

  • 当回的JSON中上加新属性
  • 增长指向任何资源的”link”
  • 添加content-type支持的新格式
  • 添加content-language支持之新格式
  • 是因为API的创建者和顾客还要处理不同之casing,因此casing的转移无关紧要

版本控制应在什么级别出现?

  建议对单个的资源拓展版本控制。对API的有些变更,如修改工作流,也许如果跨越多独资源的版本控制,以这个来防护对客户端有破坏性的熏陶。

版本控制应以啊级别出现?

  建议针对单个的资源开展版本控制。对API的部分变更,如修改工作流,也许要逾多只资源的版本控制,以之来预防对客户端起破坏性的影响。

以Content-Location来加强响应

  可选。见RDF(Resource Description Framework,即资源描述框架)规范。

采取Content-Location来增长响应

  可选。见RDF(Resource Description Framework,即资源描述框架)规范。

带有Content-Type的链接

  Atom风格的链接支持”type”属性。提供足够的音信以便客户端好对一定的本子及内容类型进行调用。

带有Content-Type的链接

  Atom风格的链接支持”type”属性。提供足够的音信以便客户端可本着特定的版本和情节类型进行调用。

找寻有支持之版

摸索有支持的版本

自家应当又支持小只版?

  维护多只例外之本会给工作易得烦、复杂、容易错,而且代价高,对于其余给定的资源,你当支持非跳2个版。

自我应当同时支持小只版?

  维护多单例外之本子会叫工作换得烦、复杂、容易出错,而且代价高,对于另外给定的资源,你应该支持不超越2个版。

弃用

  Deprecated(弃用)的目的是用来验证资源对API仍然可用,但于将来见面不有并转换得无可用。留神:弃用的时长将由弃用政策决定——这里并无让有概念。

弃用

  Deprecated(弃用)的目的是故来证实资源对API仍然可用,但当前会见无存并更换得无可用。专注:弃用的时长将出于弃用政策决定——这里连不曾于来概念。

我怎么告客户端给弃用的资源?

  许多客户端将来做客的资源或于初本子引入后会见给废弃掉,因此,他们得出同栽方法来发现和监控他们之应用程序对遗弃用资源的运。当求一个弃用资源时,API应该健康应,并含有一个布尔档次的自定义Header
“Deprecated”。以下用一个例证来开展验证。

  #Request

  GET http://api.example.com/users/12345
  Accept: application/json
  Content-Type: application/json; version=1

  #Response

  HTTP/1.1 200 OK
  Content-Type: application/json; version=1
  Deprecated: true
  {“id”:”12345”, “name”:”Joe DiMaggio”}

 

自家怎么样告客户端给弃用的资源?

  许多客户端将来看的资源或在新本子引入后会叫废弃掉,因此,他们用来雷同种植方式来发现及督查他们的应用程序对委用资源的下。当呼吁一个弃用资源时,API应该正常应,并包含一个布尔类型的自定义Header
“Deprecated”。以下用一个例子来进展认证。

  #Request

  GET http://api.example.com/users/12345
  Accept: application/json
  Content-Type: application/json; version=1

  #Response

  HTTP/1.1 200 OK
  Content-Type: application/json; version=1
  Deprecated: true
  {“id”:”12345”, “name”:”Joe DiMaggio”}

 

日期/时间拍卖

  如果没有妥善地、一致地处理好日期及时来说,这将化一个万分累。我们常会面碰到时区的题材,而且由于日期在JSON中是坐字符串的格式在的,如果不指定统一之格式,那么解析日期也会是一个题材。

  以接口内部,服务端应该因为UTC或GMT时间来存储、处理与缓存时间穿。这将有效化解日期及时空的问题。

日子/时间拍卖

  如果没妥善地、一致地拍卖好日期与岁月吧,这将改为一个异常累。我们常常会面碰到时区的题材,而且由于日期在JSON中凡为字符串的格式在的,如果不指定统一之格式,那么解析日期也会见是一个题材。

  以接口内部,服务端应该坐UTC或GMT时间来存储、处理和缓存时间戳。这将有效解决日期及时的题目。

Body内容遭的日期/时间序列化

  有一个粗略的章程可以解决这些题目——在字符串中尽用同一之格式,包括时间片(带有时区信息)。ISO8601时间格式是一个没错的解决方案,它应用了全增强的时空格式,包括小时、分钟、秒和秒的小数部分(例如yyyy-MM-dd’T’HH:mm:ss.SSS’Z’)。建议以REST服务的body内容被(请求与应均包括)使用ISO8601代表有的日子格式。

  顺便取一下,对于那些基于JAVA的服务以来,DateAdapterJ库使用DateAdapter,Iso8601TimepointAdapter和HttpHeaderTimestampAdapter类可以非常容易地分析及格式化ISO8601日期和时,以及HTTP
1.1
header(RFC1123)格式。可以从https://github.com/tfredrich/DateAdapterJ下载。

  对于那些创建基于浏览器的用户界面来说,ECMAScript5标准一开始就是含了JavaScript解析及创造ISO8601日期的始末,所以它们应有改成我们所说之主流浏览器所遵循的艺术。当然,如果您只要支持那些不能自动解析日期的旧版浏览器,可以使JavaStript库或正则表达式。这里来几乎独好分析及创办ISO8601时间的JavaStript库:

  http://momentjs.com/

  http://www.datejs.com/

Body内容被之日子/时间序列化

  有一个大概的计好化解这些问题——在字符串中总用同样的格式,包括时间片(带有时区信息)。ISO8601时间格式是一个科学的化解方案,它利用了净增强的工夫格式,包括小时、分钟、秒和秒的小数部分(例如yyyy-MM-dd’T’HH:mm:ss.SSS’Z’)。建议于REST服务之body内容中(请求和应均包括)使用ISO8601代表所有的日子格式。

  顺便取一下,对于那些基于JAVA的劳动以来,DateAdapterJ库使用DateAdapter,Iso8601TimepointAdapter和HttpHeaderTimestampAdapter类可以非常容易地解析及格式化ISO8601日期及时,以及HTTP
1.1
header(RFC1123)格式。可以自https://github.com/tfredrich/DateAdapterJ下载。

  对于那些创建基于浏览器的用户界面来说,ECMAScript5标准一开始就带有了JavaScript解析及创办ISO8601日期的内容,所以她应有改成我们所说的主流浏览器所遵循的法子。当然,如果你如果支持那些不能自动解析日期的旧版浏览器,可以下JavaStript库或正则表达式。这里出几乎单可以分析及创办ISO8601时间之JavaStript库:

  http://momentjs.com/

  http://www.datejs.com/

HTTP Headers中之日子/时间序列化

  然而上述提议只有适用于HTTP请求或响应内容遭之JSON和XML内容,HTTP规范对HTTP
headers使用另外一样种植不同的格式。在被RFC1123再度给之RFC822中指出,该格式包括了各种日期、时间跟date-time格式。不过,建议始终以时戳格式,在你的request
headers中她看起像这么:

  Sun, 06 Nov 1994 08:49:37 GMT

  不过,这种格式没有设想毫秒或者秒的十进制小数。Java的SimpleDataFormat的格式串是:”EEE,
dd MMM yyyy HH:mm:ss ‘GMT'”。

 

HTTP Headers中之日子/时间序列化

  然而上述建议就适用于HTTP请求或响应内容被的JSON和XML内容,HTTP规范对HTTP
headers使用另外一样种植不同之格式。在被RFC1123重复给之RFC822中指出,该格式包括了各种日期、时间与date-time格式。不过,建议始终用时间戳格式,在您的request
headers中她看起如这样:

  Sun, 06 Nov 1994 08:49:37 GMT

  不过,这种格式没有考虑毫秒或者秒的十进制小数。Java的SimpleDataFormat的格式串是:”EEE,
dd MMM yyyy HH:mm:ss ‘GMT'”。

 

保安服务的安全

  Authentication(身份认证)指的是肯定给定的要是打劳动既解之某(或某个系统)发出之,且请求者是外自己所声明的特别人。Authentication是为说明请求者的真身份,而authorization(授权)是为证明请求者有权力去实践于求的操作。

  本质上,这个进程是如此的:

  1. 客户端发起一个央,将authentication的token(身份验证令牌)包含在X-Authentication
    header中,或者将token叠加以呼吁的查询串参数中。
  2. 服务器对authorization
    token(授权令牌)进行自我批评,并拓展认证(有效还不过),并基于令牌内容分析或者加载认证中心。
  3. 服务器调用授权服务,提供验证中心、被求资源与必要的操作许可。
  4. 要授权通过了,服务器将会见连续健康运转。

  上面第三步之付出可能会见较充分,但是一旦如果是一个只是缓存的权杖控制列表(ACL),那么以起远程请求前,可以以当地创建一个授权客户端来缓存最新的ACLs。

保护服务之安康

  Authentication(身份验证)指的是肯定给定的请求是于服务都掌握的某(或某某系统)发出之,且请求者是他好所声明的大人。Authentication是为证明请求者的真人真事身份,而authorization(授权)是为验证请求者有权力去执行为求的操作。

  本质上,这个过程是这么的:

  1. 客户端发起一个请,将authentication的token(身份验证令牌)包含在X-Authentication
    header中,或者将token叠加在伸手的查询串参数中。
  2. 服务器对authorization
    token(授权令牌)进行检查,并展开求证(有效且未过),并因令牌内容分析或者加载认证中心。
  3. 服务器调用授权服务,提供验证中心、被求资源及必备之操作许可。
  4. 若授权通过了,服务器将见面继续健康运转。

  上面第三步的开支可能会见比较深,但是只要如果有一个不过缓存的权柄控制列表(ACL),那么当闹远程请求前,可以当地方创建一个授权客户端来缓存最新的ACLs。

身份验证

  时极度好的做法是运OAuth身份验证。强烈推荐OAuth2,不过她依旧处在草案状态。或者选择OAuth1,它了好胜任。在少数情况下啊可选取3-Legged
OAuth。更多关于OAuth的正经好翻此http://oauth.net/documentation/spec/。

  OpenID是一个叠加选择。不过建议将OpenID作为一个增大的身份验证选项,以OAuth为主。更多关于OpenID的正规化好查此http://openid.net/developers/specs/。

身份验证

  时极度好的做法是下OAuth身份验证。强烈推荐OAuth2,不过它们依然处在草案状态。或者选择OAuth1,它了好胜任。在好几情况下呢可挑选3-Legged
OAuth。更多关于OAuth的正规化好查看此http://oauth.net/documentation/spec/。

  OpenID是一个外加选择。不过建议将OpenID作为一个附加的身份验证选项,以OAuth为主。更多关于OpenID的标准好查阅此http://openid.net/developers/specs/。

传输安全

  所有的征都应有以SSL。OAuth2需要授权服务器和access
token(访问令牌)来使TLS(安全传输层协议)。

  在HTTP和HTTPS之间切换会带来平安隐患,最好的做法是装有简报默认都下TLS。

传安全

  所有的证实都应当利用SSL。OAuth2需要授权服务器和access
token(访问令牌)来运TLS(安全传输层协议)。

  在HTTP和HTTPS之间切换会带来平安隐患,最好的做法是持有简报默认都下TLS。

授权

  对劳动的授权和针对其它应用程序的授权一样,没有其余区别。它根据这样一个题材:“主体是不是对准加的资源发要的许可?”这里为闹了简便的老三项数据(主体,资源以及批准),因此杀易构造一个支撑这种概念的授权服务。其中核心是叫予以资源访问许可的丁要体系。使用这些相似概念,就足以呢各一个主题构建一个缓存访问控制列表(ALC)。

授权

  对劳务之授权和指向其他应用程序的授权一样,没有其它区别。它根据这样一个问题:“主体是否针对加的资源起求的许可?”这里让起了简单的老三桩数据(主体,资源与准),因此特别容易构造一个支撑这种概念的授权服务。其中重点是给授予资源访问许可的口还是系。使用这些相似概念,就可为各级一个主题构建一个缓存访问控制列表(ALC)。

应用程序安全

  对RESTful服务来说,开发一个安然无恙之web应用适用同的规格。

  • 当服务器上说明所有输入。接受“已清楚”的对的输入并驳回错误的输入。
  • 防止SQL和NoSQL注入。
  • 采取library如微软的Anti-XSS或OWASP的AntiSammy来针对出口的多少开展编码。
  • 拿信息之长短限制以规定的字段长度内。
  • 劳应该仅仅显示一般的错误信息。
  • 设想工作逻辑攻击。例如,攻击者可跨了多步骤的订座流程来预订产品而不论是需输入信用卡信息呢?
  • 对可疑之位移记录日志。

  RESTful安全需要留意的地方:

  • 证实数据的JSON和XML格式。
  • HTTP动词应该叫界定以同意的方法吃。例如,GET请求不克去除一个实体。GET用来读取实体而DELETE用来删除实体。
  • 顾race
    conditions(竞争规则——由于个别独或多个经过竞争下未克吃同时做客的资源,使得这些过程产生或为时间及推进的次序因只要产出问题)。

  API网关可用于监视、限制及操纵对API的走访。以下内容可由于网关或RESTful服务实现。

  • 蹲点API的应用情况,并打听怎么活动是常规的,哪些是非正常的。
  • 范围API的行使,使恶意用户不能够歇少一个API服务(DOS攻击),并且有能力阻止恶意的IP地址。
  • 拿API密钥存储在加密的安康密钥库中。

 

应用程序安全

  对RESTful服务来说,开发一个安之web应用适用同的规格。

  • 每当服务器上印证所有输入。接受“已了解”的不易的输入并驳回错误的输入。
  • 防止SQL和NoSQL注入。
  • 使library如微软的Anti-XSS或OWASP的AntiSammy来针对输出的数开展编码。
  • 拿消息之长短限制于规定的字段长度内。
  • 劳应该单纯显示一般的错误信息。
  • 设想工作逻辑攻击。例如,攻击者可跨了多步骤的预购流程来预订产品要无需输入信用卡信息呢?
  • 针对可疑的移位记录日志。

  RESTful安全用注意的地方:

  • 征数据的JSON和XML格式。
  • HTTP动词应该于限于同意的法中。例如,GET请求不能够去一个实体。GET用来读取实体而DELETE用来删除实体。
  • 在意race
    conditions(竞争规则——由于个别独或多独经过竞争下未可知让同时做客的资源,使得这些经过来或因为时及助长的先后因使起问题)。

  API网关可用于监视、限制与控制对API的访问。以下内容可由于网关或RESTful服务实现。

  • 监API的采取状态,并打听怎么活动是健康的,哪些是非正常的。
  • 克API的施用,使恶意用户不可知止住少一个API服务(DOS攻击),并且产生能力阻止恶意的IP地址。
  • 拿API密钥存储在加密底安康密钥库中。

 

缓存和可伸缩性

  通过以网层级消除通过远程调用来抱请求的数据,缓存提高了网的只是扩展性。服务通过在响应中设置headers来增进缓存的力。遗憾的凡,HTTP
1.0遭与缓存相关的headers与HTTP
1.1例外,因此服务器如果以支持少数种版本。下表给出了GET请求而支持缓存所不可不的无比少headers集合,并吃有了适宜的叙说。

HTTP Header

描述

示例

Date

应返回的日子以及岁月(RFC1123格式)。

Date: Sun, 06 Nov 1994 08:49:37 GMT

Cache-Control

一呼百应可为缓存的尽老秒数(最深age值)。如果响应不支持缓存,值吗no-cache。

Cache-Control: 360

Cache-Control: no-cache

Expires

而让起了最大age值,该时间戳(RFC1123格式)表示的是应过期的工夫,也便是Date(例如当前日子)加上最充分age值。如果响应不支持缓存,该headers不有。

Expires: Sun, 06 Nov 1994 08:49:37 GMT

Pragma

当Cache-Control为no-cache时,该header的价为让安装为no-cahche。否则,不有。

Pragma: no-cache

Last-Modified

资源本身最后给涂改的时空穿(RFC1123格式)。

Last-Modified: Sun, 06 Nov1994 08:49:37 GMT

  为了简化,这里选出一个应中的headers集合的例子。这是一个粗略的对准资源进行GET请求的应,缓存时长为同天(24小时):

  Cache-Control: 86400
  Date: Wed, 29 Feb 2012 23:01:10 GMT
  Last-Modified: Mon, 28 Feb 2011 13:10:14 GMT
  Expires: Thu, 01 Mar 2012 23:01:10 GMT

  下面是一个类似之例证,不过缓存被完全禁用:

  Cache-Control: no-cache
  Pragma: no-cache

缓存和可伸缩性

  通过在系统层级消除通过远距离调用来博请求的数额,缓存提高了系统的但扩展性。服务通过当应中安headers来增进缓存的能力。遗憾之是,HTTP
1.0吃及缓存相关的headers与HTTP
1.1差,因此服务器如果同时支持有限栽版本。下表给起了GET请求而支持缓存所不可不的极度少headers集合,并叫来了适度的讲述。

HTTP Header

描述

示例

Date

一呼百应返回的日期和岁月(RFC1123格式)。

Date: Sun, 06 Nov 1994 08:49:37 GMT

Cache-Control

一呼百应可被缓存的极致充分秒数(最要命age值)。如果响应不支持缓存,值吗no-cache。

Cache-Control: 360

Cache-Control: no-cache

Expires

如果为起了最大age值,该日戳(RFC1123格式)表示的是应过期的工夫,也即是Date(例如当前日期)加上最深age值。如果响应不支持缓存,该headers不存。

Expires: Sun, 06 Nov 1994 08:49:37 GMT

Pragma

当Cache-Control为no-cache时,该header的价也深受安装为no-cahche。否则,不有。

Pragma: no-cache

Last-Modified

资源本身最后给涂改的时空戳(RFC1123格式)。

Last-Modified: Sun, 06 Nov1994 08:49:37 GMT

  为了简化,这里选出一个应中的headers集合的例证。这是一个概括的对准资源开展GET请求的应,缓存时长为同天(24小时):

  Cache-Control: 86400
  Date: Wed, 29 Feb 2012 23:01:10 GMT
  Last-Modified: Mon, 28 Feb 2011 13:10:14 GMT
  Expires: Thu, 01 Mar 2012 23:01:10 GMT

  下面是一个像样之例证,不过缓存被完全禁用:

  Cache-Control: no-cache
  Pragma: no-cache

ETag Header

  ETag
header对于证明缓存数据的初老程度深有因此,同时也助长条件的读取和创新操作(分别吗GET和PUT)。它的价值是一个任意字符串,用来表示回到数据的版。不过,对于返回数据的两样格式,它也可不同——JSON格式响应的ETag与同资源XML格式响应的ETag会不同。ETag
header的值好像带有格式的底层域对象的哈希表(例如Java中之Obeject.hashcode())一样简单。建议呢每个GET(读)操作返回一个ETag
header。另外,确保用对引号包含ETag的价,例如:

  ETag: “686897696a7c876b7e”

 

ETag Header

  ETag
header对于证明缓存数据的初老程度非常有因此,同时也推进条件的读取和创新操作(分别吗GET和PUT)。它的价是一个任意字符串,用来表示回到数据的版。不过,对于返回数据的两样格式,它吧得不同——JSON格式响应的ETag与平等资源XML格式响应的ETag会不同。ETag
header的价值好像带有格式的底层域对象的哈希表(例如Java中之Obeject.hashcode())一样简单。建议也每个GET(读)操作返回一个ETag
header。另外,确保用对引号包含ETag的值,例如:

  ETag: “686897696a7c876b7e”

 

HTTP状态码(前10)

  以下是由于RESTful服务或API返回的最好常用的HTTP状态码,以及部分有关其普遍用法的简便说明。其它HTTP状态码不绝经常利用,它们还是更奇特,要么更尖端。大多数劳务套件只支持这些常用之状态码,甚至只有支持中的等同组成部分,并且它们还能够正常工作。

  200 (OK) —— 通常的打响状态。表示成功之无比普遍代码。

  201 (CREATED) ——(通过POST或PUT)创建成功。通过设置Location
header来含有一个针对最新创建的资源的链接。

  204 (NO CONTENT)
—— 封装了的响应没有以,或body中尚无其它内容时(如DELETE),使用该状态。

  304 (NOT MODIFIED)
—— 用于产生极的GET调用的应,以压缩带宽的使用。
如果使用该状态,那么要为GET调用设置Date、Content-Location和ETag
headers。不含有响应体。

  400 (BAD REQUEST)
—— 用于行要时或许滋生无效状态的相似错误代码。如域名无效错误、数据丢失等。

  401 (UNAUTHORIZED)
—— 用于缺少认证token或说明token无效的错误代码。

  403 (FORBIDDEN)
—— 未授权的用户执行操作,没有权力访问资源,或者由某些原因资源不可用(如时间限制等),使用该错误码。

  404 (NOT FOUND)
—— 无论资源存不存,无论是否来401、403的限,当呼吁的资源找不交常,出于安全因素考虑,服务器都得以应用该错误码来遮掩。

  409 (CONFLICT)
—— 每当执行要或会见挑起资源撞时常采取。例如,存在双重的实体,当不支持级联删除时去根对象。

  500 (INTERNAL SERVER ERROR)
—— 当服务器抛来很时,捕捉到之形似错误。

 

HTTP状态码(前10)

  以下是出于RESTful服务还是API返回的无比常用之HTTP状态码,以及一些关于她广泛用法的简练说明。其它HTTP状态码不太经常利用,它们要更特别,要么更高级。大多数服务套件只支持这些常用的状态码,甚至仅支持中的相同局部,并且她都能健康工作。

  200 (OK) —— 通常的功成名就状态。表示成功的卓绝广泛代码。

  201 (CREATED) ——(通过POST或PUT)创建成功。通过安装Location
header来含有一个对准最新创建的资源的链接。

  204 (NO CONTENT)
—— 封装过之应没有用,或body中从不其他内容常常(如DELETE),使用该状态。

  304 (NOT MODIFIED)
—— 用于产生格的GET调用的响应,以缩减带宽的运。
如果用该状态,那么必须也GET调用设置Date、Content-Location和ETag
headers。不包含响应体。

  400 (BAD REQUEST)
—— 用于实践要时可能引起无效状态的形似错误代码。如域名无效错误、数据丢失等。

  401 (UNAUTHORIZED)
—— 用于缺少认证token或证明token无效的错误代码。

  403 (FORBIDDEN)
—— 未授权的用户执行操作,没有权限访问资源,或者出于一些原因资源不可用(如时间限制等),使用该错误码。

  404 (NOT FOUND)
—— 无论资源存不存,无论是否发401、403的限量,当呼吁的资源找不交经常,出于安全因素考虑,服务器都好下该错误码来遮掩。

  409 (CONFLICT)
—— 每当执行要或会见挑起资源撞时行使。例如,存在双重的实体,当不支持级联删除时去除根对象。

  500 (INTERNAL SERVER ERROR)
—— 当服务器抛来很时,捕捉到之形似错误。

 

外加资源

叠加资源

书籍

  REST API Design Rulebook,Mark Masse, 2011, O’Reilly Media, Inc.

  RESTful Web Services, Leonard Richardson and Sam Ruby, 2008,
O’Reilly Media, Inc.

*  RESTful Web Services Cookbook, Subbu Allamaraju, 2010, O’Reilly
Media, Inc.*

  REST in Practice: Hypermedia and Systems Architecture, Jim Webber,
et al., 2010, O’Reilly Media, Inc.

  APIs: A Strategy Guide, Daniel Jacobson; Greg Brail; Dan Woods,
2011, O’Reilly Media, Inc.

书籍

  REST API Design Rulebook,Mark Masse, 2011, O’Reilly Media, Inc.

  RESTful Web Services, Leonard Richardson and Sam Ruby, 2008,
O’Reilly Media, Inc.

*  RESTful Web Services Cookbook, Subbu Allamaraju, 2010, O’Reilly
Media, Inc.*

  REST in Practice: Hypermedia and Systems Architecture, Jim Webber,
et al., 2010, O’Reilly Media, Inc.

  APIs: A Strategy Guide, Daniel Jacobson; Greg Brail; Dan Woods,
2011, O’Reilly Media, Inc.

网站

  http://www.restapitutorial.com
http://www.toddfredrich.com
  http://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm
  http://www.json.org/
https://github.com/tfredrich/DateAdapterJ
  http://openid.net/developers/specs/
  http://oauth.net/documentation/spec/
  http://www.json.org/JSONRequest.html
http://labs.omniti.com/labs/jsend
  http://enable-cors.org/
  http://www.odata.org/documentation/uri-conventions#FilterSystemQueryOption
  http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven
  https://developer.linkedin.com/apis
  http://developers.facebook.com/docs/reference/api/
  https://dev.twitter.com/docs/api
http://momentjs.com/
  http://www.datejs.com/

 

以本来翻译的基本功及经过改动:http://blog.csdn.net/huayuqa/article/details/62237010

英文原稿下载:RESTful Best Practices-v1
2.pdf

网站

  http://www.restapitutorial.com
http://www.toddfredrich.com
  http://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm
  http://www.json.org/
https://github.com/tfredrich/DateAdapterJ
  http://openid.net/developers/specs/
  http://oauth.net/documentation/spec/
  http://www.json.org/JSONRequest.html
http://labs.omniti.com/labs/jsend
  http://enable-cors.org/
  http://www.odata.org/documentation/uri-conventions#FilterSystemQueryOption
  http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven
  https://developer.linkedin.com/apis
  http://developers.facebook.com/docs/reference/api/
  https://dev.twitter.com/docs/api
http://momentjs.com/
  http://www.datejs.com/

 

于原先翻译的根底及通过改动:http://blog.csdn.net/huayuqa/article/details/62237010

英文原文下载:RESTful Best Practices-v1
2.pdf

相关文章