例如,您运行的GET请求,users/9
但没有ID为#9的用户。哪个是最好的响应码?
- 200 OK
- 202接受
- 204没有内容
- 400错误的要求
- 找不到404
例如,您运行的GET请求,users/9
但没有ID为#9的用户。哪个是最好的响应码?
Answers:
TL; DR:使用 404
请参阅此博客。它解释得很好。
博客对204
以下内容的评论摘要:
204 No Content
作为浏览器的响应代码并不是非常有用(尽管根据HTTP规范,浏览器的确需要将其理解为“请勿更改视图”响应代码)。204 No Content
是但是,这可能要表示成功,而不必返回一些AJAX的Web服务是非常有用的。(特别是在案件喜欢DELETE
或POST
s表示不需要反馈)。因此,对您的问题的答案是404
在您的情况下使用。204
是专门的响应代码,您不应经常返回到浏览器来响应GET
。
其他响应代码比204
和更不合适404
:
200
应该随您成功获取的内容一起返回。当您要获取的实体不存在时,此方法不合适。202
服务器开始对某个对象进行工作但该对象尚未完全准备就绪时使用。当然这里不是这样。您尚未开始,也不会开始响应GET
请求构造用户9 。这违反了各种规则。400
用于响应格式不正确的HTTP请求(例如,格式错误的http标头,顺序错误的段等)。几乎可以肯定,这将由您使用的任何框架来处理。除非您是从头开始编写自己的服务器,否则不必处理这个问题。编辑:较新的RFC现在允许将400用于语义无效的请求。Wikipedia 对HTTP状态代码的描述特别有用。您还可以在www.w3.org上的HTTP / 1.1 RFC2616文档中查看定义。
204
响应代码(无内容)有关。
/badurl
或/user/9
不存在这样的用户,则为true 。开发人员可以通过添加比“未找到”更好的原因短语来提供帮助,但这不是必需的。
我强烈反对使用空数据的404,建议使用204或200。或至少一个应将响应实体与404一起使用。
接收到请求并对其进行了正确处理-它确实触发了服务器上的应用程序代码,因此不能真正说出这是一个客户端错误,因此整个客户端错误代码(4xx)类都不适合。
更重要的是,由于多种技术原因,可能会发生404。例如,该应用程序在服务器上被暂时停用或卸载,代理连接问题等等。因此,客户端无法区分表示“空结果集”的404和表示“找不到服务,请稍后再试”的404。
这可能是致命的:想象一下您公司中的会计服务,其中列出了所有由于年度奖金而产生的员工。不幸的是,一次调用它返回404。这是否意味着没有人要获得奖金,或者该应用程序当前已关闭以进行新的部署?
->对于关心数据质量的应用程序,没有响应实体的404因此几乎是不行的。
同样,许多客户端框架通过引发异常而没有询问其他问题来响应404。这迫使客户端开发人员捕获该异常,对其进行评估,然后基于该异常来决定是否将其记录为例如由监视组件接收到的错误或是否忽略它。对我来说那也不是很漂亮。
404与204相比,优点是它可以返回一个响应实体,该实体可能包含一些有关为何找不到所请求资源的信息。但是,如果这确实是相关的,则还可以考虑使用200 OK响应,并以允许对有效载荷数据进行错误响应的方式设计系统。或者,可以使用404响应的有效负载将结构化信息返回给调用方。如果他接收到例如可以解析的HTML页面而不是XML或JSON,那么这很好地表明了技术上的问题,而不是从呼叫者的角度来看可能是有效的“无结果”答复。或者可以为此使用HTTP响应标头。
不过,我还是更愿意使用空响应的204或200。这样,请求的技术执行状态与请求的逻辑结果是分开的。2xx表示“技术执行正常,这是结果,请处理”。
我认为在大多数情况下,应由客户决定是否可以接受空结果。通过返回404而没有响应实体,尽管有正确的技术执行,客户可以决定将情况视为简单无误的错误。
另一个快速类比:如果“ SQL查询未返回结果”,则返回404表示“未找到结果”就像抛出DatabaseConnectionException。它可以完成工作,但是有很多可能的技术原因会引发相同的异常,然后将其误认为有效的结果。
503 Service Unavailable
。
/users
路径,而是/users/9
“该用户被称为#9”),因此您的“空结果集”比较没有意义。404表示该对象不存在。
起初,我认为204是有意义的,但是在讨论之后,我相信404是唯一真正正确的答案。考虑以下数据:
用户:约翰,彼得
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
一些背景:
搜索返回一个数组,它没有任何匹配,但是有内容:一个空数组。
404当然是最著名的,所请求的服务器不支持url,但是实际上缺少的资源是相同的。
即使/users/:name
与匹配users/kyle
,用户Kyle也不可用资源,因此404仍然适用。它不是搜索查询,它是动态url的直接引用,所以404是。
无论如何,我的两分钱:)
如果期望该资源存在,但是它可能是空的,那么我认为仅用表示该事物为空的表示形式获得200 OK可能会更容易。
因此,我宁愿让/ things使用{“ Items”:[]}返回200 OK,而不返回204完全不包含任何东西,因为这样可以将具有0个项目的集合与具有一个或多个项目的集合视为相同还有更多项目。
我只剩下204个没有内容的PUT和DELETE,在这种情况下,实际上可能没有有用的表示形式。
如果/ thing / 9确实不存在,则使用404是合适的。
customers/1/addressbook
RPC方法不是像紧接动词和基于资源的url这样访问资源,而是通过调用终结点之类的方法GetCustomerAddressBook
来接收数据,或者本质上是null,而不必担心HTTP的复杂性。两者都有优点和缺点。
根据w3的帖子,
200 OK
该请求已成功。响应返回的信息取决于请求中使用的方法
202接受
该请求已被接受进行处理,但是处理尚未完成。
204没有内容
服务器已完成请求,但不需要返回实体,可能要返回更新的元信息。
400错误的要求
由于语法格式错误,服务器无法理解该请求。客户端不应不加修改地重复请求
401未经授权
该请求需要用户认证。响应必须包含WWW-Authenticate标头字段
找不到404
服务器找不到与Request-URI匹配的任何内容。没有迹象表明这种情况是暂时的还是永久的
204 No Content
在找不到结果时可能会返回。不404
,它已经为你的结果,但它没有内容..
总结或简化,
2xx:可选数据:格式正确的URI:条件不是URI的一部分:如果条件是可选的,则可以在@RequestBody中指定,并且@RequestParam应该导致2xx。示例:按名称/状态过滤
4xx:期望的数据:格式不正确的URI:条件是URI的一部分:如果条件是强制性的,只能在@PathVariable中指定,则应导致4xx。示例:按唯一ID查找。
因此,对于所询问的情况:“ users / 9”应为4xx(可能为404),但对于“ users?name = superman”应为2xx(可能为204)
有两个问题要问。标题中一个,示例中一个。我认为,这在一定程度上导致了对哪种反应合适的争议。
问题标题询问空数据。空数据仍然是数据,但与无数据不同。所以这建议请求一个结果集,即一个列表,也许是从/users
。如果列表为空,它仍然是列表,因此最适合使用204(无内容)。您刚刚询问了一个用户列表,并被提供了一个用户列表,它恰好没有任何内容。
而是提供的示例询问有关特定对象,用户, /users/9
。如果找不到用户#9,则不返回用户对象。您要求提供特定的资源(用户对象),但由于没有找到该资源而没有获得资源,因此使用404是合适的。
我认为解决此问题的方法是,如果您可以按期望的方式使用响应而无需添加任何条件语句,则使用204,否则使用404。
在我的示例中,我可以遍历一个空列表,而无需检查它是否具有内容,但是我不能在不破坏某些东西或添加检查以查看其是否为空的情况下在空对象上显示用户对象数据。
如果适合您,当然可以使用null对象模式返回一个对象,但这是另一个线程的讨论。
看了问题之后,您不应该使用404
为什么?
根据RFC 7231,正确的状态代码为204
在上面的答案中,我注意到1个小小的误解:
1.-资源是: /users
2.- /users/8
不是资源,这是:/users
具有route参数的资源8
,消费者可能无法注意到它并且不知道差异,但是发布者知道并且必须知道这一点!...因此他必须为消费者返回准确的响应。期。
所以:
基于RFC:404错误,因为/users
找到了资源,但是使用该参数执行的逻辑8
未找到任何content
要作为响应返回的逻辑,因此正确的答案是:204
这里的要点是:404
甚至找不到资源来处理内部逻辑
204
是:我找到了资源,执行了逻辑,但是我没有使用route参数中给定的条件找到任何数据,因此我无法向您返回任何信息。抱歉,请验证您的条件,然后再次致电给我。
200
:好的,我找到了资源,执行了逻辑(即使当我不强制返回任何东西时)也可以随便使用它并使用它。
205
:(GET响应的最佳选择)我找到了资源,执行了逻辑,为您准备了一些内容,请很好地使用,哦,如果您要在视图中共享此内容,请刷新视图显示它。
希望能帮助到你。
现有答案未详细说明的是,无论您使用路径参数还是查询参数,都将有所作为。
/users/9
,则响应应该是404
因为找不到该资源。/users/9
是资源,结果是一元或错误,不存在。这不是单子。/users?id=9
,则响应应该是204
因为/users
找到了资源,但它无法返回任何数据。资源/users
存在,结果为n元,即使为空也存在。如果id
是唯一的,则为单子。使用路径参数还是查询参数取决于用例。我更喜欢使用路径参数作为强制性,规范性或标识性参数,而将查询参数作为可选性,非规范性或归属性参数(例如分页,整理语言环境和内容)。在REST API中,由于可能会嵌套以获取“子记录”(如获取第一个公共ssh密钥或获取第三个邮政地址),因此我/users/9
不/users?id=9
特别使用。/users/9/ssh-keys/0
/users/9/address/2
我更喜欢使用404。这是为什么:
204
就像一种void
方法。我不会用它GET
,只为POST
,PUT
和DELETE
。GET
如果标识符是查询参数而不是路径参数,我会例外。NoSuchElementException
,ArrayIndexOutOfBoundsException
或者类似的东西,用一个id不存在,因此,它是一个客户端错误客户端造成的。204
意味着可以避免代码中的另一个分支。它会使客户端代码复杂化,并且在某些情况下还会使服务器代码复杂化(取决于您使用实体/模型单子还是普通的实体/模型;我强烈建议您远离实体/模型单子,因为这可能导致讨厌的错误,因为表示您认为该操作成功了,并且当您实际上应该返回其他值时返回200或204)。最后但并非最不重要的一点:一致性
GET /users/9
PUT /users/9
和 DELETE /users/9
PUT /users/9
并且在成功更新或删除的情况下DELETE /users/9
已经必须返回204
。那么,如果用户9不存在,他们应该返回什么?根据所使用的HTTP方法,将相同的情况显示为不同的状态代码是没有意义的。
此外,不是规范性的,而是一种文化上的原因:如果204
将其用于GET /users/9
项目中将要发生的下一件事是有人认为返回204
对n元方法有益。这使客户端代码变得复杂,因为2xx
客户端现在不仅要检查并解码主体,还必须专门检查204
并在这种情况下跳过对主体的解码。芽客户该怎么办?创建一个空数组?那为什么不把它放在电线上呢?如果客户端创建空数组,则204是愚蠢压缩的一种形式。如果客户端null
改为使用,则会打开一个完全不同的蠕虫罐。
Twitter使用404和自定义错误消息(例如“未找到数据”)。
参考:https : //developer.twitter.com/en/docs/basics/response-codes.html
204更合适。特别是当您具有警报系统以确保您的网站安全时,在这种情况下404会引起混乱,因为您不知道某些404警报是后端错误或正常请求,但响应为空。
我会说,两者都不是真正合适的。如前所述,例如@anneb,我也认为部分问题来自使用HTTP响应代码传输与RESTful服务相关的状态。REST服务必须说的关于其自身处理的任何内容都应通过REST专用代码进行传输。
我认为,如果HTTP服务器找到了准备好响应发送请求的任何服务,则不应使用HTTP 404进行响应-最终,服务器发现了某些内容-除非服务器明确指示处理请求的服务。
让我们假设以下URL: http://example.com/service/return/test
。
404
则是正确的。如果它要求某种服务来确切地传递此文件,并且该服务告诉它不存在该名称,则情况也是如此。如果服务没有任何明确要求其他行为的响应,则HTTP服务器只能说三点:
503
如果应该处理该请求的服务未运行或没有响应;200
否则,因为HTTP服务器实际上可以满足该请求–无论服务稍后将说什么;400
或404
表明没有此类服务(与“存在但离线”相对),没有发现其他任何内容。回到手头的问题:我认为最干净的方法是完全不使用HTTP,而不是以前说的任何响应代码。如果服务存在并且正在响应,则HTTP代码应为200。响应应在单独的标头中包含服务返回的状态–在这里,服务可以说
REST:EMPTY
例如,是否要求搜索某物。那项研究空无一物;REST:NOT FOUND
是否专门问某事。“类ID” –是文件名或按ID或条目号24的资源,等等。–并且未找到特定资源(通常,已请求并未找到一个特定资源);REST:INVALID
如果请求发送的任何部分未被服务识别。(请注意,我故意在它们前面加上“ REST:”以标记一个事实,尽管它们可能具有与HTTP响应代码相同的值或措词,但它们实际上完全不同)
让我们回到上面的URL并检查情况B,其中服务向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
计划以后再返回,则返回。这种区别比将两种不同的事物混合在一起要干净得多。如果有的话,这也将使调试更加容易,并且处理只会稍微复杂一些。
问题和讨论源于以下事实:HTTP响应代码用于表示其结果由HTTP进行服务的服务的状态,或表示sth。不在HTTP服务器本身的范围内。由于这种差异,问题无法得到解答,所有观点都需要进行大量讨论。
由服务而非HTTP服务器处理的请求的状态实际上不应该由HTTP响应代码给出(RFC 6919)。HTTP代码应该(RFC 2119)仅包含HTTP服务器可以从其自身范围提供的信息:即,是否找到该服务来处理请求。
取而代之的是,应该使用一种不同的方式来告知消费者关于实际正在处理请求的服务的请求状态。我的建议是通过特定的标头进行操作。理想情况下,标头名称及其内容均遵循一个标准,可使消费者轻松处理这些响应。
根据RFC7231-page59(https://tools.ietf.org/html/rfc7231#page-59),404状态码响应的定义为:
6.5.4。找不到404状态代码404(未找到)指示源服务器未找到目标资源的当前表示,或不愿意透露存在的一种表示形式。404状态代码不表示这种缺乏表示是暂时的还是永久的;如果原始服务器大概通过某种可配置的方式知道该条件很可能是永久性的,则与404相比,首选410(已消失)状态代码。默认情况下,404响应是可缓存的;即,除非方法定义或显式缓存控件另有说明(请参阅[RFC7234]的4.2.2节)。
引起怀疑的主要是上面上下文中的资源定义。根据同一RFC(7231),资源的定义为:
资源:HTTP请求的目标称为“资源”。HTTP不限制资源的性质;它仅定义了可用于与资源交互的接口。每个资源都由统一资源标识符(URI)标识,如[RFC7230]的2.7节所述。当客户端构造HTTP / 1.1请求消息时,它以[RFC7230] 5.3节中定义的各种格式之一发送目标URI。收到请求后,服务器将为目标资源重建有效的请求URI([RFC7230]的5.5节)。HTTP的一个设计目标是将资源标识与请求语义分开,这是通过将请求语义赋予请求方法(第4节)和一些请求修改标头字段(第5节)来实现的。
所以在我的理解中,不应在成功的GET请求中使用404状态代码,结果为空(例如:没有特定过滤器结果的列表)
这样的事情可能是主观的,双方都有一些有趣而多样的论据。但是[我认为] 对于缺少的数据返回404是不正确的。这里是一个简化的说明,以使这一点很清楚:
一切正常,找到了端点,并且找到了表和列,因此查询了数据库,并“成功”返回了数据!
现在-“成功响应”是否有数据都没有关系,您要求获得“潜在”数据的响应,并且满足了“潜在”数据的响应。空,空等是有效数据。
200只表示我们所做的任何请求都是成功的。我正在请求数据,HTTP / REST没什么问题,并且由于返回了数据(尽管为空),所以我的“数据请求”成功了。
返回200,让请求者根据每个特定情况的要求处理空数据!
考虑以下示例:
此数据为空是完全有效的。这意味着用户没有违规行为。这是200,因为它全部有效,然后我可以这样做:
您没有违规行为,有蓝莓松饼!
如果您认为这是404,则说明什么?找不到用户的违规行为?现在,从语法上讲这是正确的,但是在REST世界中,关于请求的成功或失败只是不正确的。可以成功找到该用户的“违规”数据,违规为零-代表有效状态的实数。
[厚脸皮音符..]
在标题中,您下意识地同意200是正确的答案:
有效请求但数据为空的正确REST响应代码是什么?
无论主观性和棘手的选择如何,在选择使用哪种状态代码时,都需要考虑以下几点:
为什么不使用410?这表明所请求的资源不再存在,并且在您的情况下,期望客户端永远不要请求该资源users/9
。
您可以在此处找到有关410的更多详细信息:https : //www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
令人遗憾的是,在此线程中,如此简单且定义明确的内容成为“基于观点的”。
HTTP服务器仅知道“实体”,它是任何内容的抽象,可以是静态网页,搜索结果列表,其他实体列表,某物的json描述,媒体文件等。
期望每个这样的实体都可以通过唯一的URL来标识,例如
如果服务器通过给定的URL查找资源,则其内容是什么都没关系-2G数据,null,{},[]-只要存在,它将是200。但是如果这样的实体是服务器未知,则可能返回404“未找到”。
开发人员似乎感到困惑,他们认为,如果应用程序具有针对特定路径形状的处理程序,那应该不是错误。在HTTP协议看来,只要在服务器内部没有与之匹配的实体,服务器内部发生的事件(即默认路由器是否响应还是特定路径形状的处理程序)都无关紧要。请求的URL(请求的MP3文件,网页,用户对象等),该URL将返回有效内容(空或其他),必须为404(或410等)。
另一个困惑点似乎是围绕“没有数据”和“没有实体”。前者与实体的内容有关,后者与实体的存在有关。
范例1:
范例2:
范例3:
根据Microsoft:ASP.NET Core Web API中的Controller动作返回类型,几乎向下滚动到底部,您发现以下有关404的内容与数据库中找不到的对象有关。他们在这里建议404适用于空数据。
如许多人所述,404具有误导性,并且它不允许客户端区分请求uri是否不存在,或者请求的uri是否无法获取请求的资源。
预期200状态包含资源数据-因此这不是正确的选择。204状态完全意味着其他内容,不应用作GET请求的响应。
由于一个或另一个原因,所有其他现有状态都不适用。
我已经看到这个主题在多个地方一遍又一遍地讨论。对我来说,很明显,要消除围绕该主题的困惑,需要专门的成功状态。类似于“ 209-无资源可显示”。
这将是2xx状态,因为未找到ID不应被视为客户端错误(如果客户端知道服务器DB中的所有内容,他们将不需要向服务器询问任何内容,不是吗?)。这种专用身份将解决使用其他身份辩论的所有问题。
唯一的问题是:如何获得RFC接受它作为标准?