“无结果”是否应该是RESTful响应中的错误?


52

我将描述一个示例:
我开始为烘焙店制作API。该API将使人们可以在目录中搜索烘焙产品,例如使用制作的薄荷巧克力曲奇api.examplebakery.com/search?q=.....

有人使用它来查找名为的产品pineapple-banana flavoured cookies,显然不会找到任何结果。

是否应该将其作为错误返回?搜索没有失败,API进行了搜索并成功得出结论,找不到cookie。该API不应返回404,因为确实找到了该API。




3
@gnat:这不是重复的,因为另一个问题是关于特定资源的,而不是针对多个资源的查询。
Greg Burghardt

7
类似地,假设您有一个返回对象数组的函数。如果没有与特定用例匹配的对象,您是希望该函数通过异常还是返回空数组?
凯文-恢复莫妮卡

2
@AakashM将HTTP-204返回到GET请求是非常不寻常的,我知道我在任何地方都没有看到。据我所知,HTTP-204通常在修改服务器上的资源(例如POST / PUT / DELETE请求)时用作响应。
Radu Murzea

Answers:


123

有结果时,输出为(基于您的注释的JSON)列表。对于没有结果的查询,输出应完全相同。简单列表中有0个项目。

因此,如果您的回应通常是这样的:

{
    "results": [
        {
            "name": "Pancakes",
            ....
        },
        {
            "name": "French Fries",
            ....
        }
    ]
}

然后对于结果为0的查询,应为:

{
    "results": []
}

如果您还包括有关结果的“页面”数,到这些“页面”的链接等的元数据,那么我建议说有1个“页面”。

HTTP状态应与结果-相同200 OK

204 No Content似乎也可以选择,但这并不是因为您实际上返回的是“内容”-空列表。如果您认为空白列表不算作“内容”,那么如果您修改响应以提供拼写建议,该怎么办?响应的核心仍然是一个空列表,但是现在有更多的“内容”。

有关HTTP状态代码的更多有用信息,jpmc26的答案值得一读。


9
这与空对象模式是同一种想法。错误和null并不是说这里什么都没有的唯一方法。有时您想安静地表达自己的一切。这样,客户不必进行任何测试。
candied_orange

54
我认为返回204是不合适的,因为您正在返回内容。只是内容没有结果,这与根本不返回任何内容是不同的。
TMN

9
@TMN同意-204不适合“无结果”。您的查询应始终返回一个数组,并将结果包含在数组中。如果没有结果,客户将自然地处理。如果客户想要显示特殊文本(“未找到结果”),那很好。仅应为自然不返回结果的端点返回204。
JasonB

1
如果您返回的null序列化为空字符串,我可以使用204我侦查
Ewan

15
这个。构造RESTful API时,重要的是API部分,而不是其余部分。良好的API使客户/消费者的生活变得轻松。空数组比空值/异常/状态码更容易处理。
古兰经

37

每当决定使用HTTP代码时,都应始终询问以下问题:

任何任意客户端可以/将/应该如何处理响应?

  1. 客户应该始终将响应视为失败吗?然后您要4xx还是5xx,具体取决于问题是客户端的输入还是服务器的进程。
  2. 客户应该在其他地方提出请求吗?然后3xx适合您。
  3. 服务器是否做了客户要求的(成功的)?那是2xx。

始终确定响应代码应位于哪个范围内。这样做很快就消除了很多作为选项的响应代码,并且(可能更重要的是)它使遵循代码的语义更加简单。有关每种类别的代码代表什么的说明,请参见HTTP代码文档的开始部分。

在这种情况下,客户端从有效的现有端点请求了给定过滤器的结果列表,并有权访问它。服务器能够处理请求并确定要返回的适当数据(无项目),因此请求成功。碰巧他们提供的过滤器过滤掉了所有结果。由于这可能是某些客户端的预期结果,因此服务器不必确定这是否是客户端想要的。如果客户端代码某种程度上有问题,则由客户端负责确定,检查和适当处理。所以这显然是2xx。

现在的问题是,“哪个2xx?” 这取决于服务器打算如何响应。

  • 其他答案所描述的那样,您是否会发回空列表的表示形式?如果是这样,则您希望为200。200表示服务器没有问题,并具有表示结果供客户端使用。对于用户来说,这可能是最方便的响应方式,他们可以解析响应是否有结果,然后自己弄清楚如何处理空列表。
  • 204在语义上没有错,但是您必须不带任何消息正文进行响应。这意味着所有客户端代码都必须显式检查不同的HTTP代码(或至少检查是否缺少消息正文),然后分别进行处理。这很不方便,很可能导致行为不端的客户。

其他根本不适用:

  • 201是不可能的。您没有创建任何持久性资源,也没有将位置返回给已创建的资源。
  • 202是不可能的。请求已完成;它不在后台处理。
  • 203表示在权威服务器和客户端之间修改了响应。您的RESTful接口权威服务器,因此此处不适用。
  • 205没有道理。您不需要客户端清除或刷新任何内容。
  • 206似乎设计用于通过多个响应返回大量资源。它还要求客户端要求标头中包含部分内容(因此,通过查询字符串进行的分页不符合条件)。在这里不适用。

因此,它应该是200或204,并且200更有可能导致更简单,更健壮的客户端代码(尤其是如果您使用包含空列表的一致响应结构)。


5
会对下降投票者的意见感兴趣。我不认为这有争议。
jpmc26

2
我认为客户不必明确检查204。他们需要的只是处理空响应对象的能力。通过跳过“解析正文”部分来处理204,这是HTTP框架的工作。Content-Lenght 4和body null的 200 相同。
Agent_L

1
@Agent_L您是对的,如果服务器响应的结构与正常响应不一致(例如将null列表放置在通常的位置),即使使用200,您也不会获得一致性的好处。但是,我所描述的是使用响应与正常结构一致,并且有一个空列表,结果列表通常会出现在该列表中。204剥夺了做出这种一致响应的任何机会。同样,即使在具有便利功能的HTTP客户端库中,您也经常(通常?)必须进行显式调用以解析JSON。
jpmc26

@Agent_L特别是对于列表,调用者通常可以只让其代码在空列表上正常运行(例如,通过遍历该列表),而他们需要某种类型的显式检查才能处理另一种表示形式。
jpmc26

16

不可以。使用404来表示“您的查询已处理,但没有匹配项”,这很糟糕,因为:

  • 基于异常处理的条件流(即,强制非正常结果在客户端中创建和处理异常,这可能是性能不佳且笨拙的)

  • 找不到“真实”页面之间的歧义,您输入了端点错误错误

要记住的是,总是有一个客户对消息进行反序列化,并且客户返回的内容很重要。而不是序列化。

如果客户端应返回null,则使用null的序列化。如果客户端应返回一个空数组,请使用[],如果客户端应抛出错误,请使用500并传递错误消息


2
服务器为什么要关心客户端对信息的处理方式?(PS:我不是拒绝您回答的人)。
Radu Murzea

在这种情况下,“客户端”是在客户端设备上运行的代码,它将服务公开给客户端应用程序。它必须能够公开服务方法并返回服务预期的结果。您需要一对客户机/服务器对才能完全实现通信
Ewan

3
当然,请勿将5xx用于客户端错误。在这种情况下,最好使用4xx。
凯文(Kevin)

1
虽然,在大多数情况下,它不应该是“服务器”,而不是“客户端”吗?是服务器在处理请求并提供响应,客户端只是在处理响应?在那种情况下,5xx代码是可以的,因为它是服务器错误,而不是客户端错误?
怀特先生

2
搭配的烦恼所有的错误代码是,他们中的HTTP意义。500是唯一适合您的服务引发异常的代码
Ewan

9

除了@Ewan的很好的答案:

如果查询是返回一组结果的查询,则在逻辑上,空集与一组或多组相同。一般来说,由于@Ewan指出的原因,将空集更改为错误的弊大于利,而且根本没有必要。

如果查询是查找并返回特定单例的类型(希望找到该单例,例如,按ID精确匹配),则在逻辑上适当的可能响应是未找到。


是的,我确实以Ewan的回答为依据。
Walfrat

5

您假设在没有返回数据的情况下代码必须采取特殊的措施,但事实并非如此。该代码可能只是在寻找产品数量,或将结果附加到列表或任何其他东西上。仅当确实存在错误时,才应给用户一个“错误”。


3
“如果确实存在错误,则只应给用户一个“错误”。- 这个。执行“搜索”时结果集为空通常不是“错误”。但是,如果数据库连接失败,则意味着实际上无法执行搜索,否则空结果集(并且没有错误)将是不明确的。在这种情况下,某种错误状态将是适当的(可能与空结果集一起使用-取决于API的定义方式)。
怀特先生

0

当我使用API​​时,作为客户端,我必须处理与“错误”情况不同的“成功”情况;我在那里别无选择。因此,你应该返回的情况下的错误客户希望该客户端的情况下,以区别对待,并成功希望治疗相同。

如果我执行的查询理论上可以返回任意数量的结果(零,一,两百,依此类推),那么只要API提供了所有结果的完整列表,就应该返回“成功”。可能在有很多结果的情况下,您返回了一部分结果列表,以避免太大的结果,并且有一种商定的方式来获取其他结果。这是因为作为客户,我经常想处理零结果的情况,例如更多结果的情况。我可能会有所不同,但我不想被迫这样做。

查找值的情况有所不同。我期待一个结果,就是我想要的价值。我需要一个结果,以有意义的方式继续我想做的事情。对于没有值的情况,返回状态404是更可接受的,因为无论如何我确实需要以不同的方式处理该情况。

摘要:如果客户期望从零到大数目的任意数量的结果,那么即使所有结果为零,也要交付所有结果,则返回“成功”。如果客户端希望得到一个准确的结果,则如果找到结果,则返回成功,如果未找到结果,则返回错误。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.