102

我从未使用过 PUT 或 DELETE HTTP 请求方法。我倾向于在系统状态(我的应用程序或网站)可能不受影响(如产品列表)时使用 GET,并在受影响时(如下订单)使用 POST。这两个不是总是足够的,还是我错过了什么?

4

6 回答 6

96

DELETE 用于删除请求资源:

DELETE 方法请求源服务器删除由 Request-URI 标识的资源。此方法可能会被源服务器上的人工干预(或其他方式)覆盖。客户端不能保证操作已经执行,即使源服务器返回的状态码表明操作已经成功完成……</p>

PUT 用于在服务器上放置或更新资源:

PUT 方法请求将封闭的实体存储在提供的 Request-URI 下。如果 Request-URI 引用了一个已经存在的资源,封闭的实体应该被认为是在源服务器上的一个修改版本。如果 Request-URI 不指向现有资源,并且该 URI 能够被请求用户代理定义为新资源,则源服务器可以使用该 URI 创建资源……</p>

有关完整规格,请访问:

由于当前的浏览器很遗憾不支持 HTML 表单中的 POST 和 GET 以外的任何其他动词,因此您通常无法充分利用 HTTP(尽管您仍然可以通过 JavaScript 劫持它们的提交)。HTML 表单中不支持这些方法导致 URI 包含动词,例如

POST http://example.com/order/1/delete

甚至更糟

POST http://example.com/deleteOrder/id/1

通过 HTTP 有效地隧道化 CRUD 语义。但是动词从来都不是 URI 的一部分。相反,HTTP 已经通过 HTTP 方法提供了对资源(例如订单)进行 CRUD 的机制和语义。HTTP 是一种协议,而不仅仅是一些数据隧道服务。

因此,要删除网络服务器上的资源,您可以调用

DELETE http://example.com/order/1

并更新它你会打电话

PUT http://example.com/order/1

并在 PUT 正文中提供更新的资源表示供网络服务器应用。

因此,如果您正在为REST API构建某种客户端,您可能会使其发送 PUT 和 DELETE 请求。这可能是内置在浏览器中的客户端,例如通过 JavaScript 发送请求,也可能是在服务器上运行的某个工具等。

有关更多详细信息,请访问:

于 2012-08-27T13:20:41.597 回答
27

使用 HTTP 请求动词,例如 GET、POST、DELETE、PUT 等...使您能够构建 RESTful Web 应用程序。在这里阅读:http ://en.wikipedia.org/wiki/Representational_state_transfer

从中受益的最简单方法是查看此示例。每个 MVC 框架都有一个Router/Dispatcher将 URL-s 映射到 actionControllers 的。所以像这样的 URL:/blog/article/1会调用blogController::articleAction($id); 现在这个路由器只知道 URL 或/blog/article/1/

但是,如果路由器知道整个 HTTP 请求对象而不仅仅是 URL,他就可以访问 HTTP 请求动词(GET、POST、PUT、DELETE...),以及有关当前 HTTP 请求的许多其他有用的东西。

这将使您能够配置应用程序,以便它可以接受相同的 URL 并根据 HTTP 请求动词将其映射到不同的 actionController。

例如:

如果你想检索第 1 条,你可以这样做:

GET /blog/article/1 HTTP/1.1

但如果你想删除第 1 条,你会这样做:

DELETE /blog/article/1 HTTP/1.1

请注意,两个 HTTP 请求具有相同的 URI,/blog/article/1,唯一的区别是 HTTP 请求动词。并且基于该动词,您的路由器可以调用不同的 actionController。这使您能够构建整洁的 URL-s。

阅读这两篇文章,它们可能会对您有所帮助:

Symfony 2 - HTTP 基础

Symfony 2 - 路由

这些文章是关于 Symfony 2 框架的,但它们可以帮助您弄清楚 HTTP 请求和响应是如何工作的。

希望这可以帮助!

于 2012-08-27T13:29:14.797 回答
9

虽然我冒着不受欢迎的风险,但我说它们现在没用了。

我认为它们在过去是很好用的,例如 DELETE 告诉服务器删除在提供的 URL 中找到的资源,而 PUT(及其同级 PATCH)告诉服务器以幂等方式进行更新。

事情发生了变化,URL 变得虚拟(例如,请参见url 重写)使资源失去了真实文件夹/子文件夹/文件的初始含义,因此 HTTP 协议方法(GET、POST、PUT/PATCH、DELETE)覆盖的 CRUD 动作动词失去了轨道.

举个例子:

  • /api/entity/list/{id}GET /api/entity/{id}
  • /api/entity/add/{id}POST /api/entity
  • /api/entity/edit/{id}PUT /api/entity/{id}
  • /api/entity/delete/{id}删除 /api/entity/{id}

左边没有写 HTTP 方法,本质上没关系(POST 和 GET 就够了),右边使用了适当的 HTTP 方法。

右侧看起来优雅、干净、专业。想象一下,现在您必须维护一个一直在使用优雅 API 的代码,并且您必须搜索删除调用的完成位置。您将搜索“api/entity”,在结果中您必须查看哪个正在执行 DELETE。或者更糟糕的是,你有一个初级程序员错误地将 PUT 切换为 DELETE 并且因为 URL 发生了同样的事情。

在我看来,将动作动词放在 URL 中比为该动作使用适当的 HTTP 方法具有优势,即使它不是那么优雅。如果您想查看删除调用的位置,您只需搜索“api/entity/delete”即可立即找到它。

在没有整个 HTTP 方法数组的情况下构建 API 可以更容易地在之后使用和维护

于 2020-05-14T11:10:09.120 回答
1

请参阅@Gordon 接受的答案,关键点很简单:

PUT 和 DELETE 是具有含义的特定动词,指示服务器执行特定操作以及应如何处理指令。

OK 标准和语义很好,但如果我只想以某种方式运行代码从数据库中删除某些内容,那么 DELETE 对我来说真正有用吗?

那么,如果我们说,“好吧,但我更容易通过向我的具有路径的 URI 发出 GET 来执行删除/api/entity/delete/{id}(正如@Bogdan 的回答中所建议的那样)。好吧,让我们看看 GET 的定义:

GET 方法意味着检索由 Request-URI 标识的任何信息(以实体的形式)

来源 - W3C 标准 - https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html

如果您使用GETaDELETE显然是根据其标准定义滥用该方法。

好吧,让我们进一步说'好的,但这并不重要,因为对于开发人员来说,在某处读取使用 GET 方法并读取的 URI 更实用,/api/entity/delete/{id}而不是使用删除与 GET 具有相同签名的资源的 DELETE 方法检索的方法,以便开发人员了解这是为了删除。让我们考虑一个结构良好的 DELETE 方法签名(示例适用于 .NET Core 5):

// DELETE: api/TodoItems/5
[HttpDelete("{id}")]
public async Task<IActionResult> DeleteTodoItem(long id)
{

这不会响应获取请求,(例如,在调用 API 时意外删除而不是检索更受保护 - 开发人员必须显式执行对 API 的 DELETE 请求)。我们有一个非常清晰、结构良好和命名的 API 操作,开发人员甚至自动化工具都可以清楚地发现它(例如,开发人员现在可以专门搜索DELETE代码中的任何出现,或明确指示 DELETE 的方法名称) )。更重要的是,这种模式符合“RESTFUL”API 的普遍接受标准,该标准应该使 API 更广泛地被开发人员(以及可能的任何自动化工具)识别和解释。

好的,这很好,但是将其设为 DELETE 的真正区别是什么?为什么还要使用 DELETE 而不是 GET?我的操作是从数据库中删除一些东西,我的网络服务器为什么要关心?OK,我们来思考一下DELETE的定义:

9.7 DELETE - DELETE 方法请求源服务器删除由 Request-URI 标识的资源。此方法可能会被源服务器上的人工干预(或其他方式)覆盖。

所以现在,如果我们指定删除,我们有可能在服务器上出现特定行为,这可能允许通过手动或自动干预来撤销删除操作。在特定用例中,这可能很重要。

OK 那么 DELETE 对我有用,但为什么要使用 PUT?例如,如果我只是创建一个使用 POST 的“upsert”方法,如果资源存在则更新资源,如果不存在则创建资源,这样会更方便

我个人通常在实现对数据库进行操作的 API 时执行此操作,尽管 PUT 再次具有特定含义,即它专门指示资源的更新,而 POST 指示创建,因此使用 POST 来创建和更新是反标准的。我自己的观点是,REST API 是一种情况,我通常认为 upsert 功能的实用性比严格使用正确的动词来添加和插入更重要,但我可能在这里遗漏了一些东西。

在 REST api 之外使用 PUT 对于实际目的可能更重要,例如,如果我们正在执行更新操作,其中服务器可以通过了解资源已更新来潜在地清除任何缓存(如果我们的资源更重要是一个完整的文档,例如)。在 RESTful API 中使用 PUT 进行更新操作时,可能有一些我没有考虑过的实际优势。

POST 的标准定义声明 POST 成功响应应该是 201(已创建),而不仅仅是通用的“200 OK”,以便我们能够正确解释资源创建显式成功。该响应不适用于更新操作,但标准中没有为响应代码指定“必须”。对于开发人员来说,使用 POST 进行 upsert 并在成功时返回 200(OK)当然很常见,无论是创建还是更新。

PUT 的标准更加严格,并指定在尝试更新时任何意外创建的资源必须通过 201 响应代码指示。如果指定 URI 中不存在现有资源,则可能发生这种情况。该标准解释说,如果我们使用 PUT,我们将获得更清晰的反馈,说明我们尝试更新操作的结果是否符合我们的预期。

来自 W3C 标准:

[如果 put] 不指向现有资源,并且该 URI 能够被请求用户代理定义为新资源,则源服务器可以使用该 URI 创建资源。如果创建了新资源,源服务器必须通过 201 (Created) 响应通知用户代理。如果修改了现有资源,则应发送 200(OK)或 204(No Content)响应代码以指示请求成功完成。

于 2021-10-20T06:14:12.453 回答
1

安全方法:获取资源/不修改资源
幂等:如果多次请求,资源状态不会发生变化
不安全方法:创建或更新资源/修改资源
非幂等:如果多次请求,资源状态会发生变化

根据您的要求:

1) 对于安全和幂等操作 (Fetch Resource) 使用 --------- GET METHOD
2) 对于不安全和非幂等操作 (Insert Resource) 使用------ POST METHOD
3)对于不安全和幂等操作(更新资源)使用--------- PUT METHOD
3)对于不安全和幂等操作(删除资源)使用--------- DELETE METHOD

于 2019-06-08T10:58:13.930 回答
-2

PUT每当您需要更改资源时,都会使用该方法。资源,它已经是资源集合的一部分。这里要注意的一件事是,PUT方法修改了整个资源,而PATCH方法用于修改资源或数据的必要部分。

删除

顾名思义,DELETErequest方法用于删除指定的资源。它请求源服务器删除由 Request-URL 标识的资源。

我希望这个简单的定义有所帮助。

于 2021-11-11T11:49:55.233 回答