对RESTful PUT端点的客户端进行适当响应,以便在一个批处理中更新多个实体?

时间:2015-12-28 18:39:52

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

对于使用如下所示的端点更新单个实体(例如,文档)的标准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指南是否针对此批量更新问题提供了任何建议?是否有针对此问题的推荐方法?

1 个答案:

答案 0 :(得分:1)

HTTP状态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,但会为ID 1和2包含两个200 http状态,并为ID 3包含400状态。

[
  {
    "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 }
  }
]