查看@Gordon 接受的答案,关键点很简单:
PUT 和 DELETE 是具有含义的特定动词,指示服务器执行特定操作以及应如何处理指令。
OK 标准和语义很好,但如果我只想以某种方式运行代码从数据库中删除某些内容,那么 DELETE 对我来说真正有用吗?
如果我们说,“好吧,但我更容易通过向我的 URI 发出一个具有路径 /api/entity/delete/{id} 的 GET 来执行删除操作(正如 @Bogdan 的回答中所建议的那样)。好吧,让我们看看在 GET 的定义中:
GET 方法意味着检索任何信息(以
entity) 由 Request-URI 标识
来源 - W3C 标准 - https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html
如果您将GET 用于DELETE,那么根据其标准定义,您显然是在滥用该方法。
好吧,让我们进一步说“好的,但这并不重要,因为对于开发人员来说,在某处使用 GET 方法读取 URI 并读取 /api/entity/delete/{id} 而不是使用删除资源的 DELETE 方法更实用与检索的 GET 方法相同的签名,以便开发人员了解这是为了删除。让我们考虑一个结构良好的 DELETE 方法签名(示例适用于 .NET Core 5):
// DELETE: api/TodoItems/5
[HttpDelete("{id}")]
public async Task<IActionResult> DeleteTodoItem(long id)
{
这不会响应获取请求,(例如,在调用 API 时意外删除而不是检索会受到更多保护 - 开发人员必须显式执行删除请求以API)。而且我们有一个非常清晰、结构良好且命名的 API 操作,开发人员甚至自动化工具都可以清楚地发现它(例如,开发人员现在可以专门搜索代码中任何出现的 DELETE,或者搜索清楚的方法名称)表示删除)。更重要的是,这种模式符合普遍接受的“RESTFUL”API 标准,应该使 API 更广泛地被开发人员(以及可能的任何自动化工具)识别和解释。
好的,这很好,但是将其设为 DELETE 的真正区别是什么?为什么还要使用 DELETE 而不是 GET?我的操作是从数据库中删除一些东西,我的网络服务器为什么要关心? OK,我们来想想DELETE的定义:
9.7 DELETE - DELETE 方法请求源服务器删除由 Request-URI 标识的资源。这种方法可能是
被原点上的人为干预(或其他方式)覆盖
服务器。
所以现在,如果我们指定删除,我们有可能在服务器上出现特定行为,这可能允许通过手动或自动干预来撤销删除操作。在特定用例中,这可能很重要。
好吧,那么 DELETE 对我有用,但为什么要使用 PUT?例如,如果我只是创建一个使用 POST 的“upsert”方法,如果资源存在则更新资源,如果不存在则创建它会更方便
我个人通常在实现对数据库进行操作的 API 时执行此操作,尽管 PUT 也有特定含义,即它具体表示资源的更新,而 POST 表示创建,所以使用 POST 来创建和更新是反标准的。我自己的观点是,当我通常认为 upsert 功能的实用性比严格使用正确的动词来添加与插入更重要时,REST API 是一种情况,但我可能会在这里遗漏一些东西。
在 REST api 之外使用 PUT 对于实际目的可能更重要,例如,如果我们正在执行更新操作,其中服务器可以通过了解资源已更新来潜在地清除任何缓存(这更重要例如,如果我们的资源是一个完整的文档)。在 RESTful API 中使用 PUT 进行更新操作时,可能会有一些我没有考虑过的实际优势。
POST 的标准定义声明 POST 成功响应应该是 201(已创建),而不仅仅是通用的“200 OK”,以便我们能够正确解释资源创建显式成功。该响应不适用于更新操作,但标准中没有为响应代码指定“必须”。开发人员使用 POST 进行 upsert 并在成功时返回 200(OK)当然很常见,无论是创建还是更新。
PUT 的标准更为严格,并指定在尝试更新时任何意外创建的资源都必须通过 201 响应代码来指示。如果指定 URI 中不存在现有资源,则可能发生这种情况。该标准解释说,如果我们使用 PUT,我们会得到更清晰的反馈,说明我们尝试更新操作的结果是否符合我们的预期。
来自 W3C 标准:
[如果 put] 不指向现有资源,并且该 URI 是
能够被请求用户定义为新资源
代理,源服务器可以使用该 URI 创建资源。如果一个
创建新资源,源服务器必须通知用户代理
通过 201(已创建)响应。如果修改了现有资源,
应该发送 200 (OK) 或 204 (No Content) 响应代码
表示请求成功完成。