传递复杂对象到 REST 服务的删除方法

Cic*_*cio 0 rest http-put complextype http-delete

我有管理资源的 REST 服务EASYPAY..此时此服务公开了 3 种不同的方法:

  1. 获取 EasyPay 请求 ( GET);
  2. 插入一个 Easypay 请求 ( POST);
  3. 更新 Easypay 请求 ( PUT)。

当我插入或更新请求时,我还必须trace在数据库的表中插入一行。

现在我必须删除一个 Easypay 请求,我还必须在跟踪表上添加一行。我想使用DELETEHTTP 动词,但我看到使用 delete 我不能传递复杂的对象,而只能传递要删除的请求的 ID。我不能使用PUTHTTP 动词,因为我已经使用过它,无论如何它在概念上都不正确......我不想做更多的从客户端到服务器的调用(一个用于删除请求,另一个用于删除请求)在跟踪表中添加一行)..所以我不知道如何解决问题。

编辑

我试着解释得更好......我有一个部署在两个不同服务器上的网站。一种用于前端,一种用于后端。后端只为前端公开一些 REST 服务,它无法访问互联网(只能访问内部网)。访问该网站的客户可以通过名为 XPAY 的系统进行付款,它的工作方式与 paypal 非常相似(XPAY 只是另一个虚拟 POS)。因此,当客户尝试付款时,我会在数据库中保存一些信息 + 跟踪付款尝试,然后将他重定向到 XPAY。在那里,他可以付款。最后,XPAY 返回网站(前端)向我们传达付款结果。结果在支付的 URL 中,所以我必须把 URL 中的所有信息都发送到后端。根据结果​​,

你有什么建议?

谢谢

Rom*_*ner 5

实际上有几种方法可以解决您的问题。首先,REST 只是一种架构风格,而不是一种协议。因此,REST 并没有规定必须如何组成 URI 或传递哪些参数。它只需要一个唯一的资源标识符,并且可能应该是自描述的,这意味着客户端可以根据返回的内容(HATEOAS,包括指向自身的链接和适当的内容类型规范)采取进一步的行动。

删除

由于您想在其他表中保留对已删除资源的跟踪,您可以在 URI 本身中传递数据作为查询参数(甚至可以对 JSON 进行编码以作为查询参数传递)或使用自定义 HTTP 标头来将(元)信息传递给后端。

将复杂对象(无论是 XML 还是 JSON)作为查询参数发送可能会导致某些问题,尽管某些 HTTP 框架将最大 URI 大小限制为大约 2000 个字符。因此,如果调用的 URI 超过此限制,后端可能无法满足请求。

尽管超文本传输​​协议没有定义头的最大数量(或大小),但如果请求太大某些实现可能会引发错误

邮政

当然,您也可以向后端发送一个新的临时资源,该资源可用于删除待处理的付款请求并向跟踪表添加新条目。

根据规范

POST 方法执行的操作可能不会产生可由 URI 标识的资源。在这种情况下,200(正常)或 204(无内容)是适当的响应状态,具体取决于响应是否包含描述结果的实体。

这使得POST对于在服务器端触发某些处理的短期临时资源的请求变得可行。如果您想设计一些类似队列或侦听器的系统,在其中将要执行的操作放入系统中,这将非常有用。由于POST请求可能包含正文,因此您可以在POST请求正文中发送 POS 响应。然后可以使用此操作请求删除挂起的 POS 请求并向跟踪表添加新条目。

修补

补丁是客户端可以指示服务器将一个或多个资源从状态 1 转换为状态 2 的一种方式。因此,客户端负责分解服务器为将资源转换为所需状态而必须采取的必要操作,而服务器尝试执行它们。客户端总是在已知状态下工作(它在之前的某个时间收集到)。这允许客户端将当前状态修改为所需状态,从而了解转换所需的步骤。根据其原子要求,要么所有指令都成功,要么都不成功。

一个JSON补丁为您的情况可能是这样的:

PATCH /path/to/resource HTTP/1.1
Host: backend.server.org
Content-lengt: 137
Content-Type: application/json-patch+json
If-Match: "abc123"

[
    { "op": "remove", "path": "/easyPayRequest/12345" }
    { "op": "add", "path": "/trace/12345", "value": [ "answer": "POSAnswerHere" ] }
]
Run Code Online (Sandbox Code Playgroud)

其中12345是实际easypay 请求的ID,POSAnswerHere应该替换为POS 服务的实际响应或后端进一步希望写入的作为跟踪的内容。

If-Match示例中的标头仅保证补丁请求在最新的已知状态下执行。如果同时进一步的进程改变了状态(它也会生成一个新的 If-Match 值),请求将因失败而412 Precondition Failed失败。

讨论

虽然DELETE最初可能是第一选择,但在我看来,它远不是您情况下的最佳解决方案,因为此请求并不是真正的幂等。实际的 POS 实体删除是幂等的,但跟踪的添加不是因为同一请求的多次发送将为每个请求添加一个条目(-> 副作用)。然而,这DELETE在某种程度上与操作的幂等性要求相矛盾。

POST另一方面是不保证幂等性的通用操作(PATCH也不保证)。虽然它主要用于在服务器端创建新资源,但只有服务器(或该服务器应用程序的创建者)知道它实际对请求做了什么(尽管这可能会扩展到所有操作)。由于没有事务限制,添加跟踪可能会成功,而删除挂起的请求实体可能会失败,反之亦然。虽然这可能由开发团队处理,但实际操作并没有对这个问题提供任何保证。如果服务器不在您自己手中,因此无法轻松修改或检查,这可能是一个主要问题。

因此PATCH,仍在 RFC 中的请求可能包含比POST请求更多的语义。它还指定了对每个请求显式修改多个资源的能力,并坚持原子性,这也需要类似事务的处理。JSON Patch 非常直观,传达了更多的语义,然后只是将 POS 响应添加到POST实体主体。

PATCH因此我认为应该优先于POSTor DELETE