【问题标题】:REST - PUT (updating) resource stateREST - PUT(更新)资源状态
【发布时间】:2023-03-21 10:52:01
【问题描述】:

我一直在思考这个问题,但无法将其缠绕在我的脑海中。 假设我有一个通过 REST 公开的任务系统。任务有自己的生命周期,例如:

CREATED -> ACTIVE   ->  PROCESSING -> CLOSED
   |          |               |
   |          |-->ESCALATED-->|
   |
    --> DISMISSED

现在使用 POST,我通过在正文有效负载中提供所有信息来创建任务。

但现在我只需要更改任务的状态并添加注释即可。所以在所有理论上 PUT 是要走的路 - 它正在更新资源。但事情是这样的:

PUT: /tasks/{taskId}?action=activate 似乎是合法的 URI,但是该操作已经有一个可用于更改资源状态的请求参数 - PUT 有效负载呢?此端点的用户发送 0 长度消息的请求是否直观?

更新:

也很抱歉我的英语不好。我的意思是 - 通过 PUT 请求 ONLY 使用 URI 参数来更改资源的状态是否是一种好习惯,没有 BODY (Content-Lenght:0) 因此 URI :/tasks/32/?action=CLOSED 将“任务”状态从 PROCESSING 更改为 CLOSED

如果这是一种不好的做法 - 哪种方法被认为是更好的做法?

【问题讨论】:

  • 我不确定我是否明白这一点,但恕我直言,从 REST 的角度来看,您应该将资源与正文有效负载(如 POST)一起放置,而不是通过查询字符串传递数据;我假设查询字符串仅用于获取资源。
  • 写完这篇文章 10 分钟后,我发现了这个 - stackoverflow.com/questions/7323958/… @ilpaijin - 感谢您的输入,但是上面的堆栈帖子呢?
  • 我很抱歉我的英语不好,但我没有收到您的问题“上面的堆栈帖子”。
  • @ilpaijin 抱歉,我的意思是 stackoverflow 帖子:stackoverflow.com/questions/7323958/… 描述 POST 例如不一定必须有正文。
  • @Xeperis 该答案已过时,基于已过时的 RFC 2616。 POST 和 PUT 需要一个主体。在 POST 的情况下,您可以有一个空主体,其 mimetype 反映了这一点,但带有空主体的 PUT 在语义上等同于 DELETE。

标签: rest design-patterns jax-rs


【解决方案1】:

不,您不能这样做并调用您的应用程序 RESTful,原因有两个:

  1. URI 是原子标识符。您不能将查询字符串参数视为方法参数或具有与正文有效负载相同的语义。它们是标识符的一部分。

  2. PUT 要求服务器将给定 URI 处的资源替换为提交的表示。您不能像现在这样使用 PUT 进行部分更新,并且绝对不能使用 PUT 在部分更新中应用查询字符串参数。

考虑到这一点,有几个选项可以做你想做的事,可以被认为是最佳实践:

  1. 您可以 PUT 整个表示,更改您想要更新的状态值。换句话说,您的客户将发出 GET,更改文档中的值,然后使用 PUT 将所有内容发回。

  2. 您可以修补仅将更改应用于状态值的差异文档。查看json-patch 以获取与 PATCH 方法兼容的数据格式示例。

  3. 您可以向仅执行所需更改的专用端点发出 POST 请求,但您必须记录如何使用它。 POST 提交要由目标资源处理的有效负载,因此您可以对它做任何您想做的事情。

【讨论】:

  • 所以假设我的客户只能通过多种方式与资源交互 - 添加评论或更改“任务”资源的状态,最好是第二或第三选项?因为为了争论,可以说任务只能由经理角色创建,而简单的员工角色用户并没有所有这些权力只是一个子集。
  • 理想情况下,您的所有资源都应在您的应用程序中统一支持第 1 和第 2 选项,因此您只需要为尚不标准的操作实施 POST。
【解决方案2】:

是的,它是基于旧 RFC 的一个选项,但它已过时(请参阅 rfc7231)。老实说,考虑 PUTting 或 POST 带有空正文且仅带有查询参数和值的资源的实际用法,我感到很不寻常。

据我所知,基本的 RESTful 架构包括使用 HTTP 动词、调用资源端点以及创建/更新/删除该资源。 (请参阅@PedroWerneck 的 cmets 以获得进一步说明)。

这基本上意味着您使用 HTTP 动词(即 PUT),调用资源(tasks/abc)并向该资源发送一些数据以对其进行修改:

PUT /tasks/abc

title=abc&body=aabbccddeeff&status=changedToSomethingElse

创建的
POST /tasks

title=abc&body=aabbcc&status=created 

【讨论】:

  • REST 独立于协议。它与 HTTP 无关。
  • 你说得对,REST 不是协议,但我不同意它与 HTTP 无关。我相信 REST 架构应该与 HTTP 动词通信(也在这里声明 en.wikipedia.org/wiki/Representational_state_transfer
  • REST 可以使用任何传输协议来实现。HTTP 是最常见的,但您想象的强耦合实际上并不存在。
猜你喜欢
  • 2017-12-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多