如果我还更新时间戳属性,我应该使用PUT方法进行更新

ope*_*sas 27 rest audit logging put

更确切地说:

根据休息样式,通常认为POST,GET,PUT和DELETE http方法应该用于CREATE,READ,UPDATE和DELETE(CRUD)操作.

事实上,如果我们坚持使用http方法定义,事情可能就不那么清楚了

本文中,它解释了:

简而言之:当且仅当您知道资源所在的URL以及资源的全部内容时才使用PUT.否则,请使用POST.

主要是因为

PUT是一个限制性更强的动词.它需要一个完整的资源并将其存储在给定的URL中.如果之前有资源,则将其替换; 如果没有,则创建一个新的.这些属性支持幂等性,天真的创建或更新操作可能不支持.我怀疑这可能是为什么PUT的定义方式; 它是一种幂等操作,允许客户端向服务器发送信息.

在我的情况下,我通常会发布传递所有资源数据的更新,因此我可以使用PUT进行更新,但每次发出更新时,我都会保存一个LastUser和LastUpdate列,其中包含进行修改的用户ID和操作的时间.

所以我想知道你的意见,因为严格来说,这两列并不是资源的一部分,但它们确实阻止了操作是幂等的.

saludos

SAS

Dar*_*ler 24

忽略关于将CRUD映射到HTTP方法的REST样式的注释,这是一个很好的问题.

您的问题的答案是,是的,您可以在此方案中自由使用PUT,即使服务器以非幂等方式更新资源的某些元素.不幸的是,答案背后的理由很模糊.重要的是要了解客户端请求的意图.客户端打算用传递的值完全替换资源的内容.客户端不负责服务器执行其他操作,因此不会违反HTTP方法的语义.

这是用于允许服务器在执行GET操作时更新页计数器的原因.客户端没有要求更新,因此即使服务器选择进行更新,GET也是安全的.

HTTP规范的更新中,最终阐述了完整的资源与部分资源争论

原始服务器应该拒绝任何包含Content-Range头字段的PUT请求,因为它可能被误解为部分内容(或者可能是作为完整表示被错误地PUT的部分内容).通过将具有与较大资源的一部分重叠的状态的单独标识的资源定向,或者通过使用为部分更新专门定义的不同方法(例如,[RFC5789]中定义的PATCH方法),可以实现部分内容更新.

那么,我们应该做的事情现在已经清楚了.不太清楚的是,为什么只允许发送完整的响应存在这种限制.这个问题已经被问到,恕我直言在这个线程中仍未得到答复.

  • http://williamdurand.fr/2014/02/14/please-do-not-patch-like-an-idiot/ - 我没有称任何人为白痴,但这是一个有用的阅读。 (2认同)

Mic*_*icE 8

由于LastUserLastUpdate不可修改客户端,我会从你的资源的完全表示删除它们.让我用一个例子来解释我的推理.

假设我们的典型示例API在被要求提供单个资源时将向客户端返回以下表示:

GET /example/123

<?xml version="1.0" encoding="UTF-8" ?>
<example>
    <id>123</id>
    <lorem>ipsum</lorem>
    <dolor>sit amet</dolor>
    <lastUser uri="/user/321">321</lastUser>
    <lastUpdate>2011-04-16 20:00:00 GMT</lastUpdate>
</example>
Run Code Online (Sandbox Code Playgroud)

如果客户端想要修改资源,则可能会采用整个表示并将其发送回API.

PUT /example/123

<?xml version="1.0" encoding="UTF-8" ?>
<example>
    <id>123</id>
    <lorem>foobar</lorem>
    <dolor>foobaz</dolor>
    <lastUser>322</lastUser>
    <lastUpdate>2011-04-16 20:46:15 GMT+2</lastUpdate>
</example>
Run Code Online (Sandbox Code Playgroud)

由于API为客户端生成lastUserlastUpdate自动生成值并且无法接受客户端提供的数据,因此最合适的响应将是400 Bad Request403 Forbidden(因为客户端无法修改这些值).

如果我们要成为符合REST和发送资源的完整表示做PUT请求时,我们需要删除lastUser,并lastUpdate从资源的代表性.这将允许客户端通过PUT发送完整的实体:

PUT /example/123

<?xml version="1.0" encoding="UTF-8" ?>
<example>
    <id>123</id>
    <lorem>foobar</lorem>
    <dolor>foobaz</dolor>
</example>
Run Code Online (Sandbox Code Playgroud)

现在服务器将接受完整的表示,因为它不包含lastUpdatelastUser.

剩下的问题是如何为客户提供访问lastUpdate和访问权限lastUser.如果他们不需要它(并且这些字段仅在API内部需要),我们很好,我们的解决方案完全是RESTful.但是,如果客户端需要访问此数据,则最干净的方法是使用HTTP标头:

GET /example/123

...
Last-Modified: Sat, 16 Apr 2011 18:46:15 GMT
X-Last-User: /user/322
...

<?xml version="1.0" encoding="UTF-8" ?>
<example>
    <id>123</id>
    <lorem>foobar</lorem>
    <dolor>foobaz</dolor>
</example>
Run Code Online (Sandbox Code Playgroud)

使用自定义HTTP标头并不理想,因为需要教用户代理如何阅读它.如果我们想以更简单的方式为客户提供对相同数据的访问权限,我们唯一能做的就是将数据放入表示中,我们面临的问题与原始问题相同.我至少会尝试以某种方式缓解它.如果API使用的内容类型是XML,我们可以将数据放入节点属性,而不是直接将它们作为节点值公开,即:

GET /example/123

...
Last-Modified: Sat, 16 Apr 2011 18:46:15 GMT
...

<?xml version="1.0" encoding="UTF-8" ?>
<example last-update="2011-04-16 18:46:15 GMT" last-user="/user/322">
    <id>123</id>
    <lorem>foobar</lorem>
    <dolor>foobaz</dolor>
</example>
Run Code Online (Sandbox Code Playgroud)

这样我们至少可以避免客户端尝试在后续PUT请求中提交所有XML节点的问题.这不适用于JSON,并且解决方案仍然处于幂等性的边缘(因为API在处理请求时仍然必须忽略XML属性).

更好的是,正如Jonah在评论中指出的那样,如果客户需要访问,lastUser并且lastUpdate这些可以作为新资源公开,从原始资源链接,例如如下:

GET /example/123

<?xml version="1.0" encoding="UTF-8" ?>
<example>
    <id>123</id>
    <lorem>foobar</lorem>
    <dolor>foobaz</dolor>
    <lastUpdateUri>/example/123/last-update</lastUpdateUri>
</example>
Run Code Online (Sandbox Code Playgroud)

... 然后:

GET /example/123/last-update

<?xml version="1.0" encoding="UTF-8" ?>
<lastUpdate>
    <resourceUri>/example/123</resourceUri>
    <updatedBy uri="/user/321">321</updatedBy>
    <updatedAt>2011-04-16 20:00:00 GMT</updatedAt>
</lastUpdate>
Run Code Online (Sandbox Code Playgroud)

(以上内容也可以很好地扩展,以提供包含个别更改的完整审核日志,并提供资源更改日志.)

请注意:
我同意 Darrel Miller对此问题看法,但我想提供一种不同的方法.请注意,这种方法不会被任何标准/ RFC /等备份,这只是对问题的不同看法.


Cri*_*riu 5

使用 PUT 创建资源的缺点是客户端必须提供表示它正在创建的对象的唯一 ID。虽然客户端通常可以生成此唯一 ID,但大多数应用程序设计者更喜欢他们的服务器(通常通过数据库)创建此 ID。在大多数情况下,我们希望服务器控制资源 ID 的生成。那么我们该怎么办?我们可以改用 POST 而不是 PUT。

所以:

把=更新

发布 = 插入

希望这对您的具体情况有所帮助。