NoSQLRESTful服务至上实践

正文主要读者

引言

REST是什么

  集合接口

    因资源

    经特色来操作资源

    起描述的音

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

  无状态

  可缓存

  C-S架构

  分系统

  按需编码(可选)

REST快速提示

  使HTTP动词表示有含义

  理所当然之资源名

  XML和JSON

  创立适当粒度的资源

  考虑连通性

定义

  幂等性

  安全

HTTP动词

  GET

  PUT

  POST

  PUT和POST的缔造于

  DELETE

资源命名

  资源URI示例

  资源命名的反例

  复数

归来表征

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

    最为小化链接推荐

    链接格式

  装进响应

  拍卖跨域问题

    支持CORS

    支持JSONP

查询,过滤与分页

  结果限制

    从而范围标记进行限

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

    冲范围的响应

  分页

  结果的过滤跟排序

    过滤

    排序

服务版本管理

  由此情节商支持版本管理

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

  呼吁不支持的版

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

    破坏性的改动

    非破坏性的改动

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

  运Content-Location来增进响应

  带有Content-Type的链接

  探寻有支持之本子

    自家该又支持小只版本?

    弃用

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

日子/时间处理

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

  HTTP
Headers中的日期/时间序列化

护卫服务之平安

  身份验证

  传安全

  授权

  应用程序安全

缓存和可伸缩性

  ETag Header

HTTP状态码(前10)

叠加资源

  书籍

  网站

 

正文主要读者

  该最佳实践文档适用于对RESTful
Web服务感兴趣的开发人员,该服务吗跨多只劳务之零件提供了较高的可靠性以及一致性。按照本文的指导,可高效、广泛、公开地啊内外部客户利用。

  本文中的点原则一致适用于工程师们,他们想利用这些根据最佳实践标准开发之服务。虽然他们更是体贴缓存、代理规则、监听与安全等连锁方,但是该文档能作为同一卖包含所有品种服务之总指南。

  另外,通过由这些点原则,管理人员了解及开创公共的、提供高稳定的服务所待花的全力,他们也可是从中受益。

 

引言

  现今已经生恢宏有关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架构
  • 分段系统
  • 按需编码

  以下是这些计划则的详细座谈:

统一接口

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

  基于资源

  不同资源需要因此URI来唯一标识。返回给客户端的表征和资源本身在概念上有所不同,例如服务端不见面直接传送一个数据库资源,然而,一些HTML、XML或JSON数据能展示部分数据库记录,如用芬兰语来发挥要用UTF-8编码则使根据请求和服务器实现之底细来支配。

  通过特征来操作资源

  当客户端收到包含元数据的资源的特性时,在发生权力的景下,客户端都掌握的够用的信,可以对劳务端的资源拓展删改。

  自描述的音讯

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

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

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

  除了上述情节外,HATEOS也代表,必要的下链接也可吃含有在回来的body(或头部)中,以供URI来探寻对象自我还是涉嫌对象。下文将对是展开双重详实的阐发。

  统一接口是每个REST服务规划时的必不可少准则。

无状态

  正如REST是REpresentational State
Transfer的缩写,无状态异常要紧。本质上,这标志了拍卖要所用的状态已包含在请我里,也时有发生或是URI的均等有、查询串参数、body或头部。URI能够唯一标识每个资源,body中为暗含了资源的转态(或转态变更情况)。之后,服务器将进行拍卖,将有关的状态或资源通过头部、状态和应body传递给客户端。

  从事我们这同行业之大部人口都习惯用容器来编程,容器被发出一个“会话”的概念,用于在多单HTTP请求下保持状态。在REST中,如果只要当多独请求下保持用户状态,客户端必须概括客户端的富有消息来成功请求,必要经常又发送请求。自从服务端不欲保持、更新或传递会话状态后,无状态性得到了更可怜的延展。此外,负载均衡器无需担心与管状态系统里头的对话。

  所以状态与资源间有啊异样?服务器对状态,或者说是应用状态,所关心之接触是当目前对话或要中如完成请求所急需的数量。而资源,或者说是资源状态,则是概念了资源特点的数目,例如存储于数据库中之数码。由此可见,应用状态是凡趁客户端以及请的改观而改的多寡。相反,资源状态对于发出请求的客户端的话是匪转换的。

  以网下的某个同特定岗位及摆一个回按钮,是为其仰望而会随一定之逐条来操作为?其实是坐它违反了随便状态的准。有成百上千无遵守无状态原则的案例,例如3-Legged
OAuth,API调用速度限制等。但要如尽量确保服务器中无欲在多独请求下维持以状态。

可缓存

  以万维网上,客户端可缓存页面的响应内容。因此应都应隐式或显式的概念也而缓存的,若不足缓存则使避客户端在三番五次请求后因故原始数据要污染数据来响应。管理得当的休息存会部分地还是全地除了客户端以及服务端之间的互动,进一步改进性和延展性。

C-S架构

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

分层系统

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

按需编码(可选)

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

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

  提示:REST架构中的规划则遭到,只有按需编码为可选项。如果某个服务违反了另随意一项则,严格意思上未能够称之为RESTful风格。

 

REST快速提示

  (根据地方提到的六单标准)不管在技术上是休是RESTful的,这里出一些接近REST概念的建议。遵循其,可以兑现又好、更有效的劳务:

采用HTTP动词表示有意义

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

成立的资源名

  合理之资源名称或路径(如/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作为响应。在其让统统淘汰之前,这是最终一个可是被肯定的地方。

缔造适当粒度的资源

  同开始,系统中模拟底层应用程序域或数据库架构的API更易于给创造。最终,你会想以这些劳动还结合到一块儿——利用基本上起底层资源减少通信量。在创建独立的资源后再创更充分粒度的资源,比由再要命之同集中创建于生粒度的资源更加容易有。从有略之易定义之资源开始,创建CRUD(增删查改)功能,可以假设资源的创导变得重复易于。随后,你得创造这些根据用例和削减通信量的资源。

设想连通性

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

 

定义

幂等性

  不要打字面意思来解什么是幂等性,恰恰相反,这跟某些功能紊乱的世界无关。下面是来源于维基百科的说明:

以计算机科学中,术语幂相当用于更全面地讲述一个操作,一不好或数推行该操作有的结果是一模一样的。根据使用之上下文,这可能产生例外的意思。例如,在道或者子例程调用有副作用的状态下,意味着在率先调用之后为改动的状态为保不更换。

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

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

安全

  来自维基百科:

一对法(例如GET、HEAD、OPTIONS和TRACE)被定义也安之道,这意味着其只于用来信息搜索,而不可知改变服务器的状态。换句话说,它们不会见生出副作用,除了相对来说无害的熏陶而日志、缓存、横幅广告要计数服务等。任意的GET请求,不考虑用状态的上下文,都深受当是安之。

  总之,安全意味着调用的方无见面招副作用。因此,客户端可屡屡用安全之恳求而不用担心对服务端产生任何副作用。这象征服务端必须遵GET、HEAD、OPTIONS和TRACE操作的平安概念。否则,除了针对消费端产生模糊外,它还见面导致Web缓存,搜索引擎和其它活动代理的问题——这将于服务器上有意想不到的结果。

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

  安全的道被实现呢就念操作。然而,安全并无意味着服务器必须每次都回相同的响应。

 

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暴露不安全之操作——它当永远都无克改服务器上之任何资源。

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请求很可能会见促成创建两只包含相同信息的资源。

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(未找到)。

 

资源命名

  除了当地利用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

资源命名的反例

  前面我们早已讨论过一些适中的资源命名的例子,然而有时有反面的例证也殊有教育意义。下面是有的无极端具有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是中的。好吧…

 

回去表征

  正使前方提到的,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请求返回集合,对于发出分页的事态后我们会干。

极端小化链接推荐

  以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

卷入响应

   服务器可以以应中并且返回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。

支持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'}")

 

询问,过滤与分页

  对于大数据集,从带宽的角度来拘禁,限制返回的数据量是很重要之。而于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参数会尤其容易掌握和构建,并且不需要针对开发人员有重多之求。

据此范围标记进行限

  当用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值,不过这些参数的采取都急需以文档中展开验证。

因范围之应

  对一个因范围之请来说,无论是通过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/**

结果的过滤和排序

  针对返回结果,还亟需考虑怎样当服务端对数码进行过滤跟排,以及如何仍指定的顺序对子数据进行检索。这些操作可以跟分页、结果限制,以及字符串查询参数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)。

排序

  排序决定了自服务端返回的笔录之逐一。也便是对响应中之大多长记下进行排序。

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

  举个例子,如果我们纪念循用户的姓和称进行升序排序,而针对雇佣时间开展降序排序,请求将凡这样的:

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

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

 

服务版本管理

   坦率地说,一说到本就见面给人口以为挺窘迫,很烦,不顶爱,甚至会见被人口看难受——因为当时会追加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”}

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

  并不需要在各一个呼吁中还指定版本号。由于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的改动会带什么样的名堂,保险起见最好考虑采取本控制。当您于考虑提供一个初本子是否适宜时,或者考虑对现有的归表征进行修改是否肯定能够满足急需并于客户端所收受时,有如此几独因素使考虑。

破坏性的改

  • 改变属性名(例如将”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的转变无关紧要

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

  建议针对性单个的资源进行版本控制。对API的有改动,如修改工作流,也许如果超过多单资源的版本控制,以这个来防护对客户端起破坏性的熏陶。

行使Content-Location来增长响应

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

带有Content-Type的链接

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

找来支持之版

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

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

弃用

  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”}

 

日子/时间拍卖

  如果没妥善地、一致地处理好日期和时空的话,这将成一个老大累。我们常常会面遇上时区的题目,而且由于日期在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/

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。

身份验证

  时极其好之做法是动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。

授权

  对服务之授权和对其余应用程序的授权一样,没有其余区别。它根据这样一个题目:“主体是不是对准加的资源有要的许可?”这里为出了简单的老三桩数据(主体,资源同准),因此特别轻构造一个支持这种概念的授权服务。其中中心是吃予以资源访问许可的食指要系统。使用这些相似概念,就足以呢各一个主题构建一个缓存访问控制列表(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密钥存储于加密底安全密钥库中。

 

缓存和可伸缩性

  通过当系层级消除通过远距离调用来获取请求的数目,缓存提高了系统的可扩展性。服务通过当响应中装置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”

 

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.

网站

  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地图