在REST中,POST或PUT最适合upsert操作吗?

时间:2013-08-27 16:10:00

标签: api rest post put

我在客户端的服务器中保留了键值存储。如果用户发送密钥“k1”,那么我将其插入数据库。这被视为POST还是PUT

此外,我还有另一项操作,删除所有现有密钥并添加新密钥。这是POST还是PUT,因为它会清除记录并添加新记录。

5 个答案:

答案 0 :(得分:58)

如果用户发送密钥“k1”,那么我将其插入数据库。这被认为是POST或PUT。

根据HTTP specification

  

PUT方法请求将所包含的实体存储在提供的Request-URI下。如果Request-URI引用已经存在的资源,则封闭的实体应该被视为驻留在源服务器上的实体的修改版本。如果Request-URI未指向现有资源,并且该URI能够被请求用户代理定义为新资源,则源服务器可以使用该URI创建资源。

因此,我认为使用PUT进行插入或更新是完全合法的,前提是在两种情况下都提前知道URI。如果您将密钥用作URI的一部分(如http://www.somewhere.com/resources/k1中的k1),则应该是这种情况。但是,为了理想地RESTful,对同一URL的GET也应允许您下载资源。

此外,我还有另一个删除所有现有密钥并添加新密钥的操作,是POST还是PUT,因为它清除了记录并添加了新密钥。

我不认为这个操作可以被认为是RESTful,因为它做了两件事。它似乎提供了一个宏来满足特定客户的需求,而不是简单的数据访问。

是标准的RESTful设计
  1. 通过向父URL发送GET获取密钥列表。在上面的例子中,那将是http://www.somewhere.com/resources;
  2. 通过向http://www.somewhere.com/resources/k1;
  3. 发送删除来删除每个密钥
  4. 通过发送PUT到http://www.somewhere.com/resources/k2添加替换。
  5. 它不太明确,但我认为通过向http://www.somewhere.com/resources发送一个DELETE请求来删除所有资源也是合法的。

答案 1 :(得分:0)

upsert操作背后的想法是客户端拥有关于/决定数据结构和发送具有键值的数据的信息。因此,upsert操作的请求模型与更新操作非常相似,其中包含密钥,如下例所示:

/customers/jimmy

更新现有记录的预期方法是PUT。所以你的选择应该是PUT。

POST通常用于插入带有全新内容的新记录,如下例所示:

POST /customers HTTP/1.1
Content-Type: ...
Content-Length: ...
Host: server.yourdomain.com
Accept: ...
User-Agent: ...

id      jimmy
name    jimmy
Occupation   Stackoverflower

因此,在您的情况下,您不需要任何POST操作,因为用于upsert操作的PUT也涵盖了这一点。

这里关于upsert的关键问题是你信任你的客户端有关upsert操作的可能性。如果客户希望使用现有密钥插入新记录会发生什么?在您的情况下,您应该将此请求作为更新处理,因为插入和更新请求都来自相同的API并且您具有现有记录。这是关于设计的问题。

答案 2 :(得分:0)

Polly Shaw的答案是正确的,但我想提一下,鉴于消息可能很不完整(在资源尚未创建时缺少ID), PATCH 动词会更正确。

https://tools.ietf.org/html/rfc5789

这是非常精细的调整。

答案 3 :(得分:0)

如果upsert的定义是新记录与现有记录(要更新)的混合。

引用:https://restfulapi.net/rest-put-vs-post/

PUT必须是幂等的。这意味着,如果您第二次输入相同的有效负载,则不应更改系统状态。

如果预期的有效负载是新的和现有的混合,并且预期的行为是第二​​次创建更多的新记录,那么看起来“ upsert”将与POST紧密结合。

我们努力创建可容错的API。如果您不能使PUT成为幂等,而他们必须使用它,则可能会损坏系统。另一方面,预计POST不是幂等的,因此,如果您在有效负载中(一次又一次)发送了仅更新数据(即使这在技术上违反了POST的幂等性规则,因为它并没有改变系统的状态)在后续调用中添加记录),系统(可能)不会损坏。

  • 规范说PUT“可以”添加新项目,“必须”是幂等的
  • 它说POST“必须”添加新项,并且不是幂等

如果您真的想实施upsert,那也不完美,但是如果错误导致PUT损坏,则应该怪罪API(它应该是幂等的),而POST上的损坏是“我告诉过您”。

我还想考虑一下API使用者将要寻找的东西。通常,在新屏幕上工作的UI开发人员将希望添加用户已在UI中添加的记录。他将首先寻找POST,然后发现它还可以处理等式的PUT端。

因此,两者都不是,但是如果必须选择,请选择POST。

答案 4 :(得分:-1)

如果你混合了一切,你可能不会做REST。来自RESTful Web services: The basics POSTPUT的使用方案不同:

To create a resource on the server, use POST.
To retrieve a resource, use GET.
To change the state of a resource or to update it, use PUT.
To remove or delete a resource, use DELETE.

因此,请将POST视为向博客发布新故障单,并PUT更改现有值。

删除应该使用DELETE动词作为区别操作完成。作为"删除所有"在更新之前听起来不是一个好主意。