IMB*_*IMB 289 rest api-design http
例如,您运行GET请求users/9但没有id为#9的用户.哪个是最好的响应代码?
Jen*_*urm 306
我强烈反对404赞成204或200空数据.
收到并正确处理了请求 - 它确实触发了服务器上的应用程序代码,因此无法确定它是客户端错误,因此整个客户端错误代码类(4xx)不合适.
更重要的是,404可能由于多种技术原因而发生.例如,在服务器上临时停用或卸载的应用程序,代理连接问题等等.因此,客户端无法区分表示"空结果集"的404和表示"无法找到服务的404,稍后再试".
这可能是致命的:想象一下您公司的会计服务,其中列出了年度奖金所需的所有员工.不幸的是,有一次它被调用它返回404.这是否意味着没有人应该获得奖金,或者应用程序当前是否因新部署而停止?
- >对于关心数据质量的应用程序,404因此几乎是不行的.
此外,许多客户端框架通过抛出异常而没有进一步的问题来响应404.这会强制客户端开发人员捕获该异常,对其进行评估,然后根据该异常将其记录为由例如监视组件拾取的错误或是否忽略它.这对我来说似乎也不太好看.
404超过204的唯一优势是它可以返回一个响应实体,该实体可能包含有关未找到所请求资源的原因的一些信息.但如果这确实相关,那么人们也可以考虑使用200 OK响应并以允许有效载荷数据中的错误响应的方式设计系统.或者,可以使用404响应的有效载荷将结构化信息返回给调用者.如果他收到例如一个html页面而不是他可以解析的XML或JSON,那么这是一个很好的指示,表明某些技术出错而不是从调用者的角度来看可能有效的"无结果"回复.或者可以使用HTTP响应头.
尽管如此,我仍然希望204或200有空响应.这样,请求的技术执行状态与请求的逻辑结果分开.2xx表示"技术执行正常,这是结果,处理它".
我认为在大多数情况下,应由客户决定是否可以接受空结果.尽管技术执行正确,但通过返回404,客户端可能会决定将案例视为错误而不是错误.
另一个快速类比:如果SQL查询没有返回任何结果,则返回404以查找"未找到结果"就像抛出DatabaseConnectionException.它可以完成工作,但是有很多可能的技术原因引发相同的异常,然后将其误认为是有效的结果.
Cri*_*ole 228
TL; DR:使用 404
请参阅此博客.它解释得非常好.
博客评论摘要204:
204 No Content 作为浏览器的响应代码并不是非常有用(尽管根据HTTP规范,浏览器确实需要将其理解为"不要更改视图"响应代码).204 No Content 是但是,这可能要表示成功,而不必返回一些AJAX的Web服务是非常有用的.(特别是在喜欢DELETE或POST不需要反馈的情况下).因此,您的问题的答案就是404在您的案例中使用.204是一个专门的响应代码,您不应该经常返回到浏览器以响应GET.
其他响应代码甚至不太适合204和404:
200应该与你成功取得的任何身体一起归还.当您提取的实体不存在时不合适.202当服务器开始处理对象但对象尚未完全准备好时使用.当然不是这里的情况.您尚未开始,也不会开始构建用户9以响应GET请求.这破坏了各种规则.400用于响应格式不正确的HTTP请求(例如格式错误的HTTP标头,错误排序的段等).这几乎肯定会由你正在使用的任何框架来处理.除非您从头开始编写自己的服务器,否则不必处理此问题.编辑:较新的RFC现在允许400用于语义无效的请求.维基百科对HTTP状态代码的描述特别有用.您还可以在www.w3.org上的HTTP/1.1 RFC2616文档中查看定义
Jus*_*ijn 47
起初,我认为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
Run Code Online (Sandbox Code Playgroud)
一些背景:
搜索返回一个数组,它只是没有任何匹配但它有内容:一个空数组.
404当然最为人所知的是所请求服务器不支持的url,但缺少的资源实际上是相同的.
即使/users/:name与之匹配users/kyle,用户Kyle也不是可用资源,因此404仍然适用.它不是搜索查询,它是动态网址的直接引用,因此404就是.
无论如何,我的两分钱:)
j00*_*057 23
如果预期资源存在,但它可能是空的,我会争辩说,通过表示该事物为空的表示可能更容易获得200 OK.
所以我宁愿/东西返回200 OK,{"Items":[]}而不是204,什么都没有,因为这样一个带有0个项目的集合可以被视为与一个集合的集合相同或者更多项目.
我只是为PUT和DELETE留下204 No Content,在那里可能没有实用的表示.
在/ thing/9确实不存在的情况下,404是合适的.
Max*_*Max 20
在以前的项目中,我使用了404.如果没有用户9,则找不到该对象.因此404 Not Found是合适的.
对于对象存在,但没有数据,204 No Content是合适的.我觉得你的情况,对象也没有,虽然存在.
Jus*_*ode 13
根据w3帖子,
200好的
请求已成功.响应返回的信息取决于请求中使用的方法
202接受
该请求已被接受处理,但处理尚未完成.
204没有内容
服务器已完成请求但不需要返回实体主体,并且可能希望返回更新的元信息.
400错误请求
由于语法格式错误,服务器无法理解请求.客户端不应该在没有修改的情况下重复请求
401未经授权
该请求需要用户身份验证.响应必须包含WWW-Authenticate头字段
404未找到
服务器未找到与Request-URI匹配的任何内容.没有说明该病症是暂时的还是永久性的
Dar*_*vic 11
令人遗憾的是,如此简单和明确定义的东西在此线程中变成了“基于意见”。
HTTP 服务器只知道“实体”,它是任何内容的抽象,可以是静态网页、搜索结果列表、其他实体列表、某事物的 json 描述、媒体文件等。
每个这样的实体都可以通过一个唯一的 URL 来识别,例如
如果一个服务器通过给定的 URL 找到一个资源,它的内容是什么都没有关系——2G 的数据,null,{},[]——只要它存在,它就是 200。但如果这样的实体是服务器不知道,预计返回 404“Not Found”。
一个困惑似乎来自开发人员,他们认为如果应用程序具有特定路径形状的处理程序,它不应该是错误。在 HTTP 协议的眼中,服务器内部发生了什么并不重要(即默认路由器是否响应或特定路径形状的处理程序),只要服务器上没有匹配的实体到请求的 URL(请求的 MP3 文件、网页、用户对象等),它将返回有效内容(空或其他),它必须是 404(或 410 等)。
另一个混淆点似乎是围绕“无数据”和“无实体”。前者是关于一个实体的内容,后者是关于它的存在。
示例 1:
示例 2:
示例 3:
小智 10
总结或简化,
2xx:可选数据:格式良好的URI:条件不是URI的一部分:如果条件是可选的,可以在@RequestBody中指定,@ RequestParam应该导致2xx.示例:按名称/状态过滤
4xx:预期数据:格式不正确URI:条件是URI的一部分:如果条件是强制性的,只能在@PathVariable中指定,那么它应该导致4xx.示例:按唯一ID查找.
因此对于问题情况:"users/9"将是4xx(可能是404)但是对于"users?name = superman"应该是2xx(可能是204)
Blu*_*box 10
有两个问题要问.一个在标题中,一个在示例中.我认为这部分导致了对哪种回应适当的争议.
问题标题询问空数据.空数据仍然是数据,但与无数据不同.所以这表明可能要求一个结果集,即一个列表/users.如果列表为空,则它仍然是列表,因此204(无内容)是最合适的.您刚刚要求提供一个用户列表并且已经提供了一个用户列表,它恰好没有内容.
提供的示例改为询问特定对象,用户,/users/9.如果未找到用户#9,则不返回用户对象.您询问了一个特定的资源(用户对象)并没有找到它,因为找不到它,因此404是合适的.
我认为解决这个问题的方法是,如果您可以按照预期的方式使用响应而不添加任何条件语句,那么使用204,否则使用404.
在我的示例中,我可以迭代一个空列表,而不检查它是否有内容,但我不能在空对象上显示用户对象数据而不会破坏某些内容或添加检查以查看它是否为空.
当然,如果符合您的需要,您可以使用null对象模式返回一个对象,但这是另一个线程的讨论.
现有答案未详细说明的是,无论您使用路径参数还是查询参数,都将有所作为。
/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/9PUT /users/9 和 DELETE /users/9PUT /users/9并且在成功更新或删除的情况下DELETE /users/9已经必须返回204。那么,如果用户9不存在,他们应该返回什么?根据所使用的HTTP方法,将相同的情况显示为不同的状态代码是没有意义的。
此外,不是规范性的,而是一种文化原因:如果204将其用于GET /users/9项目中将要发生的下一件事是有人认为返回204对n元方法有益。这使客户端代码变得复杂,因为2xx客户端现在不仅要检查并解码主体,还必须专门检查204并在这种情况下跳过对主体的解码。芽客户该怎么办?创建一个空数组?那为什么不把它放在电线上呢?如果客户端创建空数组,则204是愚蠢压缩的一种形式。如果客户端null改为使用,则会打开一个完全不同的蠕虫罐。
根据 Microsoft:ASP.NET Core Web API 中的控制器操作返回类型,向下滚动到几乎底部,您会发现以下关于与数据库中未找到的对象相关的 404 的简介。在这里,他们建议 404 适合空数据。
长话短说:
/users/9,您应该返回 404。/users?id=9,您应该返回 204。长版:
在回顾了我自己对这些状态代码的使用以及本文中的示例之后,我不得不说,如果在 的 url 处找不到用户 #9,则 404 是适当的响应/users/9。
在我今天的系统中,我们的 Application Insights 日志充满了数百个记录的 404 错误,这些错误使我们的日志变得混乱,因为我们决定在/users/9没有关联数据时返回 404。然而,这并不意味着我们在设置响应时的方法不正确,相反,我建议这意味着我们在设置路由时的方法不正确。
如果您期望端点获得大量流量,并且担心记录太多 404 错误,则应该更改路由以符合您想要的状态代码,而不是强制不恰当地使用状态代码。
此后我们决定对代码进行两处更改:
/users?id=9最终,API 架构师需要了解他们的 API 将如何使用以及哪种路由适合该用例。
我相信在 的情况下/users/9,您请求的资源是用户本身,User #9; 您要求服务器响应一个标识为“9”的对象,该对象恰好存在于包含“用户”一词的路径中。如果未找到该对象,您应该得到 404。
但是,如果您调用/users?id=9,我觉得您请求的资源是 Users 控制器,同时还提供了更多的特异性,以便它不会返回所有用户的完整列表。您要求服务器响应特定用户,该用户可以通过查询字符串中定义的 ID 号进行识别。因此,如果没有找到数据,对我来说 204 是适用的,因为即使没有找到数据,控制器也是适用的。
查询字符串方法还完成了一些事情,我认为不仅对 API 开发人员有帮助,而且对客户端开发人员(尤其是继承此代码或调用它的代码的初级开发人员或未来开发人员)有帮助:
任何参与其中的人都会立即清楚 9 是一个 ID,而不是某个任意数字。在这样一个基本示例中,这一点似乎没有实际意义,但请考虑一个使用 GUID 作为行 ID 或允许您通过人名获取数据的系统,甚至是一个返回特定邮政编码而不是行 ID 信息的系统。如果所有参与的开发人员一眼就知道该标识参数是名字、姓氏、全名还是邮政编码而不是 ID,那么这对所有参与的开发人员来说都是有用的。
小智 5
看了问题之后,您不应该使用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响应的最佳选择)我找到了资源,执行了逻辑,为您准备了一些内容,请很好地使用,哦,如果您要在视图中共享此内容,请刷新视图显示它。
希望能帮助到你。