3 回答

TA贡献1783条经验 获得超4个赞
尽管已经彻底地回答了OP关于PUT和PATCH之间的区别的问题,但其对为什么PATCH不等幂的问题的回答并不十分正确。
为了显示PATCH为什么不是幂等的,它有助于从幂等的定义开始(来自Wikipedia):
幂等一词用于更广泛地描述一种操作,如果执行一次或多次,将产生相同的结果。幂等函数是具有以下性质的函数f(f(x))= f(x)任何值x。
用更易访问的语言,幂等的PATCH可以定义为:用补丁文档对资源进行补丁之后,对具有相同补丁文档的相同资源的所有后续PATCH调用都不会更改该资源。
相反,非等幂运算是其中f(f(x))!= f(x)的情况,对于PATCH,可以将其表示为:用补丁文档对资源进行PATCH之后,随后的PATCH用同一补丁文件确实会更改资源。
为了说明非幂等的PATCH,假设有一个/ users资源,并且假设调用GET /users返回了一个用户列表,当前:
[{ "id": 1, "username": "firstuser", "email": "firstuser@example.org" }]
假定服务器允许PATCHing / user,而不是像OP的示例中那样PATCHing / users / {id}。让我们发出以下PATCH请求:
PATCH /users
[{ "op": "add", "username": "newuser", "email": "newuser@example.org" }]
我们的补丁文档指示服务器将一个名为的新用户添加到用户newuser列表中。第一次调用此函数后,GET /users将返回:
[{ "id": 1, "username": "firstuser", "email": "firstuser@example.org" },
{ "id": 2, "username": "newuser", "email": "newuser@example.org" }]
现在,如果我们发出与上述完全相同的 PATCH请求,会发生什么?(就本例而言,假设/ users资源允许重复的用户名。)“ op”为“ add”,因此将新用户添加到列表中,随后GET /users返回:
[{ "id": 1, "username": "firstuser", "email": "firstuser@example.org" },
{ "id": 2, "username": "newuser", "email": "newuser@example.org" },
{ "id": 3, "username": "newuser", "email": "newuser@example.org" }]
即使我们针对完全相同的端点发出了完全相同的 PATCH ,/ users资源也再次发生了变化。如果我们的PATCH是f(x),则f(f(x))与f(x)不同,因此,该特定PATCH不是幂等的。
尽管不能保证 PATCH是幂等的,但是PATCH规范中没有任何内容可以阻止您对特定服务器进行幂等的所有PATCH操作。RFC 5789甚至预期幂等PATCH请求的优点:
可以以幂等的方式发出PATCH请求,这也有助于防止在相似的时间范围内同一资源上的两个PATCH请求之间的冲突导致不良结果。
在Dan的示例中,他的PATCH操作实际上是幂等的。在该示例中,/ users / 1实体在我们的PATCH请求之间进行了更改,但不是因为我们的PATCH请求而发生的;而是 实际上是邮局的其他补丁文档导致了邮政编码的更改。邮局的不同PATCH是不同的操作;如果我们的PATCH为f(x),则邮局的PATCH为g(x)。幂等性指出f(f(f(x))) = f(x),但不做任何保证f(g(f(x)))。
添加回答
举报