我看不出 put 和 patch 方法之间的区别

i can't see difference between put and patch method

如果我已经喜欢这句话,我只想点赞或不喜欢。所以首先我找到报价然后我检查我是否已经喜欢报价,如果不是我喜欢,否则我不喜欢。

我有一个像下面这样的路由器

router.put('/:quoteId', isAuth, quotesController.likeQuote);

likeQuote 方法如下

module.exports.likeQuote = (req, res, next) => {
  const quoteId = req.params.quoteId;
  const userId = req.userId;
  Quote.findById(quoteId)
    .then((quote) => {
      if (quote.likes.indexOf(userId) == -1) {
        quote.likes.push(userId);
      } else {
        quote.likes.pull(userId);
      }
      return quote.save();
    })
    .then((updatedQuote) => {
      res.status(201).json({ message: 'You liked the post!' });
    })
    .catch((err) => {
      err.statusCode = 500;
      next(err);
    });

但我的问题是,我只想知道 PUTPATCH 是如何工作的?我认为我们应该在 PUT 方法中发送所有字段,而不是在 PATCH 方法中发送,但在我的情况下,我什至不发送任何字段并且两者都工作 fine.How 这发生了吗?

实际的 REST API 方法(PUTPATCH、...)没有任何限制。您选择编写的逻辑就是对此的定义。现在你问的是“最佳实践”,每当你问这个问题时,你都会得到很多不同的答案。我会解释我的观点。

PUT,所以 PUT 的本质是完全替换现有对象,这就是为什么人们告诉你发送整个对象,因为当你使用 PUT是一个完整的交换。

PATCHPATCH的本质是更新现有资源。在您的情况下,这就是您要查找的内容,在这种情况下,您只需发送更新所需的必填字段。

现在如果你把PUT写成一个更新而不是一个完整的交换是错误的吗?我认为事实并非如此。只要您在整个应用程序中保持一致的逻辑,您就可以构建自己的“最佳实践”来满足您的需求。

现在您确实将此问题标记为 Mongo 相关,所以我想向您介绍 piplined updates(针对 Mongo v4.2+)的概念,您可以在其中执行您的逻辑在 1 次更新中。

Mongo Playground

i just want to know how PUT and PATCH works?

需要理解的一个重要区别是我们没有关于 PUT 和 PATCH 工作方式的标准;那是一个实现细节,故意隐藏在“统一接口”后面。

我们拥有的是标准化的语义,关于 PUT 和 PATCH 含义的协议。

(由于不熟悉标准的人,这变得更加复杂,因此对含义的误解很常见。)

如果请求处理程序的实现与请求的语义不匹配,那没关系...但如果结果出现代价高昂的错误,那就是实现的错误。


PUT 和 PATCH 都是方法标记,表示我们正在尝试修改目标 uri 标识的资源。特别是,当我们试图使服务器的资源表示与客户端的表示相匹配时,我们会使用这些方法令牌。

例如,想象一下编辑网页。我们 GET /home.html,更改我们副本中的 TITLE 元素,我们希望将更改保存到服务器。我们如何在 HTTP 中做到这一点?

一个答案是我们将 home.html 的副本(包含我们的更改)发送回服务器,以便服务器可以保存它。那就是 PUT。

另一个答案是我们区分我们的副本和服务器的副本,并向服务器发送一个补丁文档,描述服务器应该对其副本进行的更改。那是补丁。


router.put('/:quoteId', isAuth, quotesController.likeQuote);

此调用所做的是配置框架,以便将具有 PUT 方法令牌和匹配“/:quoteId”的目标 uri 的请求委托给 likeQuote 方法。

在此级别,框架假定您知道自己在做什么——不会尝试验证“likeQuote”是否实现了 PUT 语义。为确保实现和请求语义匹配,您将需要做一些工作(检查代码、测试等)。

in my case i don't even send any fields and both work just fine.

正确 - 因为框架假定您知道自己在做什么,并且您当前的实现不会尝试访问或解释 HTTP 请求的主体。

注意:这是一个很大的暗示,表明请求处理程序实际上没有实现 PUT/PATCH 语义(如果服务器不查看请求的信息,它怎么可能让它的引用副本看起来像客户端的副本?客户提供)?

It is okay to use POST;假设您的实现是正确的,您不应该使用具有远程创作语义的方法,因为那不是您正在做的。附加到 POST 路由的相同实现将是 fine.

照原样,事情已经坏了 - 请求语义和处理程序实现之间存在不匹配。在受控条件下,您很可能会侥幸逃脱。您完全有可能只在受控条件下调用此代码。