Http response 207 MULTI-STATUS 适合多任务操作吗?

Is Http response 207 MULTI-STATUS appropriate for multi task operations?

我发现 Http 207 可用于批量 insert/delete/... 等操作,我们可能插入多个项目,从业务角度来看,部分成功是可以的。

我想知道如果我们 API Post 调用一些外部服务是否同样适用?

示例业务场景:

我们有正在创建订单的 HttpPost 端点。

HttpPost:
/api/order/

现在让我们假设这个端点除了创建订单之外还会调用外部服务来打印该订单的标签,并调用另一个服务通过 REST 向外部第 3 方系统发送某种确认。

现在在这种情况下,我们假设订单的创建是此操作成功的必要条件,但打印和外部 REST 调用都可能 return 错误消息。这可能不在我们的控制范围内。

根据我所读的内容,关于如何return此信息的选项是:

  1. 带有包含必要信息的某种对象的 Http 200。例如: { "isSucess": true, "isFailure": true, "erorMesage": "string" }
  2. 使端点更多 RESTful 并将其分成 3 个将被调用的操作,但在这种情况下这是不适用的(至少从我的角度来看),因为所有这些事情都与业务紧密耦合透视,它们应该绑定在一起
  3. Return 5xx 错误。 502 因为并非所有操作都成功并且存在一些内部问题,但是如果一个失败的操作是 502 而另一个是 503 怎么办
  4. Return 207 错误,每个操作都有正确的错误响应(订单创建:200,打印:502,外部第 3 方:502)

现在我想知道哪个最合适?我有点倾向于 502 错误或 207,因为我认为它们提供了有关系统实际状态的最多信息。

这是一道关于如何使用 REST 网络服务进行嵌套分布式事务的设计题。有很多合适的答案。 这是我对此的看法,我在提到 REST 规范的同时解决了你的每一个观点。

  1. HTTP 代码 207 不是一个好主意 - 此 return 代码 (207) 指定用于支持 HTTP 上的 WebDAV (https://en.wikipedia.org/wiki/WebDAV) 扩展的系统。 WebDAV 是分布式的,但是它是一个规范

allows user agents to collaboratively author contents directly in an HTTP web server

WebDAV 并非完全为分布式事务而构建。可以处理 return 代码 207 的服务器需要安装 WebDAV 模块。您甚至可能无法在多个 REST 库中获得此​​ return 代码的支持。例如,这个 API 文档没有代码 207。https://docs.oracle.com/javaee/7/api/javax/ws/rs/core/Response.Status.html(这是一个边缘案例,但它有助于说明这一点)。

  1. 如果部分满足请求,我不希望使用 HTTP 50x。让我们以服务器已创建订单但无法 post 将其发送到第三方 REST 服务器(该服务器已关闭或网络错误)的情况为例。这是 50 倍错误的规范 https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html:

"Response status codes beginning with the digit "5" indicate cases in which the server is aware that it has erred or is incapable of performing the request. "

服务器没有问题。它已创建实体。

  1. 我的建议是 return HTTP cod 202 on POST /api/order/,return 引用命令并异步处理这些步骤。此请求涉及多个事务 - 打印标签、更新第三方 REST 端点等。这些可以在“订单”资源中更新。 例如,POST /api/order/ 可以 return 这种格式:

HTTP STATUS 202 (Accepted) { "order": { "id": "1234567" } }

客户端应使用 GET /api/order/ 检查完整状态,这将 return 个人状态:

{ "id": 1234567, "label_printed": "failed", "third_party_updated": "success"}

如果一个订单的任何一个子交易失败了,应该重新处理,这是对现有订单的更新,调用PUT /api/order/,因为PUT方法是更新资源.服务器将接受 PUT 请求并根据需要重试事务。

这里有一些适合这个问题的附加答案:

Transactions in REST?

Transactions across REST microservices?