ECMAScriptRESTful服务至上实践

正文重要读者

引言

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菲尔德(Field)(Field)ing在他的学士杂文中指出并定义了RESTful风格。(详见http://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm

  多个统筹则分别是:

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

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

合接口

  统一接口准则定义了客户端以及服务端之间的接口,简化和分手了框架结构,这样一来每个有还不过单独衍变。以下是接口统一之季个条件:

  基于资源

  不同资源要为此URI来唯一标识。重临给客户端的表征和资源本身在概念上有所不同,例如服务端不会面直接传送一个数据库资源,但是,一些HTML、XML或JSON数据能显得部分数据库记录,如用阿尔巴尼(Barney)亚语来发挥仍然用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的事例:

资源命名的反例

  前边大家既啄磨过部分适龄的资源命名的事例,然则有时有反面的例子吗大有教育意义。下边是一些请勿顶有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是什么”无异于省中也论及过。

  依照RoyFielding在外的博客中的讲述(http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertextdriven),REST接口中最好要的部分是超文本的选取。其它,他尚提出,在被来别样相关的信息前,一个API应该是可用和可了解的。也就是说,一个API应当可以经过该链接导航及数量的逐一部分。不提出才回纯数据。

  然而当下之业界先驱们并没通常下这种做法,那体现了HATEOAS仅仅以成熟度模型中之使用率还胜。纵观众多之服务序列,它们基本上重返重新多之数据,而返的链接却甚少(或者没)。这是拂Fielding的REST约定的。菲尔德(Field)ing说:“信息的诸一个可寻址单元都率领一个地方……查询结果应呈现为一个暗含摘要新闻之链接清单,而休是目的往往组。”

  另一方面,简单粗暴地将全链接集合再次回到会大大影响网络带来富。在实际情况中,依据所要的口径或采纳状态,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。此外一个提案是出于DouglasCrockford提出的,可以查看此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浏览器表单”。
    • 一个饱含”end提姆(Tim)e”参数的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的劳动来说,Date艾达pterJ库使用Date艾达(Ada)pter,Iso8601提姆epointAdapter和HttpHeader提姆estamp艾达(Ada)pter类能够至极容易地剖析和格式化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