正文主要读者

正文主要读者

引言

引言

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

相关文章

网站地图xml地图