如何以RESTful方式建模CANCEL动作?

Kar*_*ian 9 api rest http-verbs http-patch

我们目前正在处理来自我们巨石的小型服务.我们的域名与票务系统非常相似.我们已决定从域名的取消过程开始.

我们的取消服务具有简单的端点"取消",它接收票证的ID.在内部,我们检索id,执行与取消相关的一些操作,并更新商店中实体的状态.从商店的角度来看,取消的机票和实时机票之间的唯一区别是一些属性.

根据我的阅读,PATCH似乎是在这种情况下使用的正确动词,因为我只更新资源中的一个简单属性.

PATCH /api/tickets/{id}
Payload {isCancelled: true}
Run Code Online (Sandbox Code Playgroud)

但isCancelled不是实体中的实际属性.在有效载荷中发送不属于实体的属性是否公平,还是应该考虑对此请求进行建模的其他形式?我不希望将整个实体作为有效载荷的一部分发送,因为它很大.

我考虑过创建一个新的资源CancelledTickets,但在我们的域名中,我们永远不需要对已取消的门票进行GET.因此,不必创建新资源

任何帮助将不胜感激

谢谢K.

Rom*_*ner 6

REST 基本上是基于浏览器的 Web 的泛化。您应用于 Web 的任何概念也可以应用于 REST。

那么,您将如何在网页中设计取消活动?您可能有一个表行,其中包含某些活动,例如编辑和删除,用图标和鼠标悬停文本勾勒出轮廓,单击时会调用服务器上的 URI 并导致后续状态。您不太感兴趣该按钮的 URI 可能是什么样子,或者是否在后面调用了 PATCH 或 DELETE 命令。您只对处理请求感兴趣。

如果您想通过 REST 执行相同的操作,这同样适用。不是提示用户对条目执行编辑或取消活动的图像,而是应该使用有意义的链接关系名称来提示客户端有关可能性的信息。在您的情况下,这可能类似于reserve new tickets,edit reservationcancel reservation. 每个链接关系名称都伴随着一个 URL,如果客户端想要执行其中一项活动,他可以调用该 URL。URI 的确切字符在这里对客户端也不重要。调用哪个方法可能已经在响应中提供(作为进一步的伴随字段)或通过响应处理的媒体类型提供。如果媒体类型和随附字段都没有提示可以预先在 URI 上发出使用 OPTIONS 请求的 HTTP 操作。这里的经验法则是,服务器应该教客户端最终如何实现某些目标。

通过遵循这样的概念,您可以将客户端与 API 分离,并使其对更改具有健壮性。不是客户端生成 URI 来调用客户端,而是由服务器提供可能的 URI 来调用。如果服务器改变了它的内部 URI 结构,使用提供的 URI 之一的客户端仍然可以调用服务,因为它只是使用服务器提供的 URI 之一。通过分析提示客户端何时调用此类 URI 的链接关系名称来确定使用哪个。如上所述,此类链接关系名称需要在某处定义。但这正是菲尔丁在 2008 年声称的:

REST API 应该将几乎所有的描述性工作用于定义用于表示资源和驱动应用程序状态的媒体类型,或者用于为现有标准媒体类型定义扩展关系名称和/或支持超文本的标记。(来源

选择哪种 HTTP 操作来取消机票/预订可能取决于您的设计。虽然DELETE RFC 7231推荐的一些答案指出,仅删除 URI 和资源之间的关联,并且不保证此处也删除了实际资源。如果您设计的系统可能取消取消,那么DELETE这不是您的正确选择,因为在处理DELETE请求后,URI 到资源的映射不应该存在。但是,如果您认为取消也会导致取消预订,那么您可以使用DELETE

如果您以将状态作为资源内的属性维护的方式对资源进行建模,则PATCHing 资源可能是一个有效的选项。然而,简单地发送类似的东西state=canceled在这里可能是不够的,因为PATCH客户端完成的步骤计算是为了将某个资源(或多个资源)转换为所需的目标状态。JSON Patch可能会提供有关如何完成此操作的线索。需要进一步注意原子性要求PATCH。要么所有指令都成功,要么根本不成功。

正如PUT其他答案之一中所提到的。PUT具有将给定 URI 中可用的当前表示替换为请求的有效负载中给定的表示的语义。进一步允许服务器拒绝该内容或将其转换为更合适的表示并且也影响其他资源,即,如果它们模仿资源的版本历史。

如果上述操作都不能真正满足您的需求,您应该使用它,POST因为这是 HTTP 的通用 swiss-army-knife 工具包。虽然此操作通常用于创建新资源,但不限于此。它应该用于其他操作的语义不适用的任何情况。根据HTTP 规范

POST 方法请求目标资源根据资源自身的特定语义处理请求中包含的表示。

这基本上是免费出狱卡。在这里,您可以根据自己的规则在服务器上处理任何事情。如果你想取消或暂停某事,就去做吧。

我非常不鼓励GET用于创建、更改或取消/删除某些内容。GET是一个安全的操作,并保证任何调用客户端不会改变服务器上被调用资源的任何状态。请注意,它可能有轻微的副作用,即日志记录,但实际状态应该不受调用的影响。这是网络爬虫依赖的属性。他们将简单地通过调用任何 URIGET并了解接收到的响应的内容。我假设您不希望 Google(或任何其他抓取工具)取消您的所有预订,对吗?

如上所述,您应该使用哪种 HTTP 操作取决于您的设计。DELETE仅当您还打算删除表示时才应使用,即使规范不一定要求这样做,但一旦到资源的 URI 映射消失,您基本上无法进一步调用此资源(除非您创建了一个当然,首先要进行进一步的 URI 映射)。如果您将资源设计为将状态保持在属性内,我可能会选择,PATCH但总的来说,我基本上会选择POST这里,因为在这里您可以选择所有选项。


Pio*_*iuk 5

看看RESTful的确切方式.无论您是以有效载荷发送PATCH请求,isCancelled还是DELETE希望门票消失.它仍然是RESTful.

你的举动取决于你的需求.如你所说

我考虑过创建一个新的资源CancelledTickets,但在我们的域名中,我们永远不需要对已取消的门票进行GET.

我会发送DELETE.您不必将其物理移除.如果可以取消取消,则实施isCancelled机制.这只是味道的问题.


Isr*_*fel 5

公开GET资源的接口不是强制性的。

例如使用

PUT /api/tickets/{id}/actions/cancel
Run Code Online (Sandbox Code Playgroud)

提交取消请求。我选择,PUT因为实际上只有一个取消请求。

希望对您有所帮助。