S3 REST API 和 POST 方法

Posted

技术标签:

【中文标题】S3 REST API 和 POST 方法【英文标题】:S3 REST API and POST method 【发布时间】:2013-11-19 13:02:36 【问题描述】:

我正在使用AWS S3 REST API,在解决了一些令人讨厌的签名问题后,它似乎可以工作了。但是,当我使用正确的 REST 动词来创建资源时,即POST,我得到405 method not allowed。相同的请求适用于方法 PUT 并创建资源。

是我做错了什么,还是 AWS S3 REST API 不完全符合 REST 标准?

【问题讨论】:

【参考方案1】:

是的,您将 CRUD 映射到 HTTP 方法是错误的。

尽管流行的用法和广泛的误解,包括 Stack Overflow 上的高评价答案,但 POST 并不是“创建资源的正确方法”。其他方法的语义由 HTTP 协议决定,而 POST 的语义由目标媒体类型本身决定。 POST 是用于任何未由 HTTP 标准化的操作的方法,因此它可以用于创建,也可以用于更新,或者其他任何其他方法尚未完成的操作。例如,使用 POST 进行检索是错误的,因为您已经为此标准化了 GET,但是当客户端由于某种原因无法使用 PUT 时,使用 POST 来创建资源是可以的。

同样,PUT 不是“更新资源的正确方法”。 PUT 是用于完全替换资源的方法,忽略其当前状态。如果您拥有服务器期望的完整表示,则可以使用 PUT 进行创建,如果您提供完整的表示,包括您不会更改的部分,则可以使用 PUT 进行更新,但使用 PUT 进行部分更新是不正确的,因为您要求服务器考虑资源的当前状态。 PATCH 就是这样做的方法。

在非正式的语言中,每个方法对服务器说的是:

POST:获取此数据并将其应用于给定 URI 标识的资源,遵循您为资源媒体类型记录的规则。

PUT:用此数据替换给定 URI 标识的任何内容,忽略其中已有的内容(如果有的话)。

PATCH:如果给定 URI 标识的资源仍具有我上次查看时的相同状态,则应用此差异。

请注意,create 或 update 没有被提及,也不是这些方法语义的一部分。您可以使用 POST 和 PUT 创建,但不能使用 PATCH,因为它取决于当前状态。您可以使用其中任何一个进行更新,但是使用 PATCH 您可以根据要更新的状态进行更新,使用 PUT 通过替换整个实体进行更新,因此这是幂等操作,使用 POST 您要求服务器执行它根据预定义的规则。

顺便说一句,我不知道说 API 是否符合 REST 是否有意义,因为 REST 是一种架构风格,而不是规范或标准,但即使考虑到这一点,很少有声称是 REST 的 API 是真正的 RESTful,在大多数情况下,因为它们不是 hypertext driven。 AWS S3 绝对不是 RESTful,尽管它与您的问题有关,但它们对 HTTP 方法的使用大部分时间都遵循 HTTP 标准。

【讨论】:

很好的解释。 POST 修改资源。人们会感到困惑,因为通常 POST 到表示集合的资源以通过创建新成员来修改集合。但是新成员是不同的资源,具有不同的 URL,与您发布到的资源不同。 有趣,我不知道,我检查过的大多数来源都在谈论将 CRUD 映射到 POST、GET、PUT、DELETE。虽然我发现有人说它是 POST 到/someobjects/ 而不是 PUT 到/someobjects/identifier。这是有道理的,为什么 S3 API 会抱怨,因为我正在向/path/file.name 发帖。 如果你在尝试创建该资源时对 /path/file.name 进行 POST,那肯定是错误的,因为 POST 数据从属于 /path/file.name 资源,如果没有不存在,它不能用它做任何事情。理论上,AWS 应该返回 404,而不是 405,但这可能是一个实现细节。它的路由具有允许的方法,并且在检查资源是否实际存在之前检查方法。 围绕 REST 存在许多普遍的误解,这可能是最常见的。不幸的是,Stack Overflow 有助于强化其中的很多内容,而且很难找到好的资源。有点奇怪,这里带有 REST 标签的最高问题的投票最多的答案是绝对错误的。 那篇***文章非常具有误导性,质量也很差。几乎每个给出的例子都不是 RESTful 的,包括你引用的部分,至少在讨论页面上有一些关于这个问题的 cmets。如果您需要对我上面所说的任何内容进行证实,您应该参考 RFC 2616。【参考方案2】:
+--------------------------------------+---------------------+
|                 POST                 |         PUT         |
+--------------------------------------+---------------------+
| Neither safe nor idempotent Ex: x++; | Idempotent Ex: x=1; |
+--------------------------------------+---------------------+

【讨论】:

【参考方案3】:

添加到@Nicholos

来自http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html

发布:

发布的实体从属于 URI,其方式与 文件从属于包含它的目录,一篇新闻文章是 从属于发布它的新闻组,或者一条记录是 从属于数据库

POST 方法执行的操作可能不会产生资源 可以通过 URI 标识。在这种情况下,200(OK)或 204 (No Content) 是适当的响应状态,取决于是否 响应中是否包含描述结果的实体

如果在源服务器上创建了资源,则响应 应该是 201(已创建)

放置:

PUT 方法请求将封闭的实体存储在 提供的请求 URI。如果 Request-URI 引用了一个已经存在的 资源,封闭的实体应该被认为是修改过的 驻留在源服务器上的版本。如果请求 URI 不指向现有资源,并且该 URI 能够 被请求用户代理定义为新资源, 源服务器可以使用该 URI 创建资源。如果有新资源 创建后,源服务器必须通过 201 通知用户代理 (创建)响应。如果修改了现有资源,则 应该发送 200 (OK) 或 204 (No Content) 响应代码来指示 成功完成请求

IMO PUT 可用于创建或修改/替换封闭实体。

【讨论】:

【参考方案4】:

在the original HTTP specification 中,POST 请求的负载中给出的资源“被认为从属于指定的对象”(即请求 URL)。 TimBL 之前说过(找不到参考)它是仿照the identically-named method in NNTP.

【讨论】:

以上是关于S3 REST API 和 POST 方法的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Flask-rest-jsonapi / JSON API 在同一个 POST 方法中创建对象和相关对象?

将雪花数据发送到 REST API (POST) 的方法

500内部服务器错误;在spring Boot rest api中使用POST方法时

来自 PowerShell 的 REST API -“不允许使用 POST 方法”

如何以 POST 方法在 REST API 中发送日期

Spring Rest API 的 AJAX POST 方法不起作用