REST API PATCH或PUT
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了REST API PATCH或PUT相关的知识,希望对你有一定的参考价值。
我想用以下场景的适当方法设计我的休息端点。
有一个小组。每个组都有一个状态。管理员可以激活或取消激活该组。
我应该将我的终点设计为
PUT /groups/api/v1/groups/group id/status/activate
要么
PATCH /groups/api/v1/groups/group id
with request body like
action:activate|deactivate
当您更新现有资源(组ID)时,PATCH
方法是正确的选择。只有在您完全替换资源时才应使用PUT
。
有关部分资源修改的更多信息,请参见RFC 5789。具体来说,PUT
方法描述如下:
扩展超文本传输协议(HTTP)的几个应用程序需要一个功能来进行部分资源修改。现有的HTTP PUT方法仅允许完全替换文档。此提议添加了一个新的HTTP方法PATCH来修改现有的HTTP资源。
REST中的R代表资源
(事实并非如此,因为它代表Representational,但它是记住REST在REST中的重要性的一个好方法)。
关于PUT /groups/api/v1/groups/group id/status/activate
:您没有更新“激活”。 “激活”不是一个东西,它是一个动词。动词永远不是好资源。根据经验:如果动作(动词)在URL中,则可能不是RESTful。
你做什么呢?您要么“添加”,“删除”或“更新”群组上的激活,要么您更喜欢:在群组上操纵“状态” - 资源。就个人而言,我会使用“激活”,因为它们比“状态”概念更不明确:创建状态是模糊的,创建激活不是。
POST /groups/group id/activation
创建(或请求创建)激活。PATCH /groups/group id/activation
更新现有激活的一些细节。由于一个组只有一个激活,我们知道我们所指的激活资源。PUT /groups/group id/activation
插入或替换旧的激活。由于一个组只有一个激活,我们知道我们所指的激活资源。DELETE /groups/group id/activation
将取消或删除激活。
当组的“激活”具有副作用时,例如正在进行付款,发送邮件等,此模式非常有用。只有POST和PATCH可能会产生这样的副作用。例如,删除激活需要,比如通过邮件通知用户,DELETE不是正确的选择;在这种情况下,您可能想要创建一个停用资源:POST /groups/group_id/deactivation
。
遵循这些准则是一个好主意,因为这个标准合同使您的客户非常清楚,客户与您之间的所有代理和层都知道何时可以安全地重试,何时不能。假设客户端是带有片状wifi的地方,并且其用户点击“停用”,这会触发DELETE
:如果失败,客户端可以简单地重试,直到它获得404,200或其他任何可以处理的内容。但如果它触发POST to deactivation
它知道不重试:POST暗示这一点。
任何客户现在都有合同,如果遵循该合同,将防止发送42封电子邮件“您的群组已被停用”,原因很简单,因为其HTTP库不断重试对后端的调用。
更新单个属性:使用PATCH
PATCH /groups/group id
如果您想更新属性。例如。 “status”可以是可以设置的Groups的属性。诸如“状态”之类的属性通常是限制值列入白名单的良好候选者。示例使用一些未定义的JSON方案:
PATCH /groups/group id "attributes": "status": "active"
response: 200 OK
PATCH /groups/group id "attributes": "status": "deleted"
response: 406 Not Acceptable
更换资源,没有副作用使用PUT。
PUT /groups/group id
如果您想要更换整个集团。这并不一定意味着服务器实际上创建了一个新组并抛出旧组,例如ids可能保持不变。但是对于客户来说,这就是PUT的意思:客户应该假设他根据服务器的响应获得了一个全新的项目。
在PUT
请求的情况下,客户端应始终发送整个资源,包含创建新项目所需的所有数据:通常需要与POST-create相同的数据。
PUT /groups/group id "attributes": "status": "active"
response: 406 Not Acceptable
PUT /groups/group id "attributes": "name": .... etc. "status": "active"
response: 201 Created or 200 OK, depending on whether we made a new one.
一个非常重要的要求是PUT
是幂等的:如果在更新组(或更改激活)时需要副作用,则应使用PATCH
。因此,当更新导致例如发送邮件,不要使用PUT
。
我建议使用PATCH,因为您的资源“组”有很多属性,但在这种情况下,您只更新激活字段(部分修改)
根据RFC5789(https://tools.ietf.org/html/rfc5789)
现有的HTTP PUT方法仅允许完全替换文档。此提议添加了一个新的HTTP方法PATCH来修改现有的HTTP资源。
另外,更多细节,
PUT和PATCH请求之间的差异反映在服务器处理随附实体以修改资源的方式中 由Request-URI标识。在PUT请求中,封闭的实体被认为是存储在其上的资源的修改版本 原始服务器,客户端请求存储的版本 被替换。但是,使用PATCH,随附的实体包含一组描述当前资源如何驻留在资源上的指令 应修改原始服务器以生成新版本。 PATCH方法会影响Request-URI标识的资源 也可能对其他资源产生副作用;即新资源 可以通过应用a来创建或修改现有的 补丁。
PATCH既不是[RFC2616]第9.1节定义的安全也不是幂等的。
客户端需要选择何时使用PATCH而不是PUT。对于 例如,如果补丁文档大小大于 可能会在PUT中使用的新资源数据 感觉使用PUT而不是PATCH。与POST的比较更加困难,因为POST的使用方式各不相同 如果服务器选择,则包含PUT和PATCH类操作。如果 操作不会以可预测的方式修改Request-URI标识的资源,应该考虑POST而不是PATCH 或PUT。
PATCH的响应代码是
使用204响应代码是因为响应没有携带消息体(具有200代码的响应将具有)。请注意,也可以使用其他成功代码。
也请参考http://restcookbook.com/HTTP%20Methods/patch/
警告:实现PATCH的API必须以原子方式进行修补。当GET请求时,不可能对资源进行半修补。
由于您希望使用REST架构样式设计API,因此需要考虑用例来确定哪些概念足以作为资源公开。如果您决定将组的状态公开为子资源,您可以为其提供以下URI并实现对GET和PUT方法的支持:
/groups/api/groups/group id/status
这种方法相对于PATCH进行修改的缺点是,您无法以原子方式和事务方式对组中的多个属性进行更改。如果事务更改很重要,请使用PATCH。
如果您决定将状态公开为组的子资源,则它应该是组表示中的链接。例如,如果代理获得组123并接受XML,则响应主体可以包含:
<group id="123">
<status>Active</status>
<link rel="/linkrels/groups/status" uri="/groups/api/groups/123/status"/>
...
</group>
需要一个超链接来实现REST架构风格的hypermedia as the engine of application state条件。
我通常更喜欢一些更简单的东西,比如activate
/ deactivate
子资源(由Link
头与rel=service
链接)。
POST /groups/api/v1/groups/group id/activate
要么
POST /groups/api/v1/groups/group id/deactivate
对于消费者而言,这个界面非常简单,它遵循REST原则,而不会让您将“激活”概念化为单独的资源。
以上是关于REST API PATCH或PUT的主要内容,如果未能解决你的问题,请参考以下文章
我应该在我的 REST API 中使用 PATCH 还是 PUT?
Django Rest Framework,ajax POST 工作,但 PATCH 抛出 CSRF 失败:CSRF 令牌丢失或不正确