RESTful服务至上实践

本文主要读者

看了一鸣老师写的小说《人在风里》。

引言

细长读下来,文笔流畅,语言生动,幽默。情感描写,细致入微,景物描写,如身入其境。

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服务的特等形式。

  第3部分概述REST的意思、设计准则和它的相当规之处。第一某些点数了有的小贴士来回忆REST的劳动理念。之后的部分则会更尖锐地为web服务制造人员提供一些细节的扶助和议论,来完成3个力所能及理解显示在生产条件中的高质量REST服务。

 

REST是什么?

  REST架构方式讲述了七种设计准则。这一个用于架构的筹划准则,最早是由罗伊Fielding在她的博士随想中提出并定义了RESTful风格。(详见http://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm

  八个统筹准则分别是:

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

  以下是那几个规划准则的详细切磋:

统一接口

  统一接口准则定义了客户端和服务端之间的接口,简化和分手了框架结构,那样一来每一种部分都可独自衍生和变化。以下是接口统一的七个标准化:

  基于财富

  不一致能源须要用U途达I来唯一标识。重临给客户端的表征和能源本身在概念上有所差距,例如服务端不会直接传送3个数据库财富,然则,一些HTML、XML或JSON数据可见显示部分数据库记录,如用立陶宛语来抒发依然用UTF-8编码则要依据请求和服务器完成的细节来控制。

  通过特色来操作能源

  当客户端收到包括元数据的财富的表征时,在有权力的图景下,客户端已明白的十足的消息,可以对服务端的财富举办删改。

  自描述的音信

  每条消息都包蕴充分的数量用于确认消息该怎么处理。例如要由网络媒体类型(已知的如MIME类型)来认可需调用哪个解析器。响应同样也标志了它们的缓存能力。

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

  客户端通过body内容、查询串参数、请求头和U中华VI(能源名称)来传送状态。服务端通过body内容,响应码和响应头传送状态给客户端。那项技术被称之为超媒体(或超文本链接)。

  除了上述情节外,HATEOS也意味,须要的时候链接也可被含有在回去的body(或底部)中,以提供U奥德赛I来搜寻对象自笔者或涉及对象。下文将对此开展更详尽的讲演。

  统一接口是各种REST服务统筹时的画龙点睛准则。

无状态

  正如REST是REpresentational State
Transfer的缩写,无状态很首要。本质上,那标志了处理请求所需的情况已经包括在伸手小编里,也有恐怕是U宝马X5I的一局部、查询串参数、body或尾部。ULANDI可以唯一标识每一个财富,body中也包罗了财富的转态(或转态变更景况)。之后,服务器将展开拍卖,将相关的状态或财富通过底部、状态和响应body传递给客户端。

  从事大家这一行当的大多数人都习惯使用容器来编程,容器中有3个“会话”的概念,用于在多少个HTTP请求下保持状态。在REST中,假设要在多少个请求下维持用户意况,客户端必须总结客户端的有所音信来已毕请求,要求时再次发送请求。自从服务端不必要保持、更新或传递会话状态后,无状态性得到了更大的延展。其它,负载均衡器无需担心和无状态系统里头的对话。

  所以状态和能源间有哪些差异?服务器对于状态,恐怕说是应用状态,所关注的点是在现阶段对话或请求中要做到请求所需的数目。而能源,恐怕说是能源情形,则是概念了财富特色的数额,例如存储在数据库中的数据。不言而喻,应用状态是是随着客户端和伸手的变动而变更的多寡。相反,财富情状对于发出请求的客户端的话是不变的。

  在网络拔取的某一特定岗位上安排3个赶回按钮,是因为它仰望您能按一定的一一来操作吗?其实是因为它违反了无状态的准绳。有广大不信守无状态原则的案例,例如3-Legged
OAuth,API调用速度限制等。但要么要硬着头皮确保服务器中不要求在多少个请求下保持利用状态。

可缓存

  在万维网上,客户端可以缓存页面的响应内容。由此响应都应隐式或显式的概念为可缓存的,若不足缓存则要防止客户端在一而再呼吁后用旧数据或脏数据来响应。管理得当的缓存会部分地或完全地除了客户端和服务端之间的互相,进一步改革质量和延展性。

C-S架构

  统一接口使得客户端和服务端相互分开。关心分离意味什么?打个倘若,客户端不须求仓储数据,数据都留在服务端内部,那样使得客户端代码的可移植性拿到了提拔;而服务端不须求考虑用户接口和用户情况,那样一来服务端将越是简约易拓展。只要接口不更改,服务端和客户端可以单独地举办研发和替换。

分层系统

  客户端平时不能申明本人是一贯恐怕直接与端服务器举办连接。中介服务器可以经过启用负载均衡或提供共享缓存来进步系统的延展性。分层时同样要考虑安全策略。

按需编码(可选)

  服务端通过传输可举办逻辑给客户端,从而为其目前拓展和定制功用。相关的例子有编译组件Java
applets和客户端脚本JavaScript。

  遵循上述标准,与REST架构风格保持一致,能让各个分布式超媒连串统有着梦想的自然属性,比如高质量,延展性,简洁,可变性,可视化,可移植性和可信赖性。

  指示:REST架构中的设计准则中,唯有按需编码为可选项。若是有些服务违反了别样随意一项准则,严谨意思上不大概称之为RESTful风格。

 

REST飞速指示

  (依照地点提到的多少个标准化)不管在技术上是还是不是RESTful的,那里有一对近似REST概念的指出。遵守它们,可以兑现更好、更管用的服务:

采纳HTTP动词表示一些意思

  任何API的使用者能够发送GET、POST、PUT和DELETE请求,它们很大程度明显了所给请求的目的。同时,GET请求不可以改变任何秘密的财富数量。测量和跟踪仍大概发生,但只会更新数据而不会更新由UOdysseyI标识的财富数量。

理所当然的财富名

  合理的财富名称或者路径(如/posts/23而不是/api?type=posts&id=23)可以更鲜惠氏(WYETH)个请求的目的。使用ULX570L查询串来过滤数据是很好的法门,但不应当用于固定财富名称。

  适当的资源名称为服务端请求提供上下文,扩展服务端API的可精通性。通过U奇骏I名称分层地翻看能源,可以给使用者提供多个祥和的、简单领悟的能源层次,以在她们的应用程序上应用。财富名称应当是名词,防止为动词。使用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方法成立能源时,还足以行使头地点包蕴3个链接。对于响应中协理分页的聚集,”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)请求仅用于读取数据而不更改多少。由此,那种使用办法被认为是平安的。相当于说,它们的调用没有数据修改或污染的风险——调用一回和调用拾2回依然没有被调用的职能等同。其余,GET(以及HEAD)是幂等的,这意味着使用多少个一律的请求与使用单个的央浼最终都持有相同的结果。

  不要通过GET暴光不安全的操作——它应当永远都无法改改服务器上的其他能源。

PUT

  PUT常常被用于更新能源。通过PUT请求3个已知的财富U奥迪Q5I时,需求在伸手的body中富含对原来能源的换代数据。

  不过,在能源ID是由客服端而非服务端提供的景观下,PUT同样可以被用来创立财富。换句话说,如若PUT请求的UKoleosI中带有的能源ID值在服务器上不存在,则用于创制能源。同时请求的body中务必带有要创立的财富的多少。有人觉得这会发生歧义,所以唯有真的必要,使用这种措施来创设能源应该被慎用。

  可能我们也得以在body中提供由客户端定义的财富ID然后使用POST来创制新的财富——假使请求的UCRUISERI中不包括要创建的财富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不是1个有惊无险的操作,因为它会修改(或创建)服务器上的情状,但它是幂等的。换句话说,借使你接纳PUT成立大概更新能源,然后再次调用,财富依然存在并且状态不会发生变化。

  例如,借使在财富增量计数器中调用PUT,那么这几个调用方法就不再是幂等的。这种景色有时候会暴发,且只怕可以表明它是非幂等性的。然则,提议维持PUT请求的幂等性。并强烈提议非幂等性的呼吁使用POST。

POST

  POST请求常常被用来创建新的能源,尤其是被用来创建从属财富。从属能源即归属于其它能源(如父财富)的能源。换句话说,当创造2个新能源时,POST请求发送给父能源,服务端负责将新能源与父财富拓展关联,并分配一个ID(新财富的U翼虎I),等等。

  例如:

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

  当创设成功时,再次来到HTTP状态码201,并顺便3个岗位头消息,其中涵盖指向起先成立的能源的链接。

  POST请求既不是安全的又不是幂等的,因而它被定义为非幂等性财富请求。使用五个相同的POST请求很大概会造成创造多少个带有相同音讯的能源。

PUT和POST的始建相比较

  总而言之,大家提出采取POST来创建财富。当由客户端来支配新能源有着如何URAV4I(通过能源名称或ID)时,使用PUT:即只要客户端知道UHighlanderI(或财富ID)是怎么,则对该U兰德酷路泽I使用PUT请求。否则,当由服务器或服务端来控制成立的财富的UPAJEROI时则使用POST请求。换句话说,当客户端在开创之前不亮堂(或不能知晓)结果的UEvoqueI时,使用POST请求来创造新的财富。

DELETE

  DELETE很简单精晓。它被用来依据U奥德赛I标识删除资源。

  例如:

  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操作是幂等的。若是您对1个能源拓展DELETE操作,财富就被移除了。在能源上反复调用DELETE最后促成的结果都同一:即财富被移除了。但假如将DELETE的操功效于计数器(能源内部),则DETELE将不再是幂等的。如前方所述,只要数据没有被更新,统计和测量的用法如故可被认为是幂等的。提出非幂等性的财富请求使用POST操作。

  可是,那里有多个关于DELETE幂等性的警告。在3个能源上第2、回调用DELETE往往会回来404(未找到),因为该财富已经被移除了,所以找不到了。那使得DELETE操作不再是幂等的。如若财富是从数据库中剔除而不是被简单地标记为除去,那种情况需求相当让步。

  下表计算出了严重性HTTP的不二法门和资源U兰德索罗德I,以及推荐的再次来到值:

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创制能源UHighlanderL时,那里有一部分小技巧值得借鉴。

  从实质上讲,两个RESTFul
API最后都得以被略去地看成是一堆UMuranoI的汇聚,HTTP调用那一个ULANDI以及部分用JSON和(或)XML表示的能源,它们中有无数含有了相互关联的链接。RESTful的可寻址能力根本依靠ULANDI。各种能源都有友好的地点或USportageI——服务器能提供的每三个立见功能的音讯都可以作为财富来公开。统一接口的尺码部分地由此U福睿斯I和HTTP动词的三结合来消除,并符合利用规范和约定。

  在决定你系统中要采纳的能源时,使用名词来命名这么些财富,而不是用动词或动作来定名。换句话说,二个RESTful
U锐界I应该提到到1个具体的能源,而不是关乎到壹个动作。其余,名词还装有局地动词没有的习性,那也是另几个肯定的因素。

  一些财富的例子:

  • 系统的用户
  • 学员注册的教程
  • 三个用户帖子的日子轴
  • 关心其余用户的用户
  • 一篇关于骑马的篇章

  服务套件中的各个能源最少有三个U奇骏I来标识。假如这一个U库罗德I能表示一定的含义并且可以丰裕描述它所表示的能源,那么它就是几个最好的命名。URI应该享有可预测性和分支结构,那将助长坚实它们的可领悟性和可用性的:可预测指的是能源应该和名称保持一致;而分层指的是数据具有关系上的结构。那并非REST规则或正规,可是它加重了对API的概念。

  RESTful
API是提须要消费端的。U酷路泽I的名称和协会应当将它所抒发的意思传达给消费者。寻常大家很难知晓数码的境界是如何,但是从你的多寡上您应有很有只怕去品味找到要回到给客户端的数量是何等。API是为客户端而规划的,而不是为你的数码。

  假如我们今天要描述二个囊括客户、订单,列表项,产品等职能的订单系统。考虑一下大家该怎么着来讲述在那一个服务中所涉及到的财富的UPAJEROIs:

资源URI示例

  为了在系统中插入(创立)多少个新的用户,大家可以动用:

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

 

  读取编号为33245的用户音讯:

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

  使用PUT和DELETE来请求相同的U奥德赛I,可以革新和删除数据。

 

  上面是对成品有关的U奥迪Q7I的部分提议:

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

  用于创建新的成品。

 

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

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

 

  那么,如何为用户创立三个新的订单呢?

  一种方案是:

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

  那种艺术得以用来创立订单,但缺乏相应的用户数量。

  

  因为大家想为用户成立多个订单(注意之间的涉嫌),那个U陆风X8I或然不够直观,上面这几个UEvoqueI则更鲜明一(Wissu)些:

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

  现在大家领会它是为编号33245的用户创设3个订单。

 

  那上面那个请求重临的是如何啊?

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

  大概是八个数码为33245的用户所开创或富有的订单列表。注意:我们得以屏蔽对该U普拉多I举办DELETE或PUT请求,因为它的操作对象是三个成团。

 

  继续长远,那上边这几个U卡宴I的呼吁又表示怎样吗?

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

  只怕是(为编号33245的用户)增添壹个数码为8769的订单条目。没错!如若拔取GET格局呼吁那一个U奥迪Q5I,则会再次回到这几个订单的保有条条框框。可是,如果那几个条款与用户音信毫无干系,大家将会提供POST
www.example.com/orders/8769/lineitems
这个URI。

  从重返的这一个条款来看,指定的能源或许会有两个U逍客Is,所以大家大概也须要要提供这么贰个U瑞鹰I
GET
http://www.example.com/orders/8769
,用来在不了解用户ID的意况下基于订单ID来查询订单。

 

  更进一步:

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

  只怕只回去同个订单中的第叁,个条目。

  今后您应有知道什么是分层结构了。它们并不是严苛的平整,只是为着确保在你的劳务中这个强制的布局可以更易于被用户所明白。与持有软件开发中的技能一样,命名是打响的基本点。

  

  多看有的API的言传身教并学会控制那个技巧,和您的队友一起来周密你API能源的U牧马人Is。那里有一些APIs的例子:

能源命名的反例

  前边大家早就探究过一些恰如其分的财富命名的事例,可是有时一些反面的例子也很有教育意义。上边是一些不太具有RESTful风格的财富U奥德赛Is,看起来相比散乱。那几个都以不当的例子! 

  首先,一些serivices往往拔取单一的U安德拉I来指定服务接口,然后通过查询参数来指定HTTP请求的动作。例如,要更新编号12345的用户消息,带有JSON
body的哀求可能是那般:

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

  就算地点U路虎极光L中的”services”的那个节点是三个名词,但这几个UCRUISERL不是自解释的,因为对此全数的伸手而言,该UEscortI的层级结构都以一模一样的。其余,它应用GET作为HTTP动词来执行2个翻新操作,这大致就是反人类(甚至是危险的)。

  上面是此外贰个翻新用户的操作的例证:

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

  以及它的一个变种:

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

  你会日常见到在其他开发者的服务套件中有过多这么的用法。可以看到,这几个开发者试图去成立RESTful的能源名称,而且已经有了部分前进。但是你依旧可以辨识出U讴歌RDXL中的动词短语。注意,在这么些ULANDL中大家不需要”update”那么些词,因为我们能够依靠HTTP动词来达成操作。上边这几个U昂科拉L正好表达了那或多或少:

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

  那一个请求同时存在PUT和”update”,那会对消费者爆发迷惑!那里的”update”指的是3个财富吗?由此,这里大家费些口舌也是梦想您可见知道……

复数

  让我们来商量一下复数和“单数”的争议…还没传说过?但那种争议确实存在,事实上它可以归纳为那么些题材……

  在您的层级结构中U瑞虎I节点是还是不是要求被命名为单数或复数方式呢?举个例证,你用来寻找用户财富的UGL450I的命名是还是不是需求像下边这样:

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

  或者:

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

  三种方法都没难题,但常见我们都会拔取使用复数命名,以使得你的API
U瑞虎I在全数的HTTP方法中保持一致。原因是基于那样一种考虑:customers是劳动套件中的多少个会面,而ID33245的这几个用户则是以此集合中的其中壹个。

  依据这几个规则,三个应用复数方式的多节点的U安德拉I会是这么(注意粗体部分):

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

  “customers”、“orders”以及“lineitems”那么些URI节点都采用的是复数格局。

  那象征你的各样根能源只要求七个核心的U福特ExplorerL就足以了,一个用来创建集合内的资源,另1个用来依照标识符获取、更新和删除财富。例如,以customers为例,创立能源可以利用上面的UTucsonL举办操作:

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

  而读取、更新和删除能源,使用下边的U大切诺基L操作:

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

  正如前方提到的,给定的财富或然有五个UCRUISERI,但作为一个小小的的完全的增删改查功能,利用多个不难的U兰德ENVISIONI来处理就够了。

  只怕你会问:是不是在有点情状下复数没有意义?嗯,事实上是那般的。当没有集合概念的时候(此时复数没有意义)。换句话说,当能源唯有多个的图景下,使用单数财富名称也是可以的——即2个纯粹的财富。例如,尽管有三个纯净的完好布置能源,你可以行使多少个单数名称来代表:

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

  注意那里紧缺configuration的ID以及HTTP动词POST的用法。假诺每一个用户有贰个配备来说,那么这些U中华VL会是那样:

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

  通过那种艺术,在U昂科拉I中指定再次回到表征的格式,可以增加U昂科雷L的可知性。例如,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头,服务端要同时资助封装和未封装的响应,你不可以不贯彻自定义的类型——因为那些格式不是规范的门类。那大大伸张了客户端和服务端的纷纭。请参见卡宴FC
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应该是可用和可驾驭的。约等于说,3个API应当可以因此其链接导航到数码的逐一部分。不提出只回去纯数据。

  可是当下的业界先驱们并不曾平时应用那种做法,这反映了HATEOAS仅仅在成熟度模型中的使用率更高。纵观者多的服务连串,它们基本上重回更加多的数额,而回到的链接却很少(或然没有)。那是反其道而行之Fielding的REST约定的。Fielding说:“消息的每1个可寻址单元都教导二个地址……查询结果应当呈现为2个含有摘要音讯的链接清单,而不是目的数组。”

  另一方面,简单严酷地将全部链接集合重返会大大影响网络带宽。在实际上意况中,依照所需的尺码或利用情形,API接口的通讯量要依据服务器响应Chinese Football Association Super League文本链接所蕴涵的“摘要”数量来平衡。

  同时,丰盛利用HATEOAS恐怕会扩张完成的复杂性,并对劳动客户端发生显然的担当,这一定于降低了客户端和服务器端开发人员的生产力。因此,当务之急是要平衡超链接服务推行和现有可用财富之间的题材。

  超链接最小化的做法是在最大限度地减少客户端和服务器之间的耦合的同时,提升服务端的可用性、可操纵性和可明白性。那几个最小化提出是:通过POST成立财富并从GET请求再次回到集合,对于有分页的气象前面大家会提到。

小小化链接推荐

  在create的用例中,新建能源的U陆风X8I(链接)应该在Location响应头中回到,且响应核心是空的——可能只包括新建能源的ID。

  对于从服务端重返的表征集合,每一个表征应该在它的链接集合中率领3个小小的“本身”链接属性。为了方便分页操作,其余的链接可以置身一个单身的链接集合中回到,须要时可以包罗“第三页”、“上一页”、“下一页”、“最终一页”等音信。

  参照下文链接格式一部分的例证获取越多音讯。

链接格式

  参照整个链接格式的正式,提出遵循一些像样Atom、AtomPub或Xlink的风骨。JSON-LD也不易,但并不曾被大规模运用(倘使已经被用过)。近年来业内最常见的主意是采用带有”rel”成分和包蕴能源总体U凯雷德I的”href”成分的Atom链接格式,不含有其他身份验证或询问字符串参数。”rel”成分得以包含标准值”alternate”、”related”、”self”、”enclosure”和”via”,还有分页链接的“第3页”、“上一页”、“下一页”,“最终一页”。在须要时得以自定义并加上应用它们。

  一些XML
Atom格式的概念对于用JSON格式表示的链接来说是船到江心补漏迟的。例如,METHOD属性对于三个RESTful能源来说是不须要的,因为对此三个加以的财富,在享有帮助的HTTP方法(CRUD行为)中,财富的UPRADOI都以一模一样的——所以单独列出这几个是未曾要求的。

  让我们举一些切实的例证来越发验证那或多或少。上面是调用创立新资源的央浼后的响应:

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

  上边是响应头集合中蕴藏创建新能源的U卡宴I的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集合;另1个则是三个独门的对象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)标准,它可以包蕴消息号或然编码,可以只包罗其中3个,大概同时涵盖并用分隔符隔开。
  • data——包罗响应的body。当状态值为”fail”或”error”时,data仅包括错误原因或特别名称。

  下边是1个回到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和跨域财富共享(CO奥迪Q3S)。JSONP或“填充的JSON”是一种选择格局,它提供了3个办法请求来自差异域中的服务器的多少。其工作方法是从服务器再次回到任意的JavaScript代码,而不是JSON。客户端的响应由JavaScript解析器举办解析,而不是直接解析JSON数据。其余,COLANDS是一种web浏览器的技能专业,它为web服务器定义了一种艺术,从而允许服务器的财富得以被不一样域的网页访问。CO奥迪Q5S被看成是JSONP的风行替代品,并且可以被抱有现代浏览器接济。由此,不指出利用JSONP。任何情状下,推荐采用CO凯雷德S。

支持CORS

  在服务端已毕CO福睿斯S很简短,只须要在发送响应时顺手HTTP头,例如: 

Access-Control-Allow-Origin: *

  唯有在多少是国有使用的情状下才会将做客来源设置为”*”。一大半气象下,Access-Control-Allow-Origin头应该指定哪些域可以倡导三个CO纳瓦拉S请求。唯有要求跨域访问的U瑞虎L才设置CO宝马X5S头。

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服务器上布置二个用空格分隔的域的列表。愈来愈多关于COSportageS的内容可以参见那里:http://enable-cors.org/

支持JSONP

  JSONP通过应用GET请求避开浏览器的限定,从而完结对全体服务的调用。其行事原理是请求方在伸手的U昂科威L上添加3个字符串查询参数(例如:jsonp=”jsonp_callback”),其中“jsonp”参数的值是JavaScript函数名,该函数在有响应重回时将会被调用。

  由于GET请求中没有包蕴请求体,JSONP在使用时有着严重的局限性,由此数据必须通过字符串查询参数来传递。同样的,为了匡助PUT,POST和DELETE方法,HTTP方法必须也由此字符串查询参数来传递,类似_method=POST那种方式。像这么的HTTP方法传送方式是不推荐使用的,那会让服务处于安全风险之中。

  JSONP寻常在有个别不支持CO奔驰G级S的老旧浏览器中应用,即使要改成帮忙CO瑞鹰S的,会潜移默化全部服务器的架构。或然大家也得以通过代办来兑现JSONP。由此可见,JSONP正在被CO昂科威S所代表,大家相应尽量地动用CO路虎极光S。

  为了在服务端帮忙JSONP,在JSONP字符串查询参数传递时,响应必须求实践以下那个操作:

  1. 响应体必须封装成3个参数传递给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寻常只好展现大数额集中的一小部分数额。在数据集的增进速度不显然的状态下,限制默许重返的数据量是很有必不可少的。以推文(Tweet)为例,要拿到某些用户的推文(通过个人主页的日子轴),假使没有越发指定,请求私行认同只会重返20条记下,即便系统最多可以回来200条记下。

  除了限制重临的数据量,我们还须要考虑什么对时局据集进行“分页”或下拉滚动操作。成立数量的“页码”,重回大数量列表的已知片段,然后标出数据的“前一页”和“后一页”——这一行事被叫作分页。其余,我们只怕也急需指定响应大校包蕴怎么样字段或性质,从而限制重回值的多寡,并且大家盼望最终可以由此特定值来进展查询操作,并对重回值举行排序。

  有二种主要的方式来还要限制查询结果和施行分页操作。首先,大家得以创设三个目录方案,它可以以页码为导向(请求中要提交每一页的记录数及页码),恐怕以记录为导向(请求中一向付出第壹条记下和末段一条记下)来规定再次来到值的原初地点。举个例子,那三种方法分别表示:“给出第⑥页(如若每页有20条记下)的笔录”,或“给出第70到第220条的记录”。

  服务端将基于运作机制来展开切分。有个别UI工具,比如Dojo
JSON会拔取模仿HTTP规范应用字节范围。假诺服务端支持out of
box(即开箱即用成效),则前端UI工具和后端服务中间无需任何转换,那样使用起来会很便宜。

  下文将介绍一种艺术,既可以辅助Dojo那样的分页情势(在请求头中付出记录的范围),也能帮忙选择字符串查询参数。那样一来服务端将变得更为灵活,既可以动用类似Dojo一样先进的UI工具集,也足以拔取简便直接的链接和标签,而无需再为此增加复杂的支出工作。但只要服务不直接协理UI功用,可以考虑不要在请求头中付出记录范围。

  要尤其指出的是,大家并不推荐在颇具服务中采纳查询、过滤和分页操作。并不是有着能源都暗中同意资助那些操作,唯有某个特定的财富才支撑。服务和财富的文档应当表明如何接口协理这么些纷纷的效率。

结果限制

  “给出第壹到第45条的笔录”,那种请求数据的法门和HTTP的字节范围规范更平等,由此大家得以用它来标识Range
header。而“从第三,条记下早先,给出最多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条记下。

  而在服务端,通过检查请求的Range
header来显然该再次回到哪些记录。只要Range
header存在,就会有三个几乎的正则表明式(如”items=(\d+)-(\d+)”)对其开展解析,来博取要寻找的范围值。

用字符串查询参数进行限制

  字符串查询参数被作为Range
header的替代采纳,它接纳offset和limit作为参数名,其中offset代表要查询的首先条记下编号(与上述的用来范围标记的items第2个数字相同),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

  在大部场合下,那种分页方式都不曾难题。但偶尔会有那种情景,就是要赶回的笔录数据不或然间接表示成多少集中的行号。还有就是有个别数据集的更动很快,不断会有新的数据插入到数码集中,那样自然会招致分页现身难题,一些重新的数目大概会现出在不相同的页中。

  按日期排列的数据集(例如推特(TWTR.US)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)。

  通过引入一组广泛的、公认的分隔符,用于过滤的表明式可以以非凡直观的款型被应用。用那么些分隔符来设置过滤查询参数的值,那几个分隔符所创制的参数名/值对可以越来越便于地被服务端解析并坚实多少查询的天性。近日已有的分隔符包含用来分隔每种过滤短语的竖线(”|”)和用来分隔参数名和值的双冒号(”::”)。那套分隔符充足唯1、并符合一大半动静,同时用它来营造的字符串查询参数也特别不难通晓。上面将用3个简单易行的例证来介绍它的用法。假使大家想要给名为“托德”的用户们发送请求,他们住在圣路易斯,有着“Grand
Poobah”之称。用字符串查询参数落成的呼吁U奥迪Q5I如下:

  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举行版本化管理是防止那种根本变化的一种有效办法。

通过内容协商支持版本管理

  今后,版本管理通过UOdysseyI本身的版本号来完毕,客户端在乞请的UPRADOI中标明要赢得的能源的版本号。事实上,许多大商厦如Twitter、Yammer、脸谱、谷歌等平常在她们的UPAJEROI里使用版本号。甚至像WSO2那样的API管理工具也会在它的U猎豹CS6Ls中须求版本号。

  面向REST原则,版本管理技术神速发展。因为它不含有HTTP规范中放置的header,也不接济仅当壹个新的能源或概念被引入时才应该添加新U卡宴I的见解——即版本不是表现方式的变化。另一个唱对台戏的理由是能源UCR-VI是不会随时间改变的,能源就是财富。

  U牧马人I应该能简单地辨识财富——而不是它的“形状”(状态)。另一个就是必须指定响应的格式(表征)。还有一部分HTTP
headers:Accept 和 Content-Type。Accept
header允许客户端指定所企望或能帮助的响应的传媒类型(一种或各种)。Content-Type
header可分别被客户端和劳动端用来指定请求或响应的多少格式。

  例如,要获得2个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被用来表示所期待的响应格式(以及示例中的版本号),注意上述多个一样的U奥德赛I是何许完结在区其余本子中分辨财富的。大概,若是客户端要求三个XML格式的数量,可以将Accept
header设置为”application/xml”,假使需求的话也得以带3个点名的版本号。

  由于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格式请求三个包涵多版本财富的服务器,来创立3个新用户(预期会回到版本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还应该重返3个涵盖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”的值
  • 在现有的工作流中引入需要能源
  • 更改财富的定义/意图;概念/意图或财富景况的意义差异于它原本的意思。例如:
    • 2个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来拉长响应

  可选。见普拉多DF(Resource Description Framework,即财富描述框架)规范。

带有Content-Type的链接

  Atom风格的链接帮衬”type”属性。提供丰裕的音讯以便客户端能够对特定的版本和故事情节类型进行调用。

找出匡助的本子

自我应当同时帮忙多少个本子?

  维护多少个例外的本子会让劳作变得繁琐、复杂、不难失误,而且代价高,对于其他给定的能源,你应当协理不当先一个版本。

弃用

  Deprecated(弃用)的目的是用来表明能源对API依旧可用,但在今后会不存在并变得不可用。只顾:弃用的时长将由弃用政策决定——那里并没有提交定义。

自身什么告知客户端被弃用的能源?

  许多客户端现在造访的能源或许在新本子引入后会被扬弃掉,因而,他们须要有一种艺术来发现和监察他们的应用程序对弃用财富的施用。当呼吁一个弃用财富时,API应该健康响应,并带有3个布尔类型的自定义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内容中的日期/时间种类化

  有1个简约的法门可以消除那几个难点——在字符串中一向用同样的格式,蕴含时间片(带有时区音讯)。ISO8601时间格式是3个不易的解决方案,它使用了一心增强的岁月格式,包罗小时、分钟、秒以及秒的小数部分(例如yyyy-MM-dd’T’HH:mm:ss.SSS’Z’)。提出在REST服务的body内容中(请求和响应均包含)使用ISO8601代表全体的日子格式。

  顺便提一下,对于那几个基于JAVA的服务以来,DateAdapterJ库使用DateAdapter,Iso8601TimepointAdapter和HttpHeaderTimestampAdapter类可以格外不难地解析和格式化ISO86017日期和时间,以及HTTP
1.1
header(中华VFC1123)格式。能够从https://github.com/tfredrich/DateAdapterJ下载。

  对于那么些创制基于浏览器的用户界面来说,ECMAScript5正规一开端就富含了JavaScript解析和创建ISO860三十日期的内容,所以它应该成为大家所说的主流浏览器所遵守的办法。当然,假诺你要协助那多少个不或然自动解析日期的旧版浏览器,可以接纳JavaStript库或正则表达式。那里有多少个可以分析和创造ISO8601时间的JavaStript库:

  http://momentjs.com/

  http://www.datejs.com/

HTTP Headers中的日期/时间连串化

  不过上述提出仅适用于HTTP请求或响应内容中的JSON和XML内容,HTTP规范针对HTTP
headers使用另一种不一样的格式。在被牧马人FC1123更替的福特ExplorerFC822中指出,该格式包涵了各个日期、时间和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. 若果授权通过了,服务器将会继续健康运作。

  上边第2步的支付大概会相比大,然而如若尽管存在二个可缓存的权能决定列表(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。

授权

  对服务的授权和对别的应用程序的授权一样,没有其余不相同。它依据那样一个题材:“主体是还是不是对给定的资源有请求的许可?”那里给出了简便的三项数据(主体,财富和认可),由此很简单构造一个支持那种概念的授权服务。其中大旨是被赋予财富访问许可的人或系统。使用那几个相似概念,就足以为每3个主旨营造一个缓存访问控制列表(ALC)。

应用程序安全

  对RESTful服务以来,开发2个康宁的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

响应重回的日子和岁月(奥迪Q3FC1123格式)。

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

Cache-Control

响应可被缓存的最大秒数(最大age值)。借使响应不援救缓存,值为no-cache。

Cache-Control: 360

Cache-Control: no-cache

Expires

假使给出了最大age值,该时间戳(劲客FC1123格式)表示的是响应过期的光阴,也等于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

财富本人最终被改动的时日戳(CR-VFC1123格式)。

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

  为了简化,那里举1个响应中的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

  上面是1个近乎的例子,不过缓存被全然禁用:

  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)
—— 无论能源存不存在,无论是或不是有40一,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地图