RESTful Web Services Cookbook——1,使用统一的接口

HTTPHypertext Transfer Protocol)是一种应用层级别的协议,它定义了客户端与服务器之间资源的转移表述(transferring representations)的许多操作,

  • 表述:是资源信息(状态、数据或标记) 的一种封装,使用诸如XML, JSON或HTML等格式进行编码,使用媒体类型进行标识。
  • 操作:诸如GET, POST, PUTDELETE之类的方法。

有了定义好的这些操作,就无须创造createOrder,、getStatus、updateStatus等特定的应用程序操作了。至于能从HTTP基础定义中受益多少,很大程度上取决于你把它当做应用层协议用得有多好。

然而,包括SOAP和一些Ajax Web框架在内的不少技术都将HTTP作为一种传输信息(transport messages)的协议,这种用法很难充分利用HTTP层的基础定义。

一,保持交互可见性

(一)什么是交互可见性

作为一种应用层协议,HTTP 旨在保持客户端与服务器对库、服务器、代理、缓存和其他工具的可见交互。这种可见性是HTTP的一个核心特征—— 一个组件能够对其他两个组件之间的交互进行 监视或仲裁的能力。

(二)交互可见性的意义

维持可见性使得开发人员可以使用现有的HTTP软件和基础定义来实现之前必须自己实现的功能,比如:

  • 缓存(Caching):缓存响应内容,并在资源修改时使缓存自动失效。
  • 乐观并发控制(Optimistic concurrency control):检测并发写入,并在操作过期的表述时防止资源发生变更。
  • 内容协商(Content negotiation):在给定资源的多个可用表述中, 选择合适的表述。
  • 安全性和幂等性:确保客户端可以重复或重试特定的HTTP请求。

当一个Web服务无法保持可见性时, 以上这些功能将无法正常工作。

(三)如何保持HTTP请求和响应的可见性

HTTP通过以下途径来实现可见性:

  • HTTP的交互是无状态(stateless)的,任何HTTP中介都可以推断出给定请求和响应的意义,而无须关联过去或将来的请求和响应。
  • HTTP 使用统一接口,接口中包含HTTP方法,每一个方法操作一个且仅有一个资源。 每个方法的语法和含义不会因应用程序或资源的不同而发生改变。http以统一接口而闻名于世。
  • HTTP 使用类似 MIME 的格式来编码表述。这种格式在头部(headers )和正文(body)之间保持清晰的分离。头部是可见的,除了创建消息的软件和处理消息的软件外,中间的每个软件都可以将正文视为完全不透明的。

(四)实例:一个更新资源的HTTP请求

在这里插入图片描述

  1. 请求行(request line):包含HTTP方法、资源路径和HTTP版本。
  2. 请求头(request headers):包含整个完整通信都需要用到的信息。Host指出请求的目的地(主机域名),Content-Type表示具体请求中的媒体类型信息。请求头后必须有一个空行。
  3. 请求正文(request body ):添加请求中的额外数据内容。
  4. 响应状态行(response status line):包含HTTP版本号、状态码、状态消息。
  5. 响应头(response headers):包含客户端可以使用的一些信息。Content-Length响应内容的长度。响应头后必须有一个空行。
  6. 响应正文(response body ):服务器返回给客户端的文本信息。

对于 RESTful Web 服务, 主要目标必须是尽最大可能保持可见性。

保持可见性非常简单

  • 使用HTTP方法时,其语义要与HTTP所规定的语义保持一致,并添加适当的头部来描述请求和响应。
  • 使用适当的状态码和状态消息,以便代理、缓存和客户端决定请求的结果。

在某些情况下, 可能需要权衡其他特性,如网络效率、客户端的便利性以及分离关注点而放弃可见性 当进行这种权衡时,应仔细分析对缓存、幂等性、安全性等特性的影响。

二,何时需要权衡可见性

可见性经常与其他架构要求相冲突, 如抽象(abstraction)、松耦合(loose coupling)、 效率(efficiency)和信息粒度(message granularity)等。

考虑一个“人” 资源与一个相关的“地址” 资源,任何客户端都可以提交一个 GET 请求得到这两个资源的表述,但为了方便客户端,服务器端可能会在“人” 的资源表述中包含“地址”资源,就像下面这样:
在这里插入图片描述

  • 这里使用Atom来设计XML格式的表述。

假设服务器允许客户端提交PUT请求更新这些资源。
当一个客户端修改了其中一个资源,相关资源的状态也会改变。然而,在HTTP层面上,这些是相互独立的资源。只有服务器才知道它们是相互依赖的。数据的重叠是降低可见性的常见原因。

可能需要为了下面这些情况,放弃可见性:

  • 客户端便利性:服务端为了客户端的方便,可能需要设计专用的粗粒度复合资源。
  • 抽象:为了抽象复杂的业务操作(包括事务),服务器可能需要使用控制器资源来改变其他资源。这样的资源可以隐藏业务操作的实现细节。
  • 网络效率:当客户端需要在短时间内连续执行几个操作时,可能需要将这些操作组合到一个批处理中,以降低网络延迟。

这些情况中,如果只关注可见性,Web服务就不得不设计成以无重叠的独立资源形式来显示所有数据。按这种方式设计的Web服务,可能导致资源粒度过细,客户端和服务器之间分离关注点(separation of concerns)不够。

其他场合包括复制或合并资源、部分更新,可能也需要权衡可见性。

三,如何维持应用状态

当在阅读关于REST时,经常得到这样的建议:在客户端保存应用状态(application state)。

(一)但什么是“应用状态”

考虑一个包含两个步骤的汽车保险购买应用:

  • 客户端提交一个带有司机和车辆细节信息的请求,服务器返回一个一周内有效的报价。
  • 客户端提交购买保险的请求,服务器生成保单。

在这个例子中,应用程序的状态就是报价。服务器需要知道从第一个步骤返回的报价,基于它才能给出第二个请求中的保单。

所以说,应用状态是服务器需要在每个客户端的每个请求之间维护的状态,这些状态记录了一系列请求之间的联系,正是因为这些联系的存在,才能完成一个又一个完整的业务操作。

(二)应当如何保存这些状态?

前面提到,HTTP是无状态协议’——每个请求与之前的请求都是独立的。
然而,交互性应用程序通常要求客户端执行时遵循特定顺序。这就要求服务器在协议之外暂时存储每个客户端在步骤序列里的当前位置。

将应用状态编码到URI里,并通过链接在表述中包含这些 URI ,就能让客户端使用这些 URI 与资源进行交互。

如果状态过大,或出于安全或隐私考虑不能在网络中传输,则可以在持久化存储(如数据库或文件系统)中存储应用状态,并将其状态的引用编码在URI中。

  • 应当选择形如数据库或文件系统的持久化存储(durable storage)来保存应用程序状态。使用缓存或内存会话(memory session)这样的非持久化存储会降低Web服务的可靠性,例如在服务器重启时状态可能会丢失,非持久化存储解决方案也会降低服务器的可扩展性。
  • 当在链接中保存应用程序状态时, 一定要加入一些检查方式(如signatures)来检测和防止伪造状态。

在这里插入图片描述

  1. 一个包含应用程序状态的链接。通过 rel 指定 href 里所填的 URL 和本网页间的关系。服务器把报价保存在数据存储里,并将主键编码在 URI 中。当客户端在本页面使用该 URI 发起请求购买保险时,服务器可以通过这个主键恢复该应用程序状态。

如果报价所需的数据量很小,服务器可以将状态编码在URI中:
在这里插入图片描述

因为客户端需要在每个请求中发回以上这些数据,在链接中编码应用程序状态会降低网络性能。
然而这样可以提高可扩展性,因为服务器不需要保存任何维持请求联系的数据。

可以基于特定用例和状态数量,组合以上两种方式来管理应用程序状态,保持网络性能、可扩展性和可靠性之间的平衡。

四,如何在服务器端实现安全和幂等的方法

安全性和幂等性是服务器在实现某些方法时必须保证提供给客户端的。

(一)幂等性和安全性的具体含义

安全性(Safe)是指对该REST接口访问,不会使服务器端资源状态发生改变。

HTTP的幂等性(Idempotent)是指对同一REST接口的一次或多次访问,得到的资源状态是相同的。

(二)HTTP方法的安全性与幂等性

在HTTP RFC定义了这些特性,并告诉我们哪些HTTP方法是安全的和幂等的:
在这里插入图片描述

(三)实现安全方法

将HTTP方法实现为只读操作就能实现安全方法。

安全性并不意味着服务器每次都必须返回同一结果。它只是表明客户端可以发起请求,并知道它不会改变资源的状态,即只读。
在这里插入图片描述

(四)实现幂等方法

幂等方法类似于“setter”,调用多次和只调用一次产生的效果是一样的。

比如发送了下面的请求:
在这里插入图片描述
现在假设因为网络故障, 客户端读不到响应。 因为HTTP协议规定PUT是幂等的, 所以客户端可以重复提交请求:
在这里插入图片描述
但是幂等性并不意味着服务器必须对每个请求以相同的方式进行响应,例如对DELETE方法的响应。

  • DELETE方法是幂等的,这意味着就算服务器在前一个请求中已经删除了资源,它也必须返回200 (0K)响应码。但实际上,要把DELETE实现为幂等操作,需要服务器追踪所有已经删除的资源。否则它可能会返回一个404 ( Not Found)响应他码。
  • 就算服务器保留了所有已删除资源的记录, 安全策略也可能要求服务器对所有已不存在的资源返回一个404(Not Found)响应码。

五,如何在客户端处理安全和慕等方法

把GET,、OPTIONS和HEAD看做只读操作,需要时,可以随时发起这些请求。

在网络或软件出错时,重新提交GET,、PUT和DELETE请求以做确认, 提供 If-Unmodified-Since 和/或 If-Match 条件头。

当您在一个幂等方法上遇到软件或网络的错误时,可以实现一个重试请求的逻辑:
在这里插入图片描述

六,何时使用GET方法

原则:使用GET方法进行安全与幕等的信息获取。

下面是一些错误用法示例:
在这里插入图片描述
对于服务器来说,所有这些操作都是不安全和非羸等的。但对于那些基于HTTP的软件,这些操作都是安全和籍等的。这种差异的后果严重依赖于应用程序。

如果这些操作必须要使用GET方法, 特别警惕以下几点:

  1. 添加Cache-Control: no-cache头来确保响应不被缓存
  2. 保由此产生的任何副作用都是良性的,不会改变关键业务数据。
  3. 在服务器实现方面,将这些操作实现成可重复执行的(例如幕等)。

七,何时使用POST方法

原则:

  • 要创建新的资源, 须资源作为一个工厂(见 How to Create Resources Using POST)。
  • 要修改一个或多个资源,须通过一个控制器资源(见 When and How to Use Controllers to Operate on Resources)。
  • 执行需要大量输入的查询(见 How to Support Query Requests with Large Inputs)。
  • 在其他HTTP方法看上去不合适时,执行不安全或非慕等的操作。

下面是一些适用场合:

  • 注解(Annotation )已存在资源。
  • 向公告板、新闻组、邮件列表或类似的文章群组发送消息。
  • 提供数据块,例如,数据处理器提交的表单的数据结果。
  • 通过追加操作扩充数据库。

所有基于HTTP的工具都会按下面的方式对待POST

  • 缓存不会缓存这一方法的响应。
  • 网络爬虫和类似的工具不会自动发起POST请求。
  • 大部分通用的HTTPX具不会自动重复提交POST请求。

另外,以下情况必须使用POST,即使GET才是正确的方法:

  • 浏览器等HTML客户端在发起请求获取相关资源时,将页面的URI作为Referer 头。这可能会把包含在 URI 中的敏感信息泄露给外部服务器。 ,这种情况下,使用传输层安全协议(Transport Layer Security, TLS, SSL的接班人),或者,如果不能加密URI中的敏感信息, 考虑使用POST处理HTML文档。
  • 当客户端提交的查询包含太多参数时,POST可能是唯 一的选择。

get与post需要注意的几点

八,如何使用POST方法创建资源

POST方法的应用场合之一是创建新资源,该协议类似于使用“工厂方法模式(factory method pattern)” 创建新对象。

  1. 让客户端向工厂资源提交附有需要创建资源的表述的POST请求,通过请求头中可选支持的Slug来向服务器提供一个名字,以作为被创建资源的 URI 的一部分。
  2. 资源创建之后, 返回响应码201 (Created),并在响应头Location头中包含新创建资源的URI。如果响应正文包含了新创建资源的完整表述, 那么在正文头的Content-Location中包含新创建资源的URI。

考虑一个为用户创建“地址” 资源的例子,可以把“用户” 资源作为一个创建新“地址” 的工厂:
在这里插入图片描述

  1. 使用“用户” 资源作为创建“家庭地址” 资源的工厂。
  2. 对新资源URI命名的建议。
  3. 新创建资源的URI。
  4. 响应中表述的URI。

九,何时使用PUT方法创建新资源

除了使用POST方法外,还能使用PUT方法创建新资源。

只有在客户端可以决定资源的 URI 时才使用 PUT 方法创建新资源, 否则,使用POST。

在这里插入图片描述

  1. 客户端可以控制 URI 的构成时,才使用PUT方法创建新资源。

HTTP协议PUT与POST

十,如何使用POST方法实现异步任务

(一)什么是异步请求

HTTP是一种同步、无状态的协议。 当客户端向服务器提交一个请求后,无论成功与否,客户端都期望得到一个回答。但这并不意味着服务器必须在返回响应之前完成对请求的处理。
例如,在一个银行系统中,当发起一次转账请求时,服务器可能在下一个工作日前都不会进行转账操作,而客户端可能稍后就要检查状态。

如果客户端通过串行方式在当前线程发送了这种同步的HTTP请求,那么在短时间内它就是得不到服务器的响应的,这将导致当前线程陷入等待,干不了别的事情。如果恰恰这种请求有很多,即使客户端从单线程转为多线程转甚至线程池的模式,都可能会堆积大量请求任务发不出去,而目标服务器却还远没有达到处理请求并响应的瓶颈。

客户端可以发送异步请求来实现更高的效率。因为异步HTTP请求减少了同步HTTP请求发送后等待完整处理结果的时间,保留了发送请求和处理响应的过程,这样一来,空出来的时间就能完成其他的任务。
那么异步任务(asynchronous task)的方式是如何知道请求是否已经完成处理的呢?那就是过一会儿再发一次请求去咨询服务器关于这次请求的处理进度,然后再做出处理动作。
举个例子,客户端就是甲方,只管发布需求,但乙方一时半会儿完成不了,所以甲方就隔三岔五地问进度,催完进度他就干其他事去了。乙方被催时可能就会给出需求还在处理、需求处理完毕、需求处理失败等结果,然后甲方再据结果执行其他的动作。

(二)实现异步任务

实现需要长时间才能完成的POST请求:

  • 客户端发送POST请求。
  • 服务器在接收到POST请求时创建一个新的资源,并返回回状态码202 (Accepted),其包含新资源的表述。仔细设计这个资源,让它的表述中包含请求的当前状态和诸如时间戳之类的相关信息。这个新资源的目的是让客户端可以跟踪异步任务的状态。
  • 客户端向任务资源提交GET请求,再根据请求的当前状态,执行相应的动作。

这里的“当前状态”如下:

  1. 执行中:返回响应码200 (0K)及包含当前状态的任务资源表述。
  2. 成功完成:返回响应码303 (See Other)及一个 Location 头,其中是展示任务输出的资源的 URL。
  3. 任务失败:返回响应码200(0K)及告知资源创建已失败的任务资源的表述,客户端需要读取表述的内容以找到失败的原因。

(三)实例:一个图片处理的Web服务

考虑一个图片处理的Web服务,提供文件格式转换、光学字符识别、图像清理等服务。

  1. 为了使用这个服务,客户端需要上传原始图片;
  2. 服务器根据上传图片的类型和大小,以及当前服务器的负载,服务器可能需要几秒至几个小时的时间来处理每一张图片。
  3. 处理完成后,客户端应用程序可以查看或下载处理后的图片。

1,客户端提交POST请求以启动图片处理任务:
在这里插入图片描述

  • 客户端使用了一个分段消息(multipart message),第一部分包含一份描述了需要服务器执行的图片处理操作类型XML文档,第二部分是需要处理的图片。

2,服务器受理请求,会创建一个新的任务资源:
在这里插入图片描述

  1. 响应码标识出服务器已经接受了处理请求。
  2. 客户端稍后检查状态的一个建议时间。

3,稍后,客户端向这个任务资源发送一个GET请求,跟踪处理进度,可能有一下三种情况:
在这里插入图片描述

  • 服务器还在处理这个任务。

在这里插入图片描述

  • 已处理完成,详见响应头中 Location 的URI。

在这里插入图片描述

  • 处理任务失败

十一,如何使用DELETE方法实现异步删除

DELETE用于异步任务的方法,适用于资源删除需要大量时间进行后台清理和归档的情况。

实现异步资源删除要比创建或更新资源更容易。以下步骤描述了一种实现方式:
1,客户端提交DELETE请求删除一个资源:
在这里插入图片描述
2,服务器创建一个新的资源并返回标识任务状态的表述:
在这里插入图片描述
3,客户端可以查询http://www.example.org/task/1以了解删除请求的状态:

可以使用同样的手段, 通过PUT方法实现异步资源更新。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值