users/9
在以前的项目中,我使用了404。如果没有用户9,则没有找到对象。因此404 Not Found是合适的。
如果对象存在,但没有数据,则为204 no Content。我认为在你的情况下,对象确实存在不。
TL;DR:使用404
404
看到这个博客。这解释得很好。
博客对204的评论摘要:
204
204 No Content
DELETE
因此,你的问题的答案是在你的情况下使用404。204是一个专门的响应代码,你不应该经常返回到浏览器来响应GET。
GET
其他响应代码甚至比204和404更不合适:
200
202
400
如果期望资源存在,但它可能是空的,我认为它可能更容易得到一个200 OK的表示,表明这个东西是空的。
因此,我宁愿让/things返回一个带有{"Items":[]}的200 OK,而不是一个没有任何内容的204,因为这样,一个包含0项的集合可以被视为一个包含一个或多个项目的集合。
我将把204 No Content留给put和delete,在这种情况下,可能真的没有有用的表示。
在/thing/9不存在的情况下,404是合适的。
我强烈反对404,而支持204或200的空数据。或者至少应该使用带有404的响应实体。
请求被接收并正确地处理了——它确实触发了服务器上的应用程序代码,因此不能真正地说它是客户机错误,因此整个客户机错误代码(4xx)类是不合适的。
更重要的是,404的发生有很多技术原因。例如,应用程序在服务器上被暂时停用或卸载,代理连接问题等等。
当然,这种情况下存在5xx错误类,但实际上,受影响的中间件组件通常无法知道错误在它们这一边,然后只是假设错误在客户端,然后响应404而不是500/503。
因此,仅基于状态代码,客户端无法区分意味着“空结果集”的404;404表示“有严重错误,请将此错误报告给运维团队”。
这可能是致命的:想象一下,您公司的会计服务列出了所有应获得年度奖金的员工。不幸的是,当它被调用时,它返回404。这是否意味着没有人应该得到奖励,或者应用程序目前正在进行新的部署,404实际上来自它应该安装到的tomcat,而不是应用程序本身?这两种场景产生相同的状态码,但它们的含义根本不同。
→对于需要知道所请求的资源不存在而不是暂时不可访问的应用程序来说,没有响应实体的404几乎是行不通的。
此外,许多客户端框架通过抛出异常来响应404,而不询问进一步的问题。这迫使客户端开发人员捕获异常,对其进行评估,然后基于此决定是否将其记录为由监视组件捕获的错误,或者是否忽略它。这对我来说也不太好。
尽管如此,我还是更喜欢204或200的空白回复。这样,请求的技术执行状态就与请求的逻辑结果分开了。2xx的意思是“技术执行ok,这就是结果,处理它”。
我认为在大多数情况下,应该让客户来决定一个空的结果是否可以接受。通过返回404而不返回响应实体(尽管技术执行正确),客户端可能决定将根本不是错误的情况视为错误。
另一个快速类比:返回404“没有结果”;类似于如果SQL查询没有返回结果就抛出DatabaseConnectionException。它可以完成工作,但是有很多可能的技术原因会抛出相同的异常,然后会被误认为是有效的结果。它使用错误机制来传递有效的结果。
使用公共枚举对响应内容进行编码,以允许客户端打开它并相应地派生逻辑。我不知道你的客户如何区分“数据未找到”404和“网络资源未找到”404之间的区别?你不希望有人浏览到userZ/9,并让客户端怀疑是否请求是有效的,但没有返回数据。
为了总结或简化,
2xx:可选数据:格式良好的URI: Criteria不是URI的一部分:如果Criteria是可选的,可以在@RequestBody和@RequestParam中指定,应该导致2xx。例如:按名称/状态过滤
标准是URI的一部分:如果标准是强制性的,只能在@PathVariable中指定,那么它应该导致4xx。例如:按唯一id查找。
对于要求的情况: "users/9"将是4xx(可能是404) 但是对于“用户”呢?Name =superman"应该是2xx(可能是204)
为什么不用410呢?它表明所请求的资源不再存在,并且客户端希望永远不会对该资源发出请求,在您的例子中是users/9。
你可以在这里找到关于410的更多细节:https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
根据w3的帖子,
200好了
请求成功。随响应返回的信息取决于请求中使用的方法
202年接受
请求已接受处理,但处理尚未完成。
204无内容
服务器已经完成了请求,但不需要返回实体主体,并且可能希望返回更新后的元信息。
400错误请求
由于语法错误,服务器无法理解请求。客户不应该在没有修改的情况下重复请求
401年未经授权
请求需要用户身份验证。响应必须包含一个WWW-Authenticate报头字段
404未找到
服务器没有发现任何与Request-URI匹配的内容。没有说明这种情况是暂时的还是永久的
这里有两个问题。一个在标题中,一个在例子中。我认为,这在一定程度上导致了关于哪种反应是合适的争议。
问题标题询问空数据。空数据仍然是数据,但不等于没有数据。因此,这意味着请求一个结果集,即一个列表,可能来自/users。如果一个列表是空的,它仍然是一个列表,因此204(无内容)是最合适的。您刚刚请求了一个用户列表,并得到了一个列表,它只是碰巧没有内容。
/users
相反,所提供的示例询问一个特定的对象,即用户/users/9。如果没有找到用户#9,则不返回任何用户对象。您请求一个特定的资源(一个用户对象),但由于没有找到而没有得到它,因此404是合适的。
/users/9
我认为解决这个问题的方法是,如果您可以在不添加任何条件语句的情况下使用响应,那么使用204,否则使用404。
在我的例子中,我可以迭代一个空列表而不检查它是否有内容,但是我不能在一个空对象上显示用户对象数据而不破坏一些东西或添加一个检查来查看它是否为空。
当然,如果适合您的需要,您可以使用空对象模式返回一个对象,但这是另一个线程的讨论。
204号更合适。特别是当你有一个警报系统来确保你的网站是安全的,404在这种情况下会引起混乱,因为你不知道一些404警报是后端错误或正常的请求,但响应为空。
起初,我认为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
背景知识:
搜索返回一个数组,它只是没有任何匹配,但是 它的内容是:空数组.
404当然是最著名的url不支持 请求的服务器,但缺少资源实际上是相同的。 即使/users/:name与users/kyle匹配,用户 凯尔没有可用资源,所以404仍然适用。它不是 搜索查询,它是由动态url直接引用,所以它是404
/users/:name
users/kyle
不管怎样,我的意见。
我认为,如果HTTP服务器发现任何服务已经准备好响应它发送的请求,它不应该响应HTTP 404——最后,服务器找到了一些东西——除非处理请求的服务明确地告诉它。
让我们暂时假设以下URL: http://example.com/service/return/test。
http://example.com/service/return/test
如果没有来自服务的任何响应显式地要求不同的行为,HTTP服务器只能说3件事:
503
REST:EMPTY
REST:NOT FOUND
REST:INVALID
(注意,我故意用“REST:”作为前缀,以标记这样一个事实,即虽然它们可能具有与HTTP响应代码相同的值或措辞,但它们是完全不同的东西)
让我们回到上面的URL,检查情况B,其中服务向HTTP服务器表明它不处理这个请求本身,而是将它传递给SERVICE。HTTP只提供SERVICE返回的内容,它不知道return/test部分的任何信息,因为它是由SERVICE处理的。如果该服务正在运行,HTTP应该返回200作为确实发现了什么来处理请求。
SERVICE
return/test
SERVICE返回的状态(如上所述,它希望在单独的头文件中看到)取决于实际期望的操作:
REST:FOUND
REST:GONE
REST:MOVED
REST:SUCCESS
retrun/test
REST:ERROR
REST:NOT IMPLEMENTED
这种区别比把两种不同的东西混在一起要清楚得多。它还将使调试更容易,处理也只是稍微复杂一些。
由服务而不是HTTP服务器处理的请求的状态真的不应该(RFC 6919)由HTTP响应代码给出。HTTP代码应该(RFC 2119)只包含HTTP服务器从自己的作用域提供的信息:即,是否发现服务在处理请求。
相反,应该使用一种不同的方式将请求的状态告知使用者,以告知实际处理请求的服务。我的建议是通过一个特定的头文件来实现。理想情况下,报头的名称及其内容都遵循一种标准,使使用者可以很容易地处理这些响应。
现有的答案没有详细说明使用路径参数还是查询参数是有区别的。
/users?id=9
id
使用路径参数还是查询参数取决于用例。我更喜欢将路径参数用于强制的、规范的或标识参数,将查询参数用于可选的、非规范的或属性参数(如分页、排序区域设置等)。在REST API中,我将使用/users/9而不是/users?id=9,特别是因为可能嵌套来获取“子记录”,例如/users/9/ssh-keys/0获取第一个公共ssh密钥或/users/9/address/2获取第三个邮政地址。
/users/9/ssh-keys/0
/users/9/address/2
我更喜欢使用404。原因如下:
void
POST
PUT
NoSuchElementException
ArrayIndexOutOfBoundsException
最后一点:一致性
GET /users/9
PUT /users/9
DELETE /users/9
如果成功更新或删除,PUT /users/9和DELETE /users/9已经必须返回204。如果用户9不存在,它们应该返回什么?根据所使用的HTTP方法将相同的情况显示为不同的状态代码是没有意义的。
此外,这不是一个规范的原因,而是一个文化原因:如果204用于GET /users/9,那么在项目中会发生的下一件事是,有人认为返回204对n-ary方法有好处。这使客户端代码变得复杂,因为客户端现在必须专门检查204,在这种情况下跳过解码正文,而不是仅仅检查2xx然后解码正文。但是客户会怎么做呢?创建空数组?那为什么不在电话里录下来呢?如果客户端创建空数组,204是一种愚蠢的压缩形式。如果客户端使用null代替,则打开了一个完全不同的蠕虫罐头。
2xx
null
Twitter使用404,并带有类似“找不到数据”的自定义错误消息。
裁判:https://developer.twitter.com/en/docs/basics/response-codes.html
根据RFC7231 - page59(https://www.rfc-editor.org/rfc/rfc7231#page-59) 404状态码响应的定义是:
所以在我的理解中,404状态代码不应该用于成功的GET请求,结果为空。(例如:一个没有特定过滤器结果的列表)
在看完问题后,你不应该使用404为什么?
基于RFC 7231,正确的状态代码是204
在上面的回答中,我注意到一个小错误:
1.—资源为:/users
2.- /users/8不是资源,这是:资源/users路由参数8,消费者可能不会注意到它,不知道区别,但发布者知道,必须知道这一点!…所以他必须为消费者返回一个准确的响应。时期。
/users/8
8
所以:
基于RFC: 404是不正确的,因为找到了资源/users,但是使用参数8执行的逻辑没有找到任何content作为响应返回,因此正确答案是:204
content
这里的要点是:404甚至没有找到资源来处理内部逻辑
204是a:我找到了资源,逻辑被执行了,但我没有发现任何数据使用你在路由参数中给出的标准,所以我不能返回任何东西给你。对不起,核实你的标准后再打电话给我。
200:好吧,我找到了资源,逻辑被执行(即使当我不被迫返回任何东西)采取这一点,并在你的意愿使用它。
205:(GET响应的最佳选项)我找到了资源,逻辑已经执行,我有一些内容给你,好好使用它,哦,顺便说一下,如果你要在一个视图中共享这个,请刷新视图以显示它。
205
希望能有所帮助。
这样的事情可能是主观的,双方都有一些有趣和各种扎实的论点。然而[在我看来]对于缺失的数据返回404是不正确的。这里有一个简单的描述来说明这一点:
没有问题,找到了端点,找到了表和列,因此查询了DB,并“成功”返回了数据!
现在,无论“成功响应”是否有数据都不重要,您要求“潜在”数据的响应,并且具有“潜在”数据的响应得到了满足。Null,空等是有效的数据。
200只代表我们的请求成功了。我正在请求数据,HTTP/REST没有任何问题,作为数据(尽管为空)返回我的“数据请求”是成功的。
返回一个200,让请求者在每个特定场景下处理空数据!
想想这个例子:
此数据为空是完全有效的。这意味着用户没有违规行为。这是200,因为它是有效的,然后我可以这样做:
你没有违规,吃个蓝莓松饼!
如果你认为这是404,你在说什么?无法发现用户的违规行为?从语法上讲,这是正确的,但在REST世界中,成功或失败是关于请求的,这是不正确的。该用户的“违规”数据可以成功找到,没有违规-一个实数代表有效状态。
(厚颜无耻的注意。)
在你的标题中,你下意识地认为200是正确的回答:
有效的请求但空数据的正确REST响应代码是什么?
在选择使用哪种状态码时,抛开主观性和棘手的选择,以下是一些需要考虑的事情:
如果仅仅因为没有响应数据而返回404,则任何客户端都会感到非常困惑。
对我来说,响应代码200和一个空的主体足以理解一切都是完美的,但没有数据匹配的要求。
根据Microsoft: 控制器动作返回类型在ASP。NET核心web API,向下滚动几乎到底部,你会发现以下关于404的简介与数据库中没有找到的对象有关。在这里,他们建议404适用于空数据。
令人难过的是,如此简单和明确的东西在这个帖子中变成了“基于意见的”。
HTTP服务器只知道“实体”,这是对任何内容的抽象,可以是静态网页、搜索结果列表、其他实体列表、某物的json描述、媒体文件等等。
每个这样的实体都应该由一个唯一的URL来识别,例如。
如果一个服务器通过给定的URL找到一个资源,它的内容是什么并不重要——2G的data, null,{},[]——只要它存在,它就会是200。但是如果服务器不知道这个实体,它将返回404“not Found”。
一个困惑似乎来自开发人员,他们认为如果应用程序具有特定路径形状的处理程序,那么它就不应该是错误。从HTTP协议的角度来看,服务器内部发生了什么并不重要。无论默认路由器响应还是特定路径形状的处理程序),只要服务器上没有与所请求的URL(所请求的MP3文件,网页,用户对象等)匹配的实体,这将返回有效内容(空或其他),它必须是404(或410等)。
另一个令人困惑的地方似乎是“没有数据”和“没有实体”。前者是关于实体的内容,后者是关于实体的存在。
示例1:
示例2:
示例3:
正如许多人所说的,404会误导客户端,如果请求uri不存在,或者请求的uri不能获取请求的资源,它不允许客户端进行区分。
200状态被期望包含资源数据-所以它不是正确的选择。 204状态意味着完全不同的东西,不应该被用作GET请求的响应
由于这样或那样的原因,所有其他现有状态都不适用。
我看到这个话题在很多地方被反复讨论。对我来说,很明显,要消除围绕这个话题的困惑,就需要一个专门的成功状态。类似于“209 -没有资源显示”。
这将是一个2xx状态,因为找不到ID不应该被认为是客户端错误(如果客户端知道服务器DB中的所有内容,它们就不需要向服务器询问任何事情,不是吗?)这个专用状态将解决所有与使用其他状态争论的问题。
唯一的问题是:我如何让RFC接受这个标准?
在这个场景中,Ruby on Rails响应404 Not Found。
Ruby on Rails
404 Not Found
客户端请求不存在的资源。因此,404 Not Found更合适。
我发现,在这种情况下,许多开发人员不喜欢404 not found。
404 not found
如果你不想使用404,我认为,你可以使用这两个响应代码中的任何一个:
如果你使用200 OK:响应体应为empty json:[]或{}
200 OK
empty json
[]
{}
如果你使用204 OK:响应体应为空。
204 OK
Ops问题的一句话:当我回想开始开发后端应用程序时,我在Controller -route中配置了错误的东西,因此我的Controller方法没有被调用,404是一个总是出现在我脑海中的代码。考虑到这一点,我认为如果请求确实在Controller方法中到达了您的代码,则客户端执行了一个有效的请求,并且找到了请求端点。因此,这是一个不要使用404的指示。如果db查询返回未找到,则返回200,但主体为空。
TL;博士:
长版:
在回顾了我自己对这些状态代码的使用和本文中的示例之后,我不得不说,如果在/users/9的url中没有找到用户#9,404是适当的响应。
今天在我的系统中,我们的Application Insights日志中充满了数百个记录的404错误,这些错误使我们的日志变得混乱,这都是因为我们决定在/users/9没有相关数据时返回404。然而,这并不意味着我们在设置反应时的方法不正确,相反,我认为这意味着我们在设置路由时的方法不正确。
如果您希望端点获得大量流量,并且担心记录太多404错误,那么您应该更改路由以符合您想要的状态码,而不是强制使用不适当的状态码。
我们已经决定对我们的代码做2个更改:
最后,API的架构师需要了解他们的API将如何被使用,以及哪种路由将适合于该用例。
我相信在/users/9的情况下,你请求的资源是用户本身,用户#9;您正在请求服务器响应一个标识为“9”的对象;它恰好存在于一个含有“user”的路径中。如果没有找到该对象,则应该得到404。
然而,如果你调用/users?id=9,我觉得你请求的资源是用户控制器,同时也提供了更多的专一性,这样它就不会返回所有用户的完整列表。您要求服务器响应一个可以通过查询字符串中定义的ID号识别的特定用户。因此,如果没有找到数据,204对我来说是有意义的,因为即使没有找到数据,控制器也是。
查询字符串方法还完成了一些我认为不仅有助于API开发人员,而且有助于客户端开发人员(特别是初级开发人员或继承这段代码或调用它的代码的未来开发人员):
任何人都清楚9是一个标识,而不是任意的数字。在这样一个基本的示例中,这一点似乎没有意义,但是请考虑使用guid作为行ID的系统,或者允许您通过人名获取数据的系统,或者甚至是返回特定ZIP/邮政编码信息而不是行ID的系统。如果他们一眼就知道标识参数是姓、名、全名还是ZIP/邮政编码,而不是ID,这对所有相关的开发人员都很有用。
我不认为404是正确的回应。
如果使用404,如何知道是没有找到api,还是数据库中的记录没有找到?
从你的描述,我会使用200 OK,因为你的api执行所有逻辑没有任何问题。只是在数据库中找不到记录。所以,这不是API问题,也不是数据库问题,这是你的问题,你认为记录存在,但它不存在。因此,API执行成功,数据库查询执行成功,但没有发现任何返回。
因此,在这种情况下,我会用
使用空响应,如数组的[]或对象的{}。
根据w3,我相信以下几点:
2 xx:
这类状态代码表示成功接收、理解并接受了客户机的请求。
4 xx:
4xx类状态代码用于客户端似乎出现错误的情况。
如果客户端请求/users,并且它有用户列表,响应代码将是200 OK(客户端请求是有效的)。
另一方面,如果客户端请求/users/9,而该用户不存在,则客户端错误地请求了一个不存在的资源,即用户。在这种情况下,用404 Not Found来回答是有意义的。
这个话题中的答案(在撰写本文时已经有26个)完美地说明了开发人员理解他们正在使用的构造的语义是多么重要。
如果不理解这一点,那么响应状态代码是响应的属性而不是其他属性就不明显了。这些代码存在于响应的上下文中,它们在此上下文中之外的含义是未定义的。
响应本身就是请求的结果。请求对资源进行操作。资源、请求、响应和状态代码是HTTP的结构,就HTTP而言:
HTTP提供了与资源交互的统一接口(第2节),无论其类型、性质或实现如何,通过操作和传输表示(第3节)。
换句话说,响应状态码的范围受到一个接口的限制,该接口只关心一些目标资源,并处理用于与这些资源交互的消息。服务器应用程序逻辑超出了范围,您使用的数据也不重要。
当使用HTTP时,它总是与资源一起使用。资源被以太转移或操纵。在任何情况下,除非我们在量子世界中,资源要么存在要么不存在,不存在第三种状态。
如果发出HTTP请求来获取(传输)资源的表示(如本问题中所示),而资源不存在,则响应结果应该显示一个带有相应404代码的失败。目标-获取表示-没有达到,资源没有找到。在HTTP上下文中不应该有对结果的其他解释。
RFC 7231超文本传输协议(HTTP/1.1):语义和内容,在这里被多次引用,但主要是作为状态码描述的参考。我强烈建议通读整个文档,而不仅仅是第6节,以便更好地理解HTTP接口及其组件的作用域和语义。
我们现在看到的是两种范式之间的紧张关系。
在HTTP和REST中,URL标识一个资源,即user/9资源包括9。因此HTTP应该返回404—未找到。这就是RESTful的定义。之后,你可以PUT user/9,然后当你得到然后下一次,你得到数据。这就是HTTP和REST的设计方式。
user/9
在HTTP级别,如果你不想要404,一个更好的URL应该是user?id=9,然后user部分会被找到,函数可以做它自己的处理,并返回它自己的方式通知“未找到”。
user?id=9
user
然而,为了方便指定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规范相反,并且完全理解我们是如何走到这一步的。
如果你控制了两端,考虑到你的服务器和客户端框架的限制,就做那些有效的事情。
(想想在user/9上执行HEAD请求的后果——你不能在响应中提供任何内容。200表示user/9确实存在,而404(正确地)表示它不存在。)