users/9
,但是没有ID为9的用户。
最合适的响应代码是哪个?
- 200 OK
- 202 Accepted
- 204 No Content
- 400 Bad Request
- 404 Not Found
users/9
,但是没有ID为9的用户。
最合适的响应代码是哪个?
编辑:哇,这引起了很多争议。以下是反对404的另一个论点:严格从HTTP规范(RFC7231)的角度来看,404甚至并不意味着资源不存在。它仅表示服务器没有所请求的资源的当前表示,并且这可能只是暂时的。因此,从HTTP规范的角度来看,404在有关所请求的内容不存在方面本质上是不可靠的。 如果要明确表示所请求的内容不存在,请不要使用404。
503 服务不可用
。 - Chris Pfohl/users
路由,而是/users/9
,即“被称为#9的用户”),所以你的“空结果集”比较没有意义。404表示该对象不存在。 - Chris PfohlTL;DR: 使用 404
详见这篇博客。它对此有很好的解释。
博客评论对204
的总结:
204 No Content
对于浏览器而言并不是非常有用(尽管按照HTTP规范,浏览器确实需要将其视为“不要更改视图”的响应代码)。204 No Content
在ajax Web服务中非常有用,因为可以在不必返回任何内容的情况下指示成功(特别是在不需要反馈的DELETE
或POST
等情况下)。因此,针对您的问题,您应该使用404
。在响应GET
请求时,204
是一种专门的响应代码,您不应经常向浏览器返回此代码。
其他响应代码甚至比204
和404
还不合适:
200
应该与您成功获取的任何内容一起返回。当您想获取的实体不存在时,这是不合适的。202
用于服务器已经开始处理对象但对象尚未完全准备好的情况。这里显然不是这种情况,您不会在响应GET
请求时开始或将要开始构建用户9。这样做会违反各种规则。400
用于响应格式错误的HTTP请求(例如,格式不正确的HTTP头、段错误顺序等)。这通常会由您使用的框架处理。除非您正在从头开始编写自己的服务器,否则您不必处理此问题。编辑:新版RFC现在允许将400用于语义无效的请求。维基百科的HTTP状态代码描述特别有帮助。 您还可以在HTTP/1.1 RFC2616文档中查看相关定义,该文档可在 www.w3.org 获取。
204
响应代码(无内容)的内容。 - Chris Pfohl/badurl
还是/user/9
(当不存在这样的用户时),都是如此。开发人员可以通过添加比“未找到”更好的原因短语来帮助解释问题,但这并非必需。 - Chris Pfohl服务器未找到与请求URI匹配的任何内容
,我倾向于不同意(虽然不会投反对票,请继续阅读)。事实上,Web或应用程序服务器已找到与请求URI匹配的操作,但数据库服务器没有。然而,它也说“当[...]没有其他响应适用时,通常使用此状态代码”,因此我认为这在某种程度上证实了它的使用方式(即使我不同意或者不喜欢它)。 - Daevin起初,我认为返回状态码204是有道理的,但经过讨论后,我相信404才是唯一正确的响应。考虑以下数据:
用户:John,Peter
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
一些背景:
搜索返回一个数组,只是没有匹配项,但它有内容:一个空数组。
404 当然最为人所知的是 URL 不被请求的服务器支持,但缺少资源实际上是相同的。
即使 /users/:name
与 users/kyle
匹配,用户 Kyle 也不是可用资源,因此仍然适用 404。它不是一个搜索查询,而是一个动态URL的直接引用,所以它是404。
在评论中建议后,自定义404消息是帮助API使用者更好地区分完全未知路由和缺失实体的另一种方式。
无论如何,这是我的建议 :)
GET /usrs/john 404 Not found
。开发人员无法区分输错路径和缺失个人信息之间的区别。这就是为什么我提倡使用 GET /users/kyle 404 No such user
和 GET /usrs/john 404 Not found
。 - Chris Pfohl如果期望资源存在,但可能为空,我认为更容易的方式是获得一个表示为空的表述信息,而不是没有任何内容的204状态。
因此,我宁愿用 {"Items": []} 返回200 OK 的/things,而不是204状态,因为这样0项的集合就可以像有一项或多项的集合一样处理。
我建议保留204 No Content状态用于PUT和DELETE请求,因为对于这些请求来说,确实没有有用的表述信息。
如果/thing/9不存在,应返回404状态。
customers/1/addressbook
)访问资源不同,RPC的方式是调用类似于GetCustomerAddressBook
的端点,然后接收数据或者实质上是空值,不必过多担心HTTP的复杂性。两种方法都有优缺点。 - The Muffin Manitems: []
,因为该集合确实存在,但是它是空的。在这里使用204会非常令人困惑,因为它用于不应返回任何内容的API。当请求单个资源时,适当的HTTP状态码是404。 - nod在之前的项目中,我使用了404。如果没有用户9,则表示未找到该对象。因此404 Not Found是适当的。
对于对象存在但没有数据的情况,204 No Content 是适当的。我认为在您的情况下,对象不存在。
简而言之,
2xx:可选数据:格式正确的URI:标准不是URI的一部分:如果条件是可选的,可以在@RequestBody和@RequestParam中指定,应该返回2xx。例如:按名称/状态筛选
4xx:期望的数据:格式不正确的URI:条件是URI的一部分:如果条件是强制性的,只能在@PathVariable中指定,则应导致4xx。例如:按唯一ID查找。
因此,对于所问的情况:
"users/9" 应该是 4xx(可能是404)
但是对于 "users?name=superman" 应该是 2xx(可能是204)
/users/9
的情况下,响应应该是404
,因为没有找到该资源。在这种情况下,/users/9
是资源,结果是单一的或者是错误的,它不存在。这不是一个monad。/users?id=9
的情况下,响应应该是204
,因为已找到资源/users
,但它无法返回任何数据。资源/users
存在,结果是n元的,即使为空也存在。如果id
唯一,则这是一个monad。使用路径参数或查询参数取决于具体情况。我更喜欢将路径参数用于必填、规范或标识参数,而将查询参数用于可选、非规范或属性参数(如分页、排序规则等)。在REST API中,我会使用/users/9
而不是/users?id=9
,特别是由于可能需要嵌套获取"子记录",例如/users/9/ssh-keys/0
获取第一个公共ssh密钥,或者/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 方法不同的情况下,用不同的状态代码表示相同的情况是毫无意义的。
GET /users/9
中使用 204
,项目中下一步会发生的事情是有人认为返回 204
对于 n 元方法来说是好的。这会使客户端代码变得复杂,因为客户端现在不仅需要检查 2xx
然后对主体进行解码,还必须具体检查是否为 204
并在这种情况下跳过主体解码。但客户端该怎么做呢?创建一个空数组吗?为什么不把它放在网络上传输呢?如果客户端创建空数组,则 204
是一种愚蠢的压缩方式。如果客户端使用 null
,则会引起完全不同的问题。很遗憾,在这个讨论串中,一个如此简单和明确定义的东西却变成了“基于观点”的问题。
HTTP服务器只知道“实体”,这是任何内容的抽象,无论是静态网页、搜索结果列表、其他实体列表、某个事物的JSON描述、媒体文件等等。
每个这样的实体都应该可以通过唯一的URL进行识别,例如:
如果服务器能够通过给定的URL找到资源,那么它的内容是什么并不重要——2G的数据、null、{}、[]——只要它存在,就会返回200。但如果服务器不知道这样的实体,则期望返回404“未找到”。
一个困惑似乎来自开发人员认为,如果应用程序具有特定路径形状的处理程序,那么它就不应该是一个错误。在HTTP协议的眼中,服务器内部发生了什么(即默认路由器是否响应或特定路径形状的处理程序是否响应)并不重要,只要在服务器上没有与请求的URL匹配的实体(请求的MP3文件、网页、用户对象等),它必须是404(或410等)。
另一个令人困惑的问题似乎是关于“无数据”和“无实体”的区别。前者涉及实体的内容,而后者涉及其存在性。