0

我正在创建一个 Web 客户端,其目的是通过向它们添加记录并从中删除记录来修改一组数据库表。它必须以原子方式进行,因此删除和插入都必须通过单个 HTTP 请求完成。显然,这是某种写操作,但我很难确定哪种方法是合适的。

POST起初似乎是正确的,除了RFC 2616 指定POST 请求必须描述命名资源的“新从属”。这不是我在这里所做的。

PUT可用于对现有事物进行更改,因此这似乎是正确的,除了RFC 2616 还指定“PUT 请求中的 URI 标识请求中包含的实体 [...] 并且服务器不得尝试将请求应用于其他资源”,因为我的 URI 没有直接指定数据库表,所以排除了该方法。

PATCH似乎更接近 - 现在我不是通过仅部分覆盖资源来作弊 - 但RFC 5789 清楚地表明,这种方法,如 PUT,必须实际修改由 URI 指定的资源,而不是某些从属资源。

那么我应该使用什么方法呢?

或者,更广泛地说,为了其他用户的利益:

对于对 X 的请求,您使用

  • POST创建 X 的新下属,
  • PUT创建一个新的 X,
  • PATCH修改 X。

但是如果要修改X的下属,应该使用什么方法呢?

4

4 回答 4

0

开始.. 并不是所有东西必须是 REST。如果 REST 是你的锤子,那么一切都可能看起来像钉子。

如果你真的想符合 REST 的理想,PATCH那是不可能的。你只是真的应该转移状态。

所以这个问题的常见“解决方案”是在你已经拥有的资源之外工作,但是发明一种新的资源来代表你希望执行的“交易”。此事务可以包含有关您正在按顺序执行的操作的信息,可能是原子的。

这使您可以PUT(或可能POST)进行交易,如果需要,还可以查看交易GET的当前状态,以确定它是否成功。

但在大多数设计中,这并不是很合适,您应该依靠POST并定义一个您在父节点上执行的简单 rpc 样式的操作。

于 2014-10-09T00:15:27.330 回答
0

RFC 2616 已过时。请改为阅读 RFC 723*,特别是http://svn.tools.ietf.org/svn/wg/httpbis/specs/rfc7231.html#POST

于 2014-10-09T06:41:02.057 回答
0

我知道这个问题已经被问过一段时间了,但我想我应该自己对此提供一些评论。这实际上不是真正的“答案”,而是对thecoshman 答案的回应。不幸的是,我无法评论他的回答,这将是正确的做法,但我没有足够的“声誉”,这是一个奇怪的(和不必要的)概念,恕我直言。

所以,现在开始我对@thecoshman 的评论:

您似乎质疑“交易资源”的概念,但在您的回答中,我认为您可能误解了它们的概念。在您的回答中,您描述了您首先对资源和相关事务进行 POST,然后 POST 另一个资源以“激活”此事务。但我相信事务资源的概念在某种程度上有所不同。

让我给你一个简单的例子:

在系统中,您有一个“客户”资源和他的地址,客户作为主要(或命名)资源,地址是从属地址。对于此示例,假设我们有一个 customerId 为 1234 的客户。到达该客户的 URI 将是/api/customer/1234。那么,您现在如何只更新客户的地址而无需更新整个客户资源?您可以定义一个名为“updateCustomerAddress”的“事务资源”。然后,您可以将POST更新的客户地址数据(JSON 甚至 XML)更新到以下 URI:POST /api/customer/1234/updateCustomerAddress. 然后,该服务将创建这个新的事务资源以应用于 customerId=1234 的客户。创建事务资源后,调用将返回 201,尽管实际更改可能尚未应用于客户资源。因此,后续GET /api/customer/1234可能会返回旧地址,或者已经是新的和更新的地址。这很好地支持了用于更新从属资源甚至命名资源的异步模型。

我们将如何处理创建的事务资源?它将对客户端完全不透明,并在事务完成后立即丢弃。因此,调用实际上可能不会返回事务资源的 URI,因为在客户端尝试访问它时它可能已经消失了。

如您所见,事务性资源不应该需要对服务进行两次 HTTP 调用,只需一次即可完成。

于 2017-01-20T23:00:38.343 回答
0

首先,请允许我纠正您对这些方法的理解。

POST就是创建一个全新的资源。您将一些数据发送到服务器,并期望得到一个响应,说明这个新资源是在哪里创建的。期望是,如果您POST/things/新资源存储在/things/theNewThing/. 您将POST其留给服务器来决定创建的资源的名称。发送多个相同POST的请求会产生多个资源,每个资源都有自己的“事物”和自己的 URI(除非服务器有一些额外的逻辑来检测重复项)。

PUT主要关于创建资源。PUT和之间的第一个主要区别POSTPUT让客户端控制 URI。一般来说,你并不真的想要这个,但这就是重点。另一件事就是PUT不要修改,如果您仔细阅读规范,它会声明您将 URI 中的任何资源替换为全新版本。这看起来像是在进行修改,但实际上只是在同一个 URI 上的全新资源。

顾名思义,PATCHPATCH用于获取资源。您向服务器发送描述如何修改特定资源的数据。考虑一个巨大的资源,PATCH允许您发送您希望更改的少量数据,同时PUT需要您发送整个新版本。

其次,考虑资源。您有一组表,每个表都有很多行,这相当于一组包含许多资源的集合。现在,您的问题是您希望能够原子地添加资源并同时删除它们。所以你不能只是POSTthen DELETE,因为这显然不是原子的。PATCH桌子怎么可能……

{ "add": [
  { /* a resource */ },
  { /* a resource */ } ],
  "remove" : [ "id one", "id two" ] }

在那个主体中,我们已将数据发送到服务器,以在服务器中创建两个资源并删除两个资源。现在,这有一个缺点,那就是很难让客户知道发生了什么。这两个新资源的客户端没有“正确”的方式,204 created有点像,但意味着有一个新资源的 URI 的标头……但我们添加了两个。可悲的是,无论如何你都会遇到这个问题,简单的 HTTP 并不是为了一次处理多个资源而设计的。


交易资源

所以这是人们提出的常见解决方案,我认为它很臭。基本思想是您首先POST/PUT服务器上的一个数据块对您希望进行的交易进行编码。然后,您使用另一种方法来“激活”此交易。

等等……那是两个请求……它发送的数据与您发送的数据相同PATCH,然后您甚至更多地捏造了 HTTP,以便以某种方式“激活”该事务。更重要的是,我们现在有这个“交易”资源!我们甚至用它做什么?

于 2015-08-19T08:08:32.253 回答