REST架构风格描述了六个约束。应用于体系结构的这些约束最初由Roy Fielding在他的博士论文中传达(参见https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm),并定义了RESTful的基础 -样式。
六个约束是:(单击约束以阅读更多)
统一接口约束定义了客户端和服务器之间的接口。它简化并解耦了架构,使每个部件都能独立发展。统一界面的四个指导原则是:
使用URI作为资源标识符在请求中标识各个资源。资源本身在概念上与返回给客户端的表示分开。例如,服务器不发送其数据库,而是发送一些表示某些数据库记录的HTML,XML或JSON,例如,用芬兰语表示并以UTF-8编码,具体取决于请求的详细信息和服务器实现。
当客户端持有资源的表示(包括附加的任何元数据)时,它有足够的信息来修改或删除服务器上的资源,前提是它有权这样做。
每条消息都包含足够的信息来描述如何处理消息。例如,要调用的解析器可以由Internet媒体类型(以前称为MIME类型)指定。响应还明确指出了它们的缓存能力。
客户端通过正文内容,查询字符串参数,请求标头和请求的URI(资源名称)来提供状态。服务通过正文内容,响应代码和响应标头向客户提供状态。这在技术上被称为超媒体(或超文本中的超链接)。
除了上面的描述之外,HATEOS还意味着,在必要时,链接包含在返回的正文(或标题)中,以提供用于检索对象本身或相关对象的URI。我们稍后会详细讨论这个问题。
任何REST服务必须提供的统一接口是其设计的基础。
由于REST是REpresentational State Transfer的首字母缩写,无国籍是关键。本质上,这意味着处理请求的必要状态包含在请求本身中,无论是作为URI,查询字符串参数,正文还是标题的一部分。URI唯一标识资源,主体包含该资源的状态(或状态更改)。然后,在服务器进行处理之后,通过标头,状态和响应主体将适当的状态或重要状态的片断传送回客户端。
我们大多数已经在业界工作了一段时间的人习惯于在容器内编程,这为我们提供了“会话”的概念,它在多个HTTP请求中维护状态。在REST中,客户端必须包含服务器的所有信息以完成请求,如果该状态必须跨越多个请求,则根据需要重新发送状态。无状态可以实现更高的可伸缩性,因为服务器不必维护,更新或传递该会话状态。此外,负载均衡器不必担心无状态系统的会话亲和性。
那么状态和资源之间的区别是什么?状态或应用程序状态是服务器关心的,以满足当前会话或请求所需的请求数据。资源或资源状态是定义资源表示的数据 - 例如,存储在数据库中的数据。将应用程序状态视为可能因客户端和每个请求而异的数据。另一方面,资源状态在请求它的每个客户端都是不变的。
曾经有一个Web应用程序的后退按钮问题,因为它希望您按特定顺序执行某些操作,因此它在某个时刻出现了AWOL吗?那是因为它违反了无国籍原则。有些情况不符合无状态原则,例如三脚OAuth,API调用率限制等。但是,尽一切努力确保应用程序状态不会跨越您的多个服务请求。
与万维网一样,客户端可以缓存响应。因此,响应必须隐式或显式地将自身定义为可缓存或不可缓存,以防止客户端重用陈旧或不适当的数据以响应进一步的请求。管理良好的缓存部分或完全消除了一些客户端 - 服务器交互,进一步提高了可伸缩性和性能。
统一接口将客户端与服务器分开。这种关注点分离意味着,例如,客户端不关心数据存储,数据存储仍然是每个服务器的内部,从而提高了客户端代码的可移植性。服务器不关心用户界面或用户状态,因此服务器可以更简单,更具可伸缩性。只要不改变接口,服务器和客户端也可以独立替换和开发。
客户端通常无法判断它是直接连接到终端服务器,还是沿途的中介。中间服务器可以通过启用负载平衡和提供共享缓存来提高系统可伸缩性。图层也可以实施安全策略。
服务器能够通过向客户端传输可以执行的逻辑来临时扩展或自定义客户端的功能。这样的示例可以包括编译的组件,例如Java applet和客户端脚本,例如JavaScript。
遵守这些约束,从而符合REST架构风格,将使任何类型的分布式超媒体系统具有理想的紧急属性,例如性能,可伸缩性,简单性,可修改性,可见性,可移植性和可靠性。
注意: REST架构的唯一可选约束是按需代码。如果服务违反任何其他约束,则不能严格地将其称为RESTful。
无论技术上是REST还是不(根据前面提到的六个约束条件),这里有一些推荐的类似REST的概念。这六个快速提示将带来更好,更实用的服务。
API使用者能够发送GET,POST,PUT和DELETE动词,这极大地增强了给定请求的清晰度。
通常,四个主要的HTTP谓词使用如下:
GET
读取特定资源(通过标识符)或资源集合。
PUT
更新特定资源(通过标识符)或资源集合。如果资源标识符是事先已知的,也可以用于创建特定资源。
DELETE
通过标识符删除/删除特定资源。
POST
创建一个新资源。对于不适合其他类别的操作,也是一个包罗万象的动词。
GET请求不得更改任何底层资源数据。可能仍会发生更新数据的测量和跟踪,但URI标识的资源数据不应更改。
制作出色的API是80%的艺术和20%的科学。创建表示合理资源的URL层次结构是艺术部分。拥有合理的资源名称(只是URL路径,例如/ customers / 12345 / orders)可以提高给定请求的清晰度。
适当的资源名称为服务请求提供上下文,从而提高API的可理解性。通过URI名称对资源进行分层查看,为消费者提供友好,易于理解的资源层次结构,以便在其应用程序中使用。
以下是一些URL路径(资源名称)设计的快速规则:
响应状态代码是HTTP规范的一部分。它们中有很多可以解决最常见的情况。本着使RESTful服务包含HTTP规范的精神,我们的Web API应该返回相关的HTTP状态代码。例如,当成功创建资源时(例如,从POST请求),API应返回HTTP状态代码201. 此处提供了有效HTTP状态代码列表,其列出了每个代码的详细描述。
“十大”HTTP响应状态代码的建议用法如下:
200好的
一般成功状态代码。这是最常见的代码。用于表示成功。
201创建
成功创建(通过POST或PUT)。将Location标头设置为包含指向新创建的资源的链接(在POST上)。响应主体内容可能存在也可能不存在。
204 NO CONTENT
表示成功,但响应正文中没有任何内容,通常用于DELETE和PUT操作。
400 BAD REQUEST
完成请求时的一般错误会导致无效状态。域验证错误,缺少数据等是一些示例。
401未经授权
错误代码响应丢失或无效的身份验证令牌。
403 FORBIDDEN
当用户未被授权执行操作或资源由于某种原因(例如时间限制等)不可用时的错误代码。
404未找到
在找不到请求的资源时使用,是否不存在,或者是否存在401或403,出于安全原因,服务想要屏蔽。
405方法不允许
用于指示请求的URL存在,但请求的HTTP方法不适用。例如,POST / users / 12345,其中API不支持以这种方式创建资源(使用提供的ID)。返回405时必须设置Allow HTTP标头以指示支持的HTTP方法。在前一种情况下,标题看起来像“允许:GET,PUT,DELETE”
409冲突
每当通过履行请求导致资源冲突时。重复条目,例如尝试创建具有相同信息的两个客户,以及在不支持级联删除时删除根对象,这是一些示例。
500内部服务器错误
永远不要故意归还。服务器端抛出异常时的常规catch-all错误。仅将此用于消费者无法解决的错误。
支持JSON支持,除非您处于高度标准化和受监管的行业,需要XML,模式验证和命名空间,并提供JSON和XML,除非成本是惊人的。理想情况下,让消费者使用HTTP Accept标头在格式之间切换,或者只是在URL上将.xml的扩展名更改为.json。
请注意,一旦我们开始讨论XML支持,我们就会开始讨论用于验证,命名空间等的模式。除非您的行业需要,否则请尽量避免支持所有这些复杂性。JSON旨在简化,简洁和实用。如果可以的话,让你的XML看起来像那样。
换句话说,使返回的XML更像JSON - 简单易读,不存在架构和命名空间细节,只有数据和链接。如果它最终比这更复杂,那么XML的成本将是惊人的。根据我的经验,过去几年没有人使用过XML响应,消费太昂贵了。
请注意,如果您需要这样的东西,JSON-Schema提供了架构式验证功能。
在开始时,最好创建模仿系统的底层应用程序域或数据库体系结构的API。最终,您将需要利用多个底层资源的聚合服务来减少干扰。但是,稍后从单个资源创建更大的资源比从更大的聚合创建细粒度或单个资源要容易得多。让自己轻松自如,从易于定义的小型资源开始,为这些资源提供CRUD功能。您可以稍后创建这些面向用例,减少chattiness的资源。
REST的原则之一是连通性 - 通过超媒体链接(搜索HATEOAS)。虽然没有它们,服务仍然有用,但在响应中返回链接时,API会变得更具自我描述性和可发现性。至少,“自我”链接引用会通知客户端如何检索数据。此外,利用HTTP Location标头包含通过POST(或PUT)创建资源的链接。对于在支持分页的响应中返回的集合,“first”,“last”,“next”和“prev”链接至少是非常有用的。
关于链接格式,有很多。HTTP Web链接规范(RFC5988)解释了如下链接:
链接是由国际化资源标识符(IRI)[ RFC3987 ] 标识的两个资源之间的类型连接,包括:链接可以被视为“{context IRI}在{target IRI}具有{relation type}资源的形式的声明,其具有{目标属性}。”
- 上下文IRI,
- 链接关系类型
- 目标IRI,和
- 可选地,目标属性。
至少,按照规范中的建议放置HTTP链接头中的链接,或者在JSON表示中包含此HTTP链接样式的JSON表示(例如Atom样式链接,请参阅:RFC4287)。之后,随着REST API变得更加成熟,您可以在更复杂的链接样式中进行分层,例如HAL + JSON,Siren,Collection + JSON和/或JSON-LD等。