什么是有效请求的正确REST响应代码,但空数据?

时间:2012-07-31 18:45:40

标签: rest http api-design

例如,您为users/9运行GET请求,但没有ID为#9的用户。 哪个是最好的响应代码?

  • 200 OK
  • 202接受
  • 204 No Content
  • 400 Bad Request
  • 404 Not Found

26 个答案:

答案 0 :(得分:266)

我坚决反对404支持204或200的空数据。

请求已收到并正确处理 - 它确实触发了服务器上的应用程序代码,因此无法确定它是客户端错误,因此整个类的客户端错误代码(4xx)不合适。

更重要的是,404可能由于多种技术原因而发生。例如。应用程序暂时停用或卸载在服务器上,代理连接问题和诸如此类的东西。因此,客户端无法区分404表示"空结果集"和404意味着"服务无法找到,稍后再试#34;

这可能是致命的:想象一下贵公司的会计服务,其中列出了应该获得年度奖金的所有员工。不幸的是,有一次它被调用它返回404.这是否意味着没有人应该获得奖金,或者应用程序当前是否因新部署而停止?

- >对于关心数据质量的应用程序而言,404因此几乎是不可取的。

此外,许多客户端框架通过抛出异常而没有进一步的问题来响应404。这会强制客户端开发人员捕获该异常,对其进行评估,然后根据是否将其记录为由例如监控组件或是否忽略它。这对我来说也不是很好看。

404超过204的唯一优势是它可以返回一个响应实体,该实体可能包含有关未找到所请求资源的原因的一些信息。但如果这确实相关,那么人们也可以考虑使用200 OK响应并以允许有效载荷数据中的错误响应的方式设计系统。 或者,可以使用404响应的有效载荷将结构化信息返回给调用者。如果他收到例如一个html页面,而不是他可以解析的XML或JSON,那么这是一个很好的指标,表明技术出了问题,而不是"没有结果"从来电者的角度来看可能有效的回复。或者可以使用HTTP响应头。​​

尽管如此,我仍然希望204或200有空响应。这样,请求的技术执行状态与请求的逻辑结果分开。 2xx表示"技术执行确定,这是结果,处理它"。

我认为在大多数情况下,应由客户决定是否可以接受空结果。尽管技术执行正确,但通过返回404,客户可能会决定将案例视为错误而非错误。

另一个简单的类比:返回404为"没有找到结果"就像SQL查询没有返回任何结果一样抛出DatabaseConnectionException。它可以完成工作,但是有很多可能的技术原因引发相同的异常,然后将其误认为是有效的结果。

答案 1 :(得分:199)

TL; DR:使用404

This Blog。它解释得非常好。

博客对204的评论摘要:

  1. 204 No Content作为浏览器的响应代码并不是非常有用(尽管根据HTTP规范,浏览器确实需要将其理解为“不要更改视图”响应代码)。
  2. 204 No Content 然而,对于ajax Web服务非常有用,它可能需要指示成功而不必返回某些内容。 (特别是在DELETEPOST s不需要反馈的情况下。
  3. 因此,对您的问题的答案是在您的案例中使用404204是一个专门的响应代码,您不应经常返回浏览器以响应GET

    其他响应代码甚至不如204404

    1. 200应与您成功获取的任何内容一起返回。当您提取的实体不存在时不合适。
    2. 当服务器开始处理对象但对象尚未完全准备好时,使用
    3. 202。当然不是这里的情况。您尚未开始,也不会开始构建用户9以响应GET请求。这违反了各种规则。
    4. 400用于响应格式不正确的HTTP请求(例如格式错误的http标头,错误排序的段等)。这几乎肯定会由你正在使用的任何框架来处理。除非您从头开始编写自己的服务器,否则不必处理此问题。 修改Newer RFCs现在允许将400用于语义无效的请求。
    5. 维基百科的description of the HTTP status codes特别有帮助。 您还可以查看定义in the HTTP/1.1 RFC2616 document at www.w3.org

答案 2 :(得分:24)

起初,我认为204会有意义,但在讨论之后,我相信404是唯一真正正确的回应。请考虑以下数据:

用户:John,Peter

METHOD  URL                      STATUS  RESPONSE
GET     /users                   200     [John, Peter]
GET     /users/john              200     John
GET     /users/kyle              404     Not found
GET     /users?name=kyle`        200     []
DELETE  /users/john              204     No Content

一些背景知识:

  1. 搜索返回一个数组,它只是没有任何匹配但是 它有内容:一个空数组

  2. 404当然最为人所知的是不受支持的网址 请求的服务器,但缺少的资源实际上是相同的 即使/users/:nameusers/kyle匹配,也是用户 Kyle不是可用资源,所以404仍然适用。它不是 搜索查询,它是动态网址的直接引用,因此404就是。

  3. 无论如何,我的两分钱:)。

答案 3 :(得分:21)

如果预期资源存在,但它可能是空的,我认为可能更容易获得200 OK,表示该事物是空的。

所以我宁愿/ /东西返回200 OK,{“Items”:[]}而不是204,什么都没有,因为这样一个带有0个项目的集合可以被视为与集合相同包含一个或多个项目。

我只是为PUT和DELETE留下了204 No Content,在那里可能没有实用的表示。

在/ thing / 9确实不存在的情况下,404是合适的。

答案 4 :(得分:19)

在之前的项目中,我使用过404.如果没有用户9,则找不到该对象。因此404 Not Found是合适的。

对于存在的对象,但没有数据,204 No Content是合适的。我认为在你的情况下,该对象确实存在

答案 5 :(得分:11)

根据w3帖子,

  

200 OK

请求已成功。响应返回的信息取决于请求中使用的方法

  

202接受

请求已被接受处理,但处理尚未完成。

  

204无内容

服务器已完成请求但不需要返回实体主体,并且可能希望返回更新的元信息。

  

400错误请求

由于语法格式错误,服务器无法理解该请求。客户端不应在没有修改的情况下重复请求

  

401未经授权

请求需要用户身份验证。响应必须包含WWW-Authenticate头字段

  

404 Not Found

服务器未找到与Request-URI匹配的任何内容。没有说明该病症是暂时的还是永久性的

答案 6 :(得分:9)

总结或简化,

2xx:可选数据:格式正确的URI:条件不是URI的一部分:如果条件是可选的,可以在@RequestBody中指定,@ RequestParam应该导致2xx。示例:按名称/状态过滤

4xx:预期数据:格式不正确URI:条件是URI的一部分:如果条件是强制性的,只能在@PathVariable中指定,那么它应该导致4xx。示例:按唯一ID查找。

因此对于问的情况: “users / 9”将是4xx(可能是404) 但对于“用户?名称=超人”应该是2xx(可能是204)

答案 7 :(得分:8)

有两个问题。一个在标题中,一个在示例中。我认为这部分导致了对哪种回应适当的争议。

问题标题询问空数据。空数据仍然是数据,但与无数据不同。因此,这表明请求结果集,即列表,可能来自/users。如果列表为空,则它仍然是列表,因此204(无内容)是最合适的。您刚刚要求提供一个用户列表并且已经提供了一个用户列表,它恰好没有内容。

提供的示例代之以询问特定对象,即用户/users/9。如果未找到用户#9,则不返回用户对象。您询问了一个特定的资源(用户对象)并没有找到它,因为找不到它,所以404是合适的。

我认为解决这个问题的方法是,如果您可以按照预期的方式使用响应而不添加任何条件语句,那么使用204,否则使用404。

在我的示例中,我可以迭代一个空列表而不检查它是否有内容,但我无法在空对象上显示用户对象数据而不会破坏某些内容或添加检查以查看它是否为null

当然,如果符合您的需要,您可以使用null对象模式返回一个对象,但这是另一个线程的讨论。

答案 8 :(得分:6)

可悲的是,在此线程中,如此简单且定义明确的东西变成了“基于观点”。

HTTP服务器仅知道“实体”,它是任何内容的抽象,可以是静态网页,搜索结果列表,其他实体列表,某物的json描述,媒体文件,等

每个此类实体都可以通过唯一的URL进行标识,例如

  • / user / 9-一个实体:USER ID = 9
  • / users-一个实体:所有用户的列表
  • /media/x.mp3-单个实体:名为x.mp3的媒体文件
  • / search-单个实体:基于查询参数的动态内容

如果服务器通过给定的URL找到资源,则其内容是什么无关紧要-2G数据,空,{},[]-只要存在,它将是200。但是,如果服务器不知道该实体,则可能会返回404“未找到”。

开发人员似乎感到困惑,他们认为,如果应用程序具有针对特定路径形状的处理程序,那应该不是错误。在HTTP协议看来,只要在服务器内部没有与之匹配的实体,服务器内部发生的事件(即默认路由器是否响应还是特定路径形状的处理程序)都没有关系。请求的URL(请求的MP3文件,网页,用户对象等),该URL将返回有效内容(空或其他),它必须为404(或410等)。

另一个困惑点似乎是围绕“没有数据”和“没有实体”。前者与实体的内容有关,后者与实体的存在有关。

示例1:

  • 没有数据:/ users返回200 OK,正文:[]因为没有人注册
  • 没有实体:/ users返回404,因为没有路径/ users

示例2:

  • 没有数据:/ user / 9返回200 OK,正文:{},因为用户ID = 9从未输入过他/她的个人数据
  • 没有实体:/ user / 9返回404,因为没有用户ID = 9

示例3:

  • 没有数据:/ search?name = Joe返回200 OK [],因为数据库中没有Joe。
  • 没有实体:/ search?name = Joe返回404,因为没有路径/ search

答案 9 :(得分:4)

现有答案未详细说明的是,无论您使用路径参数还是查询参数,这都有所不同。

  • 对于路径参数,该参数是资源路径的一部分。对于/users/9,响应应该为404,因为找不到该资源。 /users/9是资源,结果是一元的,或者是错误的,它不存在。这不是一个单子。
  • 对于查询参数,该参数不属于资源路径。对于/users?id=9,响应应该为204,因为找到了资源/users,但是它不能返回任何数据。资源/users存在,结果为n元,即使为空也存在。如果id是唯一的,则此一个单子。

使用路径参数还是查询参数取决于用例。我更喜欢使用路径参数作为强制性,规范性或标识性参数,而将查询参数作为可选性,非规范性或归属性参数(例如分页,整理语言环境和内容)。在REST API中,我将使用/users/9而不是/users?id=9,特别是因为可能会嵌套以获取像/users/9/ssh-keys/0这样的“子记录”来获取第一个公共ssh密钥或/users/9/address/2获取第三个邮政地址。

我更喜欢使用404。这是为什么:

  • 对一元(1个结果)和n元(n个结果)方法的调用不应无故改变。如果可能,我希望使用相同的响应代码。预期结果的数量当然是不同的,例如,您希望主体是一个对象(一元)或对象数组(n元)。
  • 对于n元,我将返回一个数组,如果没有结果,我将不返回没有集合(没有文档),我将返回一个空集合(一个空文档,例如JSON中的空数组或空XML中的元素)。也就是说,它仍然是200,但记录为零。除了身体上,没有其他理由将这些信息放在电线上。
  • 204类似于void方法。我不会将其用于GET,而不会用于POSTPUTDELETE。对于GET,标识符是查询参数而不是路径参数的情况,我是一个例外。
  • 找不到记录就像NoSuchElementExceptionArrayIndexOutOfBoundsException之类,是由客户端使用不存在的id引起的,因此,这是客户端错误。
  • 从代码角度来看,获取204意味着可以避免代码中的其他分支。它会使客户端代码复杂化,并且在某些情况下还会使服务器代码复杂化(取决于您使用实体/模型单子还是普通实体/模型;我强烈建议远离实体/模型单子,它可能会导致令人讨厌的错误,在这些错误中,由于单子操作,您认为操作成功,当您本应返回其他内容时返回200或204)。
  • 更容易编写和理解客户端代码,如果2xx表示服务器执行了客户端请求的操作,而4xx表示服务器未执行客户端请求的操作,这是客户端的错误。没有向客户提供该客户要求的记录是客户的错,因为客户要求的ID不存在。

最后但并非最不重要的:一致性

  • GET /users/9
  • PUT /users/9DELETE /users/9
如果成功更新或删除,

PUT /users/9DELETE /users/9已经必须返回204。那么,如果用户9不存在,他们应该返回什么?根据所使用的HTTP方法,将相同的情况显示为不同的状态代码是没有意义的。

此外,这不是一个规范性的原因,而是一种文化原因:如果将204用于GET /users/9,那么该项目中接下来发生的事情就是有人认为返回204对n有好处。 -ary方法。这使客户端代码变得复杂,因为客户端现在不仅要检查2xx然后解码主体,还必须专门检查204,然后跳过对主体的解码。芽客户该怎么办?创建一个空数组?那为什么不把它放在电线上呢?如果客户端创建空数组,则204是愚蠢压缩的一种形式。如果客户端改用null,则会打开另一种完全不同的蠕虫病毒罐。

答案 10 :(得分:3)

Twitter使用404和自定义错误消息,例如“找不到数据”。

参考:https://developer.twitter.com/en/docs/basics/response-codes.html

答案 11 :(得分:3)

204更合适。特别是当你有一个警报系统来确保网站安全时,404在这种情况下会引起混淆,因为你不知道某些404警报是后端错误或正常请求但响应为空。

答案 12 :(得分:2)

我说,两者都不合适。 如前所述 - 例如通过@anneb,我也认为部分问题源于使用HTTP响应代码来传输与RESTful服务相关的状态。 REST服务必须通过REST特定代码来传输有关其自身处理的任何内容。

1

我认为,如果HTTP服务器找到任何准备好回答它被发送的请求的服务,它就不应该响应HTTP 404 - 最后,服务器找到了一些东西 - 除非由处理请求的服务明确告知。

让我们暂时假设以下网址:http://example.com/service/return/test

  • 案例A是服务器“只是在文件系统上查找文件”。如果不存在,404是正确的。同样如此,如果它要求某种服务准确传递此文件,并且该服务告诉它该名称不存在。
  • 在情况B中,服务器不使用“真实”文件,但实际上该请求由某些其他服务处理 - 例如某种模板系统。在这里,服务器不能对资源的存在做出任何声明,因为它对此一无所知(除非由处理它的服务告知)。

如果服务没有明确要求不同行为的任何响应,HTTP服务器只能说3件事:

  • 503如果应该处理请求的服务没有运行或响应;
  • 200否则,因为HTTP服务器实际上可以满足请求 - 无论服务稍后会说什么;
  • 400404表示没有此类服务(与“存在但离线”相对)并且未找到任何其他内容。

2

回到手头的问题:我认为最干净的方法是不使用HTTP任何响应代码,除了之前的说法。如果服务存在并响应,则HTTP代码应为200。 响应应包含服务在单独标头中返回的状态 - 此处,服务可以说

  • REST:EMPTY例如如果它被要求搜索某事。并且研究结果是空的;
  • REST:NOT FOUND如果是专门问某事的话。 “ID-like” - 是ID或条目号24等的文件名或资源 - 并且找不到该特定资源(通常,请求并找不到一个特定资源);
  • REST:INVALID如果服务无法识别发送请求的任何部分。

(请注意,我故意用“REST:”作为前缀,以标记这些事实,虽然这些可能与HTTP响应代码具有相同的值或措辞,但它们是完全不同的)

3

让我们回到上面的网址并检查案例B,其中 service 向HTTP服务器指示它本身不处理此请求,但将其传递给SERVICE 。 HTTP仅提供由SERVICE传回的内容,它不知道有return/test部分的任何内容,因为它由SERVICE提供。如果该服务正在运行,HTTP应该返回200,因为确实找到了来处理请求。

SERVICE返回的状态(如上所述,希望在单独的标题中看到)取决于实际预期的操作:

  • 如果return/test要求提供特定资源:如果存在,请将其返回状态为REST:FOUND;如果该资源不存在,则返回REST:NOT FOUND;这可以延伸到REST:GONE,如果我们知道它曾经存在且不会返回,REST:MOVED如果我们知道它已经好莱坞了
  • 如果return/test被视为搜索或类似过滤的操作:如果结果集为空,则返回请求类型中的空集,状态为REST:EMPTY;请求类型的一组结果,状态为REST:SUCCESS
  • 如果return/test不是SERVICE重新识别的操作:如果完全错误则返回REST:ERROR(例如retrun/test之类的拼写错误)或REST:NOT IMPLEMENTED如果计划以后再使用。

4

这种区别比混合两种不同的东西要清晰得多。如果有的话,它还可以使调试更容易,处理也稍微复杂一些。

  • 如果返回HTTP 404,服务器会告诉我“我不知道你在说什么”。虽然我的请求的REST部分可能是完全正常的,但我在所有错误的地方寻找标准马赫。
  • 另一方面,HTTP 200和REST:ERR告诉我我得到了服务但在我的服务请求中做错了。
  • 从HTTP 200和REST:EMPTY,我知道我没有做错任何事 - 正确的服务器,服务器找到了服务,对服务提出了正确的请求 - 但搜索结果是空的。

摘要

问题和讨论源于以下事实:HTTP响应代码用于表示其结果由HTTP提供服务的服务的状态,或表示某事物。这不在HTTP服务器本身的范围内。 由于这种差异,这个问题无法回答,所有意见都需要经过大量讨论。

服务而不是HTTP服务器处理的请求的状态真的不应该(RFC 6919)由HTTP响应代码给出。 HTTP代码应该(RFC 2119)只包含HTTP服务器可以从其自己的范围给出的信息:即,是否发现服务处理请求。

相反,应该使用不同的方式告诉消费者有关实际处理请求的服务的请求状态。我的建议是通过特定标题这样做。理想情况下,标题的名称及其内容都遵循一个标准,使消费者可以轻松使用这些答案。

答案 13 :(得分:2)

根据RFC7231-page59(https://tools.ietf.org/html/rfc7231#page-59) 404状态码响应的定义是:

6.5.4。找不到404    404(未找到)状态代码表示原始服务器已执行    找不到目标资源的当前表示或找不到    愿意透露存在。 404状态码不    指出这种缺乏代表性是暂时的还是    常驻;如果410(Gone)状态代码优于404,    原始服务器大概通过某种可配置的方式知道    这种情况很可能是永久的。    默认情况下,404响应是可缓存的;即,除非另有说明    由方法定义或显式缓存控件指示(请参见    [RFC7234]第4.2.2节)。

引起怀疑的主要是上面上下文中的资源定义。 根据同一RFC(7231),资源的定义为:

资源: HTTP请求的目标称为“资源”。 HTTP不    限制资源的性质;它仅定义一个接口    可能用于与资源进行交互。每个资源是    由统一资源标识符(URI)标识,如    [RFC7230]的2.7节。    客户端构造HTTP / 1.1请求消息时,它将发送    (第5.3节的定义    [RFC7230]。收到请求后,服务器将重建一个    目标资源的有效请求URI(第5.5节    [RFC7230]。    HTTP的一个设计目标是将资源标识与    请求语义,这可以通过授予请求来实现    请求方法中的语义(第4节)和一些    请求修改标头字段(第5节)。如果有冲突    在方法语义和URI隐含的任何语义之间    本身,如第4.2.1节所述,方法语义采用    优先。

因此,据我了解,不应在成功的GET请求中使用404状态代码,结果为空。(例如:对于特定过滤器没有结果的列表)

答案 14 :(得分:2)

问题出现后,您不应该使用404为什么?

基于RFC 7231,正确的状态码为204

在上面的答案中,我注意到1个小误会:

1.-资源为:/users

2.- /users/8不是资源,它是:具有路由参数/users的资源8,使用者可能无法注意到它并且不知道区别,但是发布者确实并且必须知道这一点!...因此他必须向消费者返回准确的答复。期间。

如此:

基于RFC:404错误,因为找到了资源/users,但是使用参数8执行的逻辑未找到要返回的任何content作为响应,因此正确的答案是:204

这里的要点是:404甚至没有找到用于处理内部逻辑的资源

204是一个:我找到了资源,执行了逻辑,但是我没有使用route参数中给定的条件找到任何数据,因此我什么也无法返回。很抱歉,请验证您的条件,然后再次致电给我。

200:好的,我找到了资源,执行了逻辑(即使当我不强制返回任何东西时)也可以随意使用它。

205 :( GET响应的最佳选择)我找到了资源,执行了逻辑,为您准备了一些内容,请很好地使用,哦,如果您要共享此内容在视图中,请刷新视图以显示它。

希望有帮助。

答案 15 :(得分:2)

这是一个在这种情况下苦苦挣扎的开发商的补充。您可能已经注意到,当不存在特定资源时,是否返回404或200或204始终是一个讨论。上面的讨论表明,该主题非常混乱且基于观点(尽管存在http状态代码标准)。 我个人建议,因为您尚未决定如何在您的API定义中确定文档,因为我尚未提到。当然,当客户端开发人员使用您特定的“ REST” api来使用他/她对Rest的知识时,他/她会想到这一点,并期望您的api以这种方式工作。我想你看到了陷阱。因此,我使用了一个自述文件,在其中明确定义了在哪些情况下使用哪种状态码。这并不意味着我使用了一些随机的定义。我一直尝试使用该标准,但为避免此类情况,我记录了我的用法。客户可能会认为您在某些特定情况下错了,但正如所记录的那样,不需要进行额外的讨论就可以为您和开发人员节省时间。

关于Ops问题的一句话:404是我回想开始开发后端应用程序时总是想到的代码,并且在我的控制器路由中配置了错误的内容,以便不调用我的Controller方法。考虑到这一点,我认为如果请求确实到达了Controller方法中的代码,则客户端执行了有效请求并找到了请求端点。因此,这表示不使用404。如果未找到db查询,则返回200,但正文为空。

答案 16 :(得分:2)

TL;DR:

  • 如果在 /users/9 上没有找到用户,您应该返回 404。
  • 如果在 /users?id=9 处未找到用户,则应返回 204。

长版:

在查看我自己对这些状态代码的使用情况以及这篇文章中的示例后,我不得不说,如果在 /users/9 的 url 中未找到用户 #9,则 404 是适当的响应。

在我今天的系统中,我们的 Application Insights 日志充满了数百个记录的 404 错误,这些错误使我们的日志变得混乱,因为我们决定在 /users/9 没有相关数据时返回 404。然而,这并不意味着我们在设置响应时的方法不正确,相反,我认为这意味着我们在设置路由时的方法不正确。 >

如果您希望端点获得大量流量并且担心记录太多 404 错误,您应该更改路由以符合您想要的状态代码,而不是强制使用不适当的状态代码用过。

此后我们决定对我们的代码进行 2 处更改:

  1. 通过期待 /users?id=9
  2. 改变我们的上班路线
  3. 将我们的错误代码更改为 204,这样 404 就不会填满我们的 AI 日志。

归根结底,API 的架构师需要了解将如何使用他们的 API 以及适合该用例的路由类型。

我相信在 /users/9 的情况下,您请求的资源是用户本身,用户 #9;您要求服务器使用标识为“9”的对象进行响应,该对象恰好存在于包含“用户”一词的路径中。如果没有找到那个对象,你应该得到一个 404。

但是,如果您调用 /users?id=9,我觉得您请求的资源是 Users 控制器,同时还提供了更多的特殊性,因此它不会返回所有用户的完整列表。您要求服务器响应特定用户,该用户可以通过查询字符串中定义的 ID 号进行识别。因此,如果没有找到数据,我认为 204 是适用的,因为即使没有找到数据,控制器也是如此。

查询字符串方法还完成了一些我认为不仅对 API 开发人员而且对客户端开发人员(尤其是继承此代码或调用它的代码的初级开发人员或未来开发人员)有帮助的事情:

任何涉及到的人都会立即清楚 9 是一个 ID,而不是某个任意数字。在这样一个基本示例中,这一点似乎没有实际意义,但请考虑使用 GUID 作为行 ID 或允许您按人名获取数据的系统,甚至是返回特定邮政编码而不是行 ID 信息的系统.如果所有参与的开发人员一目了然地知道该标识参数是名字、姓氏、全名,还是邮政编码而不是 ID,那么他们将非常有用。

答案 17 :(得分:1)

为什么不使用410?它表明请求的资源不再存在,并且在您的情况users/9中,客户端永远不会请求该资源。

您可以在此处找到有关410的更多详细信息:https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html

答案 18 :(得分:1)

这类事情可能是主观的,双方都有一些有趣而多样的论据。但是[我认为] 为丢失的数据返回404错误。为了简化说明,下面是一个简化的描述:

  • 请求:请问我可以提供一些数据吗?
  • 资源(API端点):我会为您处理该请求,在此处[发送潜在数据的响应]

一切正常,找到了端点,并且找到了表和列,因此查询了数据库,并“成功”返回了数据!

现在-“成功响应”是否包含数据并不重要,您要求对“潜在”数据进行响应,并且满足了“潜在”数据的响应。空,空等是有效数据。

200仅表示我们所做的任何请求均成功。我正在请求数据,HTTP / REST没什么问题,并且由于返回了数据(尽管为空),所以我的“数据请求”成功了。

返回200,让请求者在每种情况下都可以保证处理空数据!

考虑以下示例:

  • 请求:查询用户ID为1234的“违规”表
  • 资源(API端点):返回响应,但数据为空

此数据为空是完全有效的。这意味着用户没有违规行为。这是200,因为它全部有效,然后我可以这样做:

  

您没有违反规定,有蓝莓松饼!

如果您认为这是404,则说明什么?找不到用户的违规行为?现在,从语法上讲这是正确的,但是在REST世界中,关于请求的成功或失败只是不正确的。可以成功找到该用户的“违规”数据,违规为零-代表有效状态的实数。


[厚脸皮音符..]

在标题中,您下意识地同意200是正确的答案:

  

对于有效请求但数据为空的正确的REST响应代码是什么?


无论主观性和棘手的选择如何,在选择使用哪种状态代码时,都需要考虑以下几点:

  1. 一致性。如果您将404用于“无数据”,则每次 都使用它。响应将不返回任何数据。
  2. 请勿将同一状态用于多个含义。如果在找不到资源(例如,API端点不存在等)时返回404,则也将其用于没有返回数据的情况。这只会使处理响应变得很痛苦。
  3. 仔细考虑上下文。什么是“要求”?您是在说什么呢?

答案 19 :(得分:1)

正如许多人所说,404具有误导性,并且它不允许客户端区分请求uri是否不存在,或者请求的uri无法获取请求的资源。

预期200状态包含资源数据-因此这不是正确的选择。 状态204完全意味着其他内容,不应将其用作GET请求的响应。

由于其他原因,所有其他现有状态均不适用。

我已经在多个地方反复讨论了这个主题。对我来说,很明显,要消除围绕该主题的困惑,需要有专门的成功状态。诸如“ 209 -无资源可显示”之类的东西。

这将是2xx状态,因为未找到ID不应被视为客户端错误(如果客户端知道服务器DB中的所有内容,他们将不需要向服务器询问任何内容,不是吗? )。这种专用身份将解决使用其他身份辩论的所有问题。

唯一的问题是:如何获得RFC接受它作为标准?

答案 20 :(得分:0)

如果仅由于没有响应数据而返回,则

404对于任何客户端来说都会非常混乱。

对于我来说,带有空主体的响应代码200足以理解一切都完美,但是没有符合要求的数据。

答案 21 :(得分:0)

根据Microsoft:Controller action return types in ASP.NET Core web API,向下滚动到底部,您会发现以下关于404的内容与数据库中找不到的对象有关。在这里,他们建议404适用于空数据。

enter image description here

答案 22 :(得分:0)

使用通用枚举对响应内容进行编码,允许客户端切换它并相应地分叉逻辑。我不确定您的客户如何区分“未找到数据”404和“未找到网络资源”404之间的区别?您不希望有人浏览到用户 Z / 9并让客户端感到惊讶,就好像请求有效但没有返回数据。

答案 23 :(得分:0)

在这种情况下,Ruby on Rails的响应是404 Not Found

404 Not Found更合适。

答案 24 :(得分:0)

我不认为 404 是正确的响应。

如果你使用404,你怎么知道是没有找到api,还是没有找到你数据库中的记录?

根据您的描述,我会使用 200 OK,因为您的 api 执行了所有逻辑而没有任何问题。它只是在数据库中找不到记录。因此,这不是 API 问题,也不是数据库问题,而是您的问题,您认为记录存在但不存在。为此,API 执行成功,数据库查询执行成功,但没有发现任何返回。

出于这个原因,在这种情况下,我会使用

200 正常

空响应,如数组的 [] 或对象的 {}。

答案 25 :(得分:0)

根据w3,我相信以下几点:

2xx:

<块引用>

此类状态码表示客户端的请求已成功接收、理解和接受。

4xx:

<块引用>

4xx 类状态代码适用于客户端似乎出错的情况。

如果客户端请求 /users,并且有用户要列出,则响应代码将为 200 OK(客户端请求有效)。

如果客户端请求 /users 并且它没有数据,响应代码仍然是 200 OK
请求的实体/资源是一个用户列表,该列表存在,只是其中没有任何用户(如果给出空响应,可以使用 204 No Content,尽管我认为空列表 [] 会更好)。
客户端请求有效,并且资源确实存在,因此 4xx 响应代码在这里没有意义。

另一方面,如果客户端请求 /users/9,而该用户不存在,则客户端通过请求不存在的资源(用户)而犯了错误.在这种情况下,用 404 Not Found 回答是有意义的。