例如,您为用户/9运行一个GET请求,但没有id为#9的用户。 哪个是最佳响应码?
200好了 202年接受 204无内容 400错误请求 404未找到
例如,您为用户/9运行一个GET请求,但没有id为#9的用户。 哪个是最佳响应码?
200好了 202年接受 204无内容 400错误请求 404未找到
当前回答
TL; diana:
如果在/users/9上没有找到用户,则应该返回404。 如果在/users中没有找到用户?如果Id =9,则应该返回204。
长版:
在回顾了我自己对这些状态代码的使用和本文中的示例之后,我不得不说,如果在/users/9的url上没有找到用户#9,404是适当的响应。
今天在我的系统中,我们的Application Insights日志中充满了数百条记录的404错误,这使我们的日志变得混乱,因为我们决定在/users/9没有相关数据时返回404错误。然而,这并不意味着我们在设置响应时的方法是不正确的,相反,我认为这意味着我们在设置路由时的方法是不正确的。
如果您希望端点获得大量流量,并且担心记录太多404错误,那么您应该更改路由以符合您想要的状态码,而不是强制使用不适当的状态码。
我们已经决定对我们的代码做2个更改:
通过expect /users改变我们的工作路线?id = 9 将我们的错误代码更改为204,这样404就不会填满我们的AI日志。
最后,API的架构师需要了解他们的API将如何被使用,以及哪种路由将适合于该用例。
我相信在/users/9的情况下,您请求的资源是用户本身,用户#9;您要求服务器响应一个标识为“9”的对象,该对象恰好存在于包含单词“user”的路径中。如果没有找到该对象,则应该得到404。
但是,如果调用/users?id=9,我觉得你所请求的资源是用户控制器,同时也提供了更多的专一性,这样它就不会返回所有用户的完整列表。您要求服务器响应一个可以通过查询字符串中定义的ID号识别的特定用户。因此,如果没有找到数据,204对我来说是有意义的,因为即使没有找到数据,控制器也是。
查询字符串方法还完成了一些我认为不仅有助于API开发人员,而且有助于客户端开发人员(特别是初级开发人员或继承这段代码或调用它的代码的未来开发人员):
It becomes immediately clear to anyone involved that 9 is an ID, not some arbitrary number. This point may seem moot in such a basic example, but consider a system that uses GUIDs as row ID's or allows you to get data by a person's name, or even a system that is returning info for specific ZIP/postal codes instead of row ID's. It would be useful for all developers involved if, at a glance, they knew whether that identifying parameter was a first, last, full name, or a ZIP/postal code instead of an ID.
其他回答
我们现在看到的是两种范式之间的紧张关系。
在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将(正确地)表明它不存在。)
根据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请求,结果为空。(例如:一个没有特定过滤器结果的列表)
起初,我认为204是有意义的,但经过讨论,我相信404是唯一真正正确的回答。考虑以下数据:
用户:约翰,彼得
METHOD URL STATUS RESPONSE
GET /users 200 [John, Peter]
GET /users/john 200 John
GET /unknown-url-egaer 404 Not Found
GET /users/kyle 404 User Not found
GET /users?name=kyle` 200 []
DELETE /users/john 204 No Content
背景知识:
the search returns an array, it just didn't have any matches but it has content: an empty array. 404 is of course best known for url's that aren't supported by the requested server, but a missing resource is in fact the same. Even though /users/:name is matched with users/kyle, the user Kyle is not available resource so a 404 still applies. It isn't a search query, it is a direct reference by a dynamic url, so 404 it is. After suggestions in the comments, customizing the message of the 404 is another way of helping out the API consumer to even better distinguish between complete unknown routes and missing entities.
不管怎样,我的意见。
这个话题中的答案(在撰写本文时已经有26个)完美地说明了开发人员理解他们正在使用的构造的语义是多么重要。
如果不理解这一点,那么响应状态代码是响应的属性而不是其他属性就不明显了。这些代码存在于响应的上下文中,它们在此上下文中之外的含义是未定义的。
响应本身就是请求的结果。请求对资源进行操作。资源、请求、响应和状态代码是HTTP的结构,就HTTP而言:
HTTP提供了与资源(第2节)交互的统一接口,无论其类型、性质或实现如何,通过操作和传输表示(第3节)。
换句话说,响应状态码的范围受到一个接口的限制,该接口只关心一些目标资源,并处理用于与这些资源交互的消息。服务器应用程序逻辑超出了范围,您使用的数据也不重要。
当使用HTTP时,它总是与资源一起使用。资源被以太转移或操纵。在任何情况下,除非我们在量子世界中,资源要么存在要么不存在,不存在第三种状态。
如果发出HTTP请求来获取(传输)资源的表示(如本问题中所示),而资源不存在,则响应结果应该显示一个带有相应404代码的失败。目标-获取表示-没有达到,资源没有找到。在HTTP上下文中不应该有对结果的其他解释。
RFC 7231超文本传输协议(HTTP/1.1):语义和内容,在这里多次提到,但主要是作为状态码描述的参考。我强烈建议通读整个文档,而不仅仅是第6节,以便更好地理解HTTP接口及其组件的作用域和语义。
正如许多人所说的,404会误导客户端,如果请求uri不存在,或者请求的uri不能获取请求的资源,它不允许客户端进行区分。
200状态被期望包含资源数据——所以它不是正确的选择。 204状态意味着完全不同的东西,不应该用作GET请求的响应。
由于这样或那样的原因,所有其他现有状态都不适用。
我看到这个话题在很多地方被反复讨论。对我来说,很明显,要消除围绕这个话题的困惑,就需要一个专门的成功状态。比如“209 -没有资源显示”。
这将是一个2xx状态,因为找不到ID不应该被认为是客户端错误(如果客户端知道服务器DB中的所有内容,它们就不需要向服务器询问任何事情,不是吗?)这个专用状态将解决所有与使用其他状态争论的问题。
唯一的问题是:我如何让RFC接受这个标准?