RESTful服务至上实践

发布时间:2019-01-24  栏目:教育  评论:0 Comments

那是平日世界里的故事:
那是稀松平日的一天,阳光灿烂,整个蓝太虚莹剔透。人们行色匆匆。
那是干瘪一天中的8点,在熙熙攘攘的大巴上,有的人埋头看手机,有的人打着电话,有的人眯着眼睡觉,有的人被大块头挤在一个小角落。在另一个角落里,有一个男生,也有一个女人,他们遇见了。他们最终各自瞧着自己的无绳电话机,没有言语,自然不会有新故事。

本文首要读者

人们会因什么原因遇到一起?
又会因什么来头初阶率先次接触?

引言

人潮里亿百年不遇的票房价值,我们相遇了伙同。无论是在公众号,仍然微信,亦或者某天的某个时刻,大家发出了联合。

REST是什么

自己自己也暴发过局地故事,比如在二〇一〇年拍了百万点击率录像被领导者抓去教育,比如上学搭讪被100三个女子拒绝并搞起搭讪社,比如疯狂学习写代码多少个月却弄起了工作室赚钱,再比如未出去的间隔年、互联网产品经营课程等等。

  合并接口

实际,我特意惊叹每一件平凡的事体,也努力于成立分裂的体验,去考察和分享部分有味或干燥的作业。

    据悉资源

那是PM范儿那么些群众号的第三年。过去的两年,在此间埋头反思了众多办事相关的作业。在第三年,我接下去会起来搞事,搞事!

    通过特征来操作资源

PM范儿的新栏目:“好奇世界”。性感的人的有趣集结,让大家一齐玩些有趣的试验。

    自描述的新闻

好,开始率先次活动。

    超媒体即选择状态引擎(HATEOAS)

  • 举手投足内容

  无状态

我们都经历过形形色色的约会,聊过很多天,也总有静默狼狈的时候。假设某一天,相遇的三个寓目者,全程只用身体语言来维系表明,会时有暴发哪些的赛璐珞反应?所以这一次活动的名字为“只看脸的约会”。由于那是率先次,脚下日月我会亲自参预!

  可缓存

  • 运动地方:上海

  • 何以参预

  C-S架构

1.后台回复一张你以为能打动我的相片和微信号;
2.符合条件的童鞋会添加微信,被拉进一个故事屋(群);
3.在故事屋当中会公布需求共同加入的职务。

  分段系统

-活动时间

  按需编码(可选)

1.立春后的某一天,暂定2月8号。

REST火速提示

瞩望遇见你,搞事的眼前些天月。

  运用HTTP动词表示一些意义

公众号:PM范儿。

  成立的资源名

  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架构方式讲述了六种设计准则。那么些用于架构的规划准则,最早是由罗伊菲尔德(Field)ing在她的大学生小说中提议并定义了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)可以更简贝因美(Beingmate)(Nutrilon)(Beingmate)个伸手的目标。使用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则更鲜可瑞康(Karicare)些:

  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是什么”一节中也涉及过。

  依照罗伊(Roy)菲尔德(Field)ing在她的博客中的描述(http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertextdriven),REST接口中最关键的一对是超文本的拔取。别的,他还提出,在付给任何相关的新闻以前,一个API应该是可用和可见道的。也就是说,一个API应当可以透过其链接导航到数量的顺序部分。不提议只回去纯数据。

  不过当下的业界先驱们并从未平时采用这种做法,那反映了HATEOAS仅仅在成熟度模型中的使用率更高。纵观众多的服务连串,它们基本上再次来到愈来愈多的多寡,而回到的链接却很少(或者没有)。那是违反菲尔德(Field)ing的REST约定的。菲尔德(Field)ing说:“音信的每一个可寻址单元都带领一个地点……查询结果应当显示为一个包蕴摘要音讯的链接清单,而不是目的数组。”

  另一方面,简单惨酷地将一切链接集合重返会大大影响网络带宽。在事实上处境中,依据所需的尺码或使用情形,API接口的通信量要依据服务器响应中超(Chinese Football Association Super League)文本链接所涵盖的“摘要”数量来抵消。

  同时,丰硕利用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。此外一个提案是由道格拉斯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日常只好显示大数额集中的一小部分数量。在数据集的拉长速度不确定的情形下,限制默许重回的数据量是很有须要的。以推文(Tweet)为例,要得到某个用户的推文(通过个人主页的小时轴),假设没有越发指定,请求默许只会回去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

  在超过半数状态下,那种分页方式都小意思。但奇迹会有那种状态,就是要回来的笔录数据无法直接表示成多少集中的行号。还有就是有些数据集的转移很快,不断会有新的数据插入到多少集中,那样自然会造成分页出现问题,一些再度的数目也许会现出在区其余页中。

  按日期排列的数据集(例如Twitterfeed)就是一种常见的景况。尽管你还能对数据开展分页,但有时候用”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、谷歌等日常在她们的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提姆(Tim)epointAdapter和HttpHeader提姆estampAdapter类可以分外容易地解析和格式化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的Anti山姆my来对输出的数码进行编码。
  • 将新闻的长度限制在确定的字段长度内。
  • 劳务应该只突显一般的错误新闻。
  • 考虑工作逻辑攻击。例如,攻击者可以跳过多步骤的订座流程来预定产品而无需输入信用卡音讯呢?
  • 对怀疑的活动记录日志。

  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

留下评论