例如,您为用户/9运行一个GET请求,但没有id为#9的用户。 哪个是最佳响应码?
200好了 202年接受 204无内容 400错误请求 404未找到
例如,您为用户/9运行一个GET请求,但没有id为#9的用户。 哪个是最佳响应码?
200好了 202年接受 204无内容 400错误请求 404未找到
当前回答
根据RFC7231 -第59页(https://www.rfc-editor.org/rfc/rfc7231#page-59) 404状态码响应的定义是:
6.5.4. 404 Not Found The 404 (Not Found) status code indicates that the origin server did not find a current representation for the target resource or is not willing to disclose that one exists. A 404 status code does not indicate whether this lack of representation is temporary or permanent; the 410 (Gone) status code is preferred over 404 if the origin server knows, presumably through some configurable means, that the condition is likely to be permanent. A 404 response is cacheable by default; i.e., unless otherwise indicated by the method definition or explicit cache controls (see Section 4.2.2 of [RFC7234]).
而引起质疑的主要是上述语境中对资源的定义。 根据同一个RFC(7231), resource的定义是:
Resources: The target of an HTTP request is called a "resource". HTTP does not limit the nature of a resource; it merely defines an interface that might be used to interact with resources. Each resource is identified by a Uniform Resource Identifier (URI), as described in Section 2.7 of [RFC7230]. When a client constructs an HTTP/1.1 request message, it sends the target URI in one of various forms, as defined in (Section 5.3 of [RFC7230]). When a request is received, the server reconstructs an effective request URI for the target resource (Section 5.5 of [RFC7230]). One design goal of HTTP is to separate resource identification from request semantics, which is made possible by vesting the request semantics in the request method (Section 4) and a few request-modifying header fields (Section 5). If there is a conflict between the method semantics and any semantic implied by the URI itself, as described in Section 4.2.1, the method semantics take precedence.
所以在我的理解中,404状态代码不应该用于成功的GET请求,结果为空。(例如:一个没有特定过滤器结果的列表)
其他回答
这样的事情可能是主观的,双方都有一些有趣和各种扎实的论点。然而,(在我看来)为丢失的数据返回404是不正确的。这里有一个简单的描述来说明这一点:
请求:能给我一些数据吗? 资源(API端点):我将在这里为您获取请求[发送潜在数据的响应]
没有问题,找到了端点,找到了表和列,因此查询了DB,并“成功”返回了数据!
现在,无论“成功响应”是否有数据都不重要,您要求“潜在”数据的响应,并且具有“潜在”数据的响应得到了满足。Null,空等是有效的数据。
200只代表我们的请求成功了。我正在请求数据,HTTP/REST没有任何问题,作为数据(尽管为空)返回我的“数据请求”是成功的。
返回一个200,让请求者在每个特定场景下处理空数据!
想想这个例子:
请求:查询用户ID为1234的“违规”表 资源(API端点):返回一个响应,但数据为空
此数据为空是完全有效的。这意味着用户没有违规行为。这是200,因为它是有效的,然后我可以这样做:
你没有违规,吃个蓝莓松饼!
如果你认为这是404,你在说什么?无法发现用户的违规行为?从语法上讲,这是正确的,但在REST世界中,成功或失败是关于请求的,这是不正确的。该用户的“违规”数据可以成功找到,没有违规-一个实数代表有效状态。
(厚颜无耻的注意。)
在你的标题中,你下意识地认为200是正确的回答:
对于有效请求但空数据,正确的REST响应代码是什么?
在选择使用哪种状态码时,抛开主观性和棘手的选择,以下是一些需要考虑的事情:
一致性。如果您使用404表示“无数据”,则在每次响应返回无数据时使用它。 同一个状态不要有多个意思。如果在没有找到资源时返回404(例如API端点不存在等),那么也不要因为没有返回数据而使用它。这只会让应对反应变成一种痛苦。 仔细考虑上下文。什么是“请求”?你说你想达到什么目的?
为了总结或简化,
2xx:可选数据:格式良好的URI: Criteria不是URI的一部分:如果Criteria是可选的,可以在@RequestBody和@RequestParam中指定,应该导致2xx。例如:按名称/状态过滤
标准是URI的一部分:如果标准是强制性的,只能在@PathVariable中指定,那么它应该导致4xx。例如:按唯一id查找。
对于所问的情况: "users/9"将是4xx(可能是404) 但是对于“用户”呢?Name =superman”应该是2xx(可能是204)
我们现在看到的是两种范式之间的紧张关系。
在HTTP和REST中,URL标识一个资源,该用户/9资源包括9。因此HTTP应该返回404—未找到。这就是RESTful的定义。之后,你可以PUT user/9,然后当你得到下一次,你得到数据。这就是HTTP和REST的设计方式。
在HTTP级别,如果你不想要404,一个更好的URL会是user?Id =9,那么用户部分将被找到,函数可以进行自己的处理并返回它自己的“未找到”通知。
然而,为了方便指定api,使用user/9格式“更好”。这给我们留下了一个困境:这个请求是通过HTTP发出的,(固执的)正确的HTTP答案是404;但是从API使用者的角度来看,框架可能不能很好地处理404,他们想要200 +一个“not found”有效负载(204对许多框架来说也可能是问题)。
这种将API放在已经定义的协议(HTTP)之上的做法导致了这种紧张。当设计成一个真正的RESTful API时(并且正确地处理404错误),这是没有问题的。
如果您认为user/9应该返回200 +“not found”,那么您使用user作为RPC端点,然后在URL的其余部分编码参数。我认为这是一种糟糕的设计,与RESTful规范相反,并且完全理解我们是如何走到这一步的。
如果你控制了两端,考虑到你的服务器和客户端框架的限制,就做那些有效的事情。
(想想在用户/9上执行HEAD请求的后果——你不能在响应中提供任何内容。200将表明用户/9确实存在,而404将(正确地)表明它不存在。)
根据w3的帖子,
200好了
请求成功。随响应返回的信息取决于请求中使用的方法
202年接受
请求已接受处理,但处理尚未完成。
204无内容
服务器已经完成了请求,但不需要返回实体主体,并且可能希望返回更新后的元信息。
400错误请求
由于语法错误,服务器无法理解请求。客户不应该在没有修改的情况下重复请求
401年未经授权
请求需要用户身份验证。响应必须包含一个WWW-Authenticate报头字段
404未找到
服务器没有发现任何与Request-URI匹配的内容。没有说明这种情况是暂时的还是永久的
我强烈反对404,而支持204或200的空数据。或者至少应该使用带有404的响应实体。
请求被接收并被正确处理——它确实触发了服务器上的应用程序代码,客户机可能没有犯任何错误,因此整个客户机错误代码(4xx)类可能不合适。
更重要的是,404的发生有很多技术原因。例如,应用程序在服务器上被暂时停用或卸载,代理连接问题等等。
当然,这种情况下存在5xx错误类,但实际上,受影响的中间件组件通常无法知道错误在它们这一边,然后只是假设错误在客户端,然后响应404而不是500/503。
因此,仅根据状态代码,客户端无法区分404(表示“您正在寻找的东西不存在”)和404(表示“有严重错误,请将此错误报告给运维团队”)。
This can be fatal: Imagine an accounting service in your company that lists all the employees that are due to an annual bonus. Unfortunately, the one time when it is called it returns a 404. Does that mean that no-one is due for a bonus, or that the application is currently down for a new deployment and the 404 is actually coming from the tomcat that it's supposed to be installed into, instead of from the application itself? These two scenarios yield the same status code, but they are fundamentally different in their meaning.
对于需要知道所请求的资源不存在而不是暂时不可访问的应用程序来说,没有响应实体的404几乎是行不通的。
此外,许多客户端框架通过抛出异常来响应404,而不询问进一步的问题。这迫使客户端开发人员捕获异常,对其进行评估,然后基于此决定是否将其记录为由监视组件捕获的错误,或者是否忽略它。这对我来说也不太好。
The advantage of 404 over 204 is that it can return a response entity that may contain some information about why the requested resource was not found. But if that really is relevant, then one may also consider using a 200 OK response and design the system in a way that allows for error responses in the payload data. Alternatively, one could use the payload of the 404 response to return structured information to the caller. If he receives e.g. a html page instead of XML or JSON that he can parse, then that is a good indicator that something technical went wrong instead of a "no result" reply that may be valid from the caller's point of view. Or one could use a HTTP response header for that.
尽管如此,我还是更喜欢204或200的空白回复。这样,请求的技术执行状态就与请求的逻辑结果分开了。2xx的意思是“技术执行ok,这就是结果,处理它”。
我认为在大多数情况下,应该让客户来决定一个空的结果是否可以接受。通过返回404而不返回响应实体(尽管技术执行正确),客户端可能决定将根本不是错误的情况视为错误。
Another perspective: From an operations point of view a 404 may be problematic. Since it can indicate a connectivity/middleware problem rather than a valid service response, i would not want a fluctuating number of "valid" 404s in my metrics/dashboards that might conceal genuine technical issues (e.g. a misconfigured proxy somewhere in the request routing) that should be investigated and fixed. This is further excarbated by some APIs even using 404 instead of 401/403 (e.g. gitlab does such a thing), to conceal the information that the request URI would have been valid but the request lacked authorization to access it. In this case too a 404 should be treated as a technical error and not as a valid "resource not found" result.
Edit: Wow, this has caused a lot of controversy. Here is another argument against 404: Strictly from a HTTP spec (RFC7231) point of view, 404 does not even mean that a resource does not exist. It only means that the server has no current representation of the requested resource available, and this even may be only temporary. So strictly by HTTP spec, 404 is inherently unreliable regarding the nonexistence of a requested thing. If you want to communicate that the requested thing positively does not exist, do not use 404.