REST API PATCH或PUT

我想用以下scheme的适当方法devise我的rest端点。

有一个组。 每个组都有一个状态。 该组可以由pipe理员激活或取消激活。

我应该如何devise我的终点?

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方法是正确的select。 PUT只能在整个replace资源时使用。

有关部分资源修改的更多信息,请参阅RFC 5789 。 具体来说, PUT方法描述如下:

扩展超文本传输​​协议(HTTP)的几个应用程序需要function来进行部分资源修改。 现有的HTTP PUT方法只允许完全replace文档。 该build议添加了一个新的HTTP方法PATCH来修改现有的HTTP资源。

REST中的R代表资源

(这不是真的,因为它代表了具有代表性,但是记住REST中的资源的重要性是一个很好的窍门)。

关于PUT /groups/api/v1/groups/{group id}/status/activate :你没有更新“激活”。 一个“激活”不是一个东西,它是一个动词。 动词永远不是好资源。 经验法则: 如果操作(动词)在URL中,则可能不是RESTful

你在做什么呢? 无论是“添加”,“删除”还是“更新”群组上的激活 ,或者您更喜欢:操纵群组上的“状态”资源。 就个人而言,我会使用“激活”,因为它们比概念“状态”模糊不清:创build一个状态是不明确的,创build一个激活不是。

  • POST /groups/{group id}/activation创build(或请求创build)激活。
  • PATCH /groups/{group id}/activation更新现有激活的一些细节。 由于一个组只有一个激活,我们知道我们所指的激活资源。
  • PUT /groups/{group id}/activation插入或replace旧的激活。 由于一个组只有一个激活,我们知道我们所指的激活资源。
  • DELETE /groups/{group id}/activation将取消或删除激活。

当一个集团的“激活”有副作用,例如付款,发送邮件等等时,这种模式是有用的。 只有POST和PATCH可能有这样的副作用。 例如,当激活的删除需要通过邮件通知用户时,DELETE不是正确的select; 在这种情况下,您可能需要创build一个停用资源POST /groups/{group_id}/deactivation

遵循这些准则是一个好主意,因为这个标准的契约对于你的客户,以及客户和你之间的所有代理和层次,什么时候是安全的,什么时候重试,什么时候都是非常明确的。 比方说,客户端的地方有一个flaky wifi,用户点击“deactive”,触发一个DELETE :如果失败,客户端可以简单的重试,直到获得一个404,200或者任何可以处理的东西。 但是,如果它触发一个POST to deactivation它知道不要重试:POST意味着这一点。
任何客户现在都有一个合同,当遵守这个合同时,将防止发送42个电子邮件“你的组已被停用”,只是因为它的HTTP库不断地重试到后端的呼叫。

更新单个属性:使用PATCH

PATCH /groups/{group id}

如果你想更新属性。 例如,“状态”可以是可以设置的组的属性。 诸如“状态”的属性通常是限制值到白名单的好候选者。 示例使用一些未定义的JSONscheme:

 PATCH /groups/{group id} { "attributes": { "status": "active" } } response: 200 OK PATCH /groups/{group id} { "attributes": { "status": "deleted" } } response: 406 Not Acceptable 

replace资源,没有副作用使用PUT。

PUT /groups/{group id}

如果你想更换整个集团。 这并不一定意味着服务器实际上创build了一个新的组,并抛出了一个新的组,例如id可能保持不变。 但是对于客户来说,这就是PUT的意思:客户应该假设他根据服务器的响应得到一个全新的项目。

客户端应该在发出PUT请求的情况下始终发送整个资源,包含创build新项目所需的所有数据:通常与POST创build所需的数据相同。

 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

我会build议使用PATCH,因为你的资源“组”有很多属性,但在这种情况下,你只更新激活字段(部分修改)

根据RFC5789( https://tools.ietf.org/html/rfc5789

现有的HTTP PUT方法只允许完全replace文档。 该build议添加了一个新的HTTP方法PATCH来修改现有的HTTP资源。

另外,更详细地说,

PUT和PATCH请求之间的差异反映在服务器处理封闭实体以修改资源的方式中
由Request-URI标识。 在PUT请求中,封闭实体被认为是存储在资源上的资源的修改版本
原始服务器,并且客户端正在请求存储的版本
被replace。 但是,对于PATCH,封闭的实体包含一组说明当前正在位于的资源的说明
原始服务器应该被修改以产生新的版本。 PATCH方法影响由Request-URI标识的资源
也可能对其他资源有副作用; 即新的资源
可以创build,或现有的修改,通过应用一个
补丁。

PATCH既不安全也不幂定义[RFC2616],第9.1节。

客户需要select何时使用PATCH而不是PUT。 对于
例如,如果补丁文件的大小大于大小的话
新的资源数据将在PUT中使用,那么它可能会产生
感觉使用PUT而不是PATCH。 与POST的比较更加困难,因为POST的使用方式多种多样
如果服务器select,则包含PUT和类似PATCH的操作。 如果
该操作不会以可预测的方式修改由Request-URI标识的资源,应考虑POST而不是PATCH
或者PUT。

PATCH的响应码是

204响应代码被使用,因为响应没有携带消息体(200代码的响应将具有)。 请注意,其他成功代码也可以使用。

另请参阅http://restcookbook.com/HTTP%20Methods/patch/

警告:实现PATCH的API必须以primefaces方式修补。 当GET请求时,资源不可能被修补。

既然您想使用REST架构风格来devise一个API,那么您需要考虑一下用例来决定哪些概念足够重要,以便作为资源公开。 如果您决定将组的状态公开为子资源,则可以为其提供以下URI并实现对GET和PUT方法的支持:

 /groups/api/groups/{group id}/status 

这种修改PATCH的方法的缺点是,你将无法以primefaces方式和事务方式更改组中的多个属性。 如果事务更改很重要,那么使用PATCH。

如果你决定公开状态作为一个组的子资源,它应该是组中的代表链接。 例如,如果代理获取组123并接受XML,则响应正文可能包含:

 <group id="123"> <status>Active</status> <link rel="/linkrels/groups/status" uri="/groups/api/groups/123/status"/> ... </group> 

超链接是实现超媒体作为 REST架构风格的应用程序状态条件的引擎所需要的。