89

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

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

4

6 回答 6

100

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

根据HTTP 规范

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发送 DELETE 来删除每个密钥;
  3. 通过向http://www.somewhere.com/resources/k2发送 PUT 添加替换。

不太明确,但我认为通过向http://www.somewhere.com/resources发送单个 DELETE 请求来删除所有资源也是合法的。

于 2013-08-27T20:35:32.187 回答
2

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

https://www.rfc-editor.org/rfc/rfc5789

这是非常精细的调整。

于 2017-06-21T06:36:21.827 回答
2

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

参考:https ://restfulapi.net/rest-put-vs-post/

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

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

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

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

如果你真的想实现一个 upsert,两者都不是完美的,但如果错误导致 PUT 上的损坏,那么 API 是罪魁祸首(它应该是幂等的),而 POST 上的损坏是“我告诉过你的”。

我也喜欢思考 API 使用者会寻找什么。通常,在新屏幕上工作的 UI 开发人员会寻找添加用户在 UI 中添加的记录。他将首先寻找一个 POST,然后发现它也处理等式的 PUT 方面。

所以,两者都不是,但如果您必须选择,请选择 POST。

于 2020-08-29T19:54:05.137 回答
1

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

/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,并且您有一条现有记录。这是关于设计的问题。

于 2016-08-06T20:30:03.617 回答
1

根据MDN 网络文档

HTTP PUT 请求方法创建新资源或用请求有效负载替换目标资源的表示。

PUT和之间的区别POSTPUT幂等的:连续调用一次或多次具有相同的效果(即没有副作用),而连续的相同POST请求可能具有附加效果,类似于多次下订单。

句法

PUT /new.html HTTP/1.1

例子

要求

PUT /new.html HTTP/1.1
Host: example.com
Content-type: text/html
Content-length: 16

<p>New File</p>

回应

如果目标资源没有当前表示并且 PUT 请求成功创建了一个,则源服务器必须通过发送201( Created) 响应来通知用户代理。

HTTP/1.1 201 Created 
Content-Location: /new.html

如果目标资源确实具有当前表示并且该表示已根据封闭表示的状态成功修改,则源服务器必须发送200( OK) 或204( No Content) 响应以指示请求成功完成。

HTTP/1.1 204 No Content 
Content-Location: /existing.html
于 2021-09-19T03:50:08.290 回答
-4

如果你混合一切,你可能没有在做 REST。来自RESTful Web 服务:基础知识 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动词的独特操作来完成。在更新之前“全部删除”听起来不是一个好主意。

于 2013-08-27T16:18:23.613 回答