【问题标题】:Proper response to client for a RESTful PUT endpoint for updating multiple entities in a single batch?RESTful PUT 端点对客户端的正确响应,以便在单个批次中更新多个实体?
【发布时间】:2016-05-21 20:19:06
【问题描述】:

对于更新单个实体(例如文档)的标准 REST PUT 请求,使用如下所示的端点:

[Route("documents/{id}")]
public void Put(int id, [FromBody]Document document)

有一种使用 HTTP 状态代码与客户端通信的明确方法,使用 HTTP 200 状态表示成功更新,如果未找到具有指定 Id 的文档,则使用 HTTP 404,如果存在则使用 HTTP 500更新记录等问题。

我的问题是我们的 RESTful API 使用率可能非常高。出于性能原因,我们希望创建一个端点,该端点将接受多个文档实体以在单个 PUT 操作中进行更新:

[Route("documents")]
public void Put([FromBody]IEnumerable<Document> documents)

输入如下:

[
    {"Id":1,"Name":"doc one","Author":"Fred"},
    {"Id":2,"Name":"doc two","Author":"John"},
    {"Id":3,"Name":"doc three","Author":"Mary"}
]

如果用户提交了 10 个文档,而我只能成功更新其中的 9 个,而剩下的一个由于某些问题而失败,我想提交 9 个成功更新的文档,然后与用户沟通哪些更新成功了,哪些失败了。

我可以采取的一种方法是,如果任何提交的文档成功更新,则返回 HTTP 200。在我返回给客户端的响应对象中,我可以包含成功的文档列表和文档列表那失败了。对于每一个失败的文档,我可以包括原因,以及每个失败文档的 HTTP 状态代码。

但是如果某些请求失败,我应该返回 HTTP 200 吗?这种方法依靠客户端检查失败文档列表以查看是否存在问题。我担心用户会看到 HTTP 200 并假设一切正常。

另一种选择是,如果客户端提交了 10 个文档,并且我能够成功更新其中的 9 个并且一个失败,则返回失败的那个的 HTTP 状态代码。例如,如果因为找不到指定的 Id 而失败,则返回 HTTP 404,如果因为 DB 不可用而失败,则返回 HTTP 500,等等。

这种方法也有问题。例如,如果两个文档由于不同的原因失败,应该返回哪个 HTTP 状态码?例如,为成功更新某些项目的请求返回 HTTP 500 状态是否有意义?

REST 指南是否对这个批量更新问题提供了任何建议?对于这个问题有什么推荐的方法吗?

【问题讨论】:

  • 看来207 Multi Status 最适合这里。

标签: rest asp.net-web-api restful-architecture api-design


【解决方案1】:

HTTP Status 207 Multi Status 可用于处理批处理。

当处理多个实体时,您的 API 可以返回包含响应列表的 207 状态响应:

  • 每个实体和响应共享一个密钥,允许消费者知道哪个响应对应于哪个提供的实体。在提供的用例中,文档的Id 可以用作键。
  • 每个响应都包含您在单独处理相应实体时收到的相同数据(包括 http 状态)。

RFC 声明消息采用 XML 格式,但您可以使用带有自己结构的 JSON。 您可以查看处理 batch processing 的 Jive API 以查看示例。

给定输入

[
  {"Id":1,"Name":"doc one","Author":"Fred"},
  {"Id":2,"Name":"doc two","Author":"John"},
  {"Id":3,"Name":"doc three","Author":"Mary"}
]

完全成功将返回一个207 http 状态,响应包含三个200 http 状态:

[
  {
    "Id": 1,
    "status": 200,
    "data" : { data returned for a single processing }
  },
  {
    "Id": 2,
    "status": 200,
    "data" : { data returned for a single processing }
  },
  {
    "Id": 3,
    "status": 200,
    "data" : { data returned for a single processing }
  }
]

如果 id 为 3 的实体出现问题,例如缺少作者:

[
  {"Id":1,"Name":"doc one","Author":"Fred"},
  {"Id":2,"Name":"doc two","Author":"John"},
  {"Id":3,"Name":"doc three"}
]

响应仍然是207,但将包含两个200 id 1 和2 的http 状态和一个400 id 3 的状态。

[
  {
    "Id": 1,
    "status": 200,
    "data" : { data returned for a single processing }
  },
  {
    "Id": 2,
    "status": 200,
    "data" : { data returned for a single processing }
  },
  {
    "Id": 3,
    "status": 400,
    "data" : { data returned for a single processing 400 error }
  }
]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-05-03
    • 1970-01-01
    • 2020-01-18
    • 2020-12-16
    • 1970-01-01
    • 1970-01-01
    • 2021-12-06
    相关资源
    最近更新 更多