执行两个操作的方法的 RESTful 名称

Posted

技术标签:

【中文标题】执行两个操作的方法的 RESTful 名称【英文标题】:RESTful name for the method that does two operations 【发布时间】:2017-05-15 08:14:33 【问题描述】:

在 API 中,我有门票资源,有两种方法:

1) 获取工单状态(工单可以锁定/解锁)

GET /api/tickets/:id

2) 更新工单状态

PUT /api/tickets/:id with status=locked|unlocked

我需要的是在一个 API 调用中将状态检查与实际更新结合起来。而且我还需要知道 API 调用是否更改了状态,或者它已经设置为所需的值。例如:

ticket_status = "unlocked"
PUT /api/tickets/:id/check_lock
changes ticket_status to "locked" and responses with "success"

ticket_status = "locked"
PUT /api/tickets/:id/check_lock
ticket_status is already "locked" so we response with "ignored"

对于反向操作,我们可以有

PUT /api/tickets/:id/check_unlock

我知道我们在这里通过组合操作打破了单一职责原则,但这样做是为了减少 API 请求的数量,并且会非常频繁地调用它。

所以我正在寻找好名字而不是那些丑陋的“check_lock”、“check_unlock”,因为它们似乎相当模棱两可。

【问题讨论】:

为什么在锁定已经锁定的票或解锁未锁定的票似乎绝对没有问题时需要“状态检查”?幂等性是一种很好的方法,可以不关心这一点。 这是一个简化的例子。我有一排票要处理。如果票被锁定,我需要延迟处理并将其推到队列的尾部。所以我需要知道它是否被锁定。 如果ticket被锁定,你是更新资源还是更新资源(PUT成功)还是中止操作? 当票被“解锁”时,我们更新它并返回带有 modified=true 的响应。如果票证被“锁定”,我们不会进行任何更改并返回带有 modified=false 的响应。决定采用 andih 建议的 POST /api/tickets/:id/toggle_lock 方法。 【参考方案1】:

使用类似的东西

PUT /api/tickets/:id/check_lock

不推荐更新锁状态(因为不是说不好的做法)。 阅读check_something 时,人们通常会想到一种安全的方法,即希望它修改任何值。

您的示例 PUT 不是幂等的。即在同一资源上调用 PUT 两次会导致不同的结果。这与HTTP Specification for PUT 相矛盾

PUT 请求被定义为替换目标的状态 资源。

在您的情况下,最好使用PATCH 更新部分票证资源,如RFC5789 甚至https://www.rfc-editor.org/rfc/rfc6902 中所述

PATCH /api/tickets/:id/ HTTP/1.1
Host: example.org
Content-Type: application/json-patch+json

 "op": "replace", "path": "/lock", "value": "unlock"  

您可以选择在响应中添加 ETag,以表明资源是否已被修改。

或者只是带有消息正文的 HTTP 状态代码 200,您可以在其中返回资源是否被修改以及锁定状态的新值。

如果你想切换锁定状态,你应该使用类似“动作资源”的东西。在这种情况下使用POST

POST /api/tickets/:id/toggle_lock

因此,您可以返回新的锁定状态以及它是否已作为 HTTP 200 状态代码正文的一部分进行更新。

【讨论】:

【参考方案2】:

考虑资源我不会有一个操作check_unlock。 我建议: GET /api/tickets/:id 带有 json 答案中的票证状态。即使你有两个 http 调用。

或者如果状态导致错误,您可以回答错误 400 或类似的内容。

【讨论】:

【参考方案3】:

我会采取稍微不同的方法并使用409 Conflict 状态码。

由于与当前的冲突,请求无法完成 资源的状态。仅在以下情况下才允许使用此代码 预计用户可能能够解决冲突并且 重新提交请求。

成功的会话:

PUT /api/tickets/123  ... locked: true ... 
200 OK

已锁定会话:

PUT /api/tickets/123  ... locked: true ... 
409 Conflict
POST /api/ticket-queue  // ticket data here 
201 Created

【讨论】:

以上是关于执行两个操作的方法的 RESTful 名称的主要内容,如果未能解决你的问题,请参考以下文章

WCF Restful CORS 无法执行 POST

springMVC框架 学习Restful风格 详解

RESTful WCF 使用方法名称包装 json 响应

mybatis执行删除的restful操作的时候:Access to the specified resource has been forbidden.

Laravel 4 定义 RESTful 控制器

理解RESTful 架构