让我们首先讨论您提到的选项:
- 1:
DELETE不一定需要删除或移除URI所针对的资源中包含的状态。它只要求删除目标 URI 到资源的映射,这意味着如果在此期间没有对该 URI 执行其他操作,则对同一 URI 的连续请求不应进一步返回资源的状态。由于您想重用指向客户端设置资源的 URI,这可能不是正确的方法。
- 2:REST 不关心 URI 的拼写,只要它根据RFC3986有效。没有 RESTful 或 RESTless URI 这样的东西。URI 作为一个整体是一个指向资源的指针,客户端应该避免通过解析和解释来提取它的知识。客户端和服务器应该使用 URI 所附加的链接关系名称。这样 URI 可以随时更改,并且客户端将仍然能够与服务进一步交互。然而,呈现的 URI 留下了一种 RPC 的味道,自动化客户端完全没有意识到这一点。
- 3:
PATCH实际上与代码版本控制工具完成的修补非常相似。在这里,客户应预先计算将源文档转换为所需形式所需的步骤,并将这些指令包含在所谓的补丁文档中。如果此补丁文档由文档状态与补丁文档使用的版本相匹配的人应用,则应正确应用更改。在任何其他情况下,结果都是不确定的。虽然application/json-patch+json与包含单独指令的补丁文档的理念非常相似,但application/merge-patch+json通过定义默认规则对其略有不同(取消属性将导致删除,包括属性将导致其添加或更新,而忽略属性将忽略原始文档中的这些属性)
- 4:从这个意义上说,首先从资源中检索最新状态并在本地更新它/计算更改,然后将结果发送到服务器可能是列出的最佳方法。在这里,您应该使用条件请求来保证更改仅应用于您最近下载的版本,并通过排除对该资源所做的任何中间更改来防止出现问题。
基本上,在 REST 架构中,服务器为客户端提供了一系列选择,客户端将根据他的任务选择其中一个选项并向附加的 URI 发出请求。通常,客户端通过HTML 表单、HAL 表单或ION等表单表示形式被告知服务器需要知道的所有内容。
正如您所提到的,在这样的环境settings中,它本身就是一个有效的资源,默认设置资源也是如此。因此,为了允许客户端重置他的设置,只需将默认设置资源的内容“复制”到目标设置资源即可。如果您想符合 WebDAV,这只是 HTTP 的扩展,您可以使用COPY HTTP操作(另请参阅IANA上其他已注册的 HTTP 操作)。对于普通的 HTTP 客户端,您可能需要一种不同的方法,以便任何任意 HTTP 客户端都能够将设置重置为所需的默认设置。
服务器希望客户端如何执行该请求可以通过上面提到的表单支持来教。Web 上的一个非常简单的方法是向客户端发送一个 HTML 页面,其中预先填写了 HTML 表单中的设置,也许还允许用户事先根据自己的意愿调整设置,然后单击提交按钮发送请求表单的 action 属性中存在的 URI,它可以是服务器想要的任何 URI。由于 HTML 仅支持表单POST,GET因此在 Web 上您仅限于POST.
有人可能会认为,只需发送一个包含要重置的设置资源的 URI 以及可选的默认设置的 URI 到专用端点的有效负载POST就足够了,然后让它执行其魔法将状态重置为默认状态。但是,这种方法确实绕过了缓存,并可能让他们相信旧状态仍然有效。HTTP 中的缓存是这样工作的,即资源的实际 URI 被用作密钥,并且对该 URI 执行的任何非安全操作都将导致该存储内容的逐出,因此任何连续的请求都将直接转到服务器而是由缓存提供服务。当你发送不安全的POST向专用资源(或 RPC 中的端点)发出请求,您错过了通知缓存有关实际设置资源修改的能力。
由于 REST 只是人类 Web 上使用的交互模型的概括,因此 Web 上使用的相同概念也适用于应用程序域级别也就不足为奇了。虽然您也可以在此处使用 HTML,但基于 JSON 的格式(例如application/hal+json或上述HAL forms或ION格式)可能更受欢迎。通常,您的服务能够支持的媒体类型越多,服务器就越有可能为众多客户端提供服务。
与人类 Web 相比,图像、按钮和其他内容为用户提供了相应控件的可供性,任意客户端,尤其是自动化客户端,通常不会很好地配合此类可供性。因此,需要提供其他方式来提示客户端有关 URI 或控制元素的用途,例如链接关系名称。虽然<<, <, >,>>可用于 HTML 页面链接以指示集合中的第一个、上一个、下一个和最后一个元素,但此处的链接关系提供,first和作为替代。这种链接关系当然应该在IANA 注册或至少遵循Web 链接扩展方法prevnextlast. 在关系上查找 URI 的客户端prev将知道 URI 的用途,并且如果 URI 发生变化,仍然能够与服务器交互。这本质上也是 HATEOAS 的全部内容,使用给定的控件通过服务器提供的状态机导航应用程序。
为 REST 架构设计应用程序的一些一般经验法则是:
- 将交互设计为与人类 Web 上的网页进行交互,或者更正式地设计为状态机或域应用程序协议,正如 Jim Webber 所说,客户端可以通过
- 让服务器通过支持不同的表单类型来教导客户端请求的外观
- API 不应使用类型化资源,而应依赖于内容类型协商
- 您的 API 或客户端支持的媒体类型越多,与其他对等方交互的可能性就越大
长话短说,总而言之,一种非常基本的方法是为客户提供一个预先填写的表格,其中包含构成默认设置的所有数据。action 属性的目标 URI 以实际资源为目标,因此也通知缓存有关修改。这种方法也是面向未来的,即使用资源支持的新结构和属性自动为客户提供服务。
......所以我可能遇到的受众和潜在的“客户”类型相当小 - 使用我的产品的开发人员,该产品部署在他们的私有数据中心或 AWS EC2 机器中,并且需要以任何语言编写脚本自动化一些任务,而不是通过 UI 来完成。
当有大量不同的客户端与您的应用程序进行交互并且需要支持将未来的演变固有地集成到设计中时,菲尔丁的架构风格意义上的 REST 会大放异彩。REST 只是为您提供了在未来添加新功能的灵活性,而行为良好的 REST 客户端只会选择它们并继续。如果您只与非常有限的一组客户端(尤其是在您控制下的客户端)进行交互,或者如果未来更改的可能性非常小,那么 REST 可能会过度杀伤力,并且不能证明仔细设计和实施所造成的额外开销是合理的。
...一些技术考虑,如缓存是相关的。人类用户的考虑,例如 API 设计在各种资源中的一致性,以及学习的难易程度,也是相关的。但是“一些第 3 方爬虫能否识别它可以从给定状态执行的下一个操作”并不是那么相关......
该术语API design已经表明需要一种更像 RPC 的方法,其中暴露了某些操作,用户可以调用以执行某些任务。只要您不从菲尔丁的角度将其称为 REST API,这一切都很好。显而易见的事实是,几乎没有任何应用程序/系统真正遵循 REST 架构风格,但有大量“坏例子”滥用术语 REST,因此表明 REST 架构的错误图景,其目的是以及它的优点和缺点。这在某种程度上是由于人们没有(仔细)阅读菲尔丁的论文而引起的问题,部分是由于对实用主义的整体偏好以及使用/实施快捷方式来尽快完成工作。
关于对“REST”的务实态度,很难给出准确的答案,因为每个人似乎都对它有不同的理解。无论如何,这些 API 中的大多数都依赖于外部文档,例如 Swagger、OpenAPI 等等,而这里的 URI 似乎可以让开发人员了解其用途。.../settings/reset因此,大多数开发人员应该清楚以结尾的 URI 。URI 是否具有 RPC 气味,或者是否遵循相应 HTTP 操作的语义,即 中的部分PUT或有效负载GET,是您应该记录的设计选择。