在使用GET查询“暂未就绪,请稍后再试”资源的REST API中,HTTP状态码是什么?

8
首先,我已经阅读了一些相关帖子:

但我仍然认为我应该在这里提出我的问题和想法。在使用GET查询“Not Ready Yet, Try Again Later”资源时,REST API应该使用什么HTTP状态码?例如,客户端尝试通过向此URL发出HTTP GET来查询所有未来在本地发生的新闻(!):http://example.com/news?city=chicago&date=2099-12-31,那么服务器应该回复什么?

这些是我考虑过的http状态码,它们的rfc定义以及我为什么不完全满意:

  • 3xx重定向。注释:因为没有其他链接可以重定向到,所以不是一个选项。

  • 503服务不可用:由于服务器的临时超载或维护,服务器目前无法处理请求。这意味着这是一个暂时的条件,在一定延迟后将得到缓解。如果已知,可以在Retry-After头中指示延迟的长度。注释:期望重试行为,但语义上根本不是服务器的错误,所以所有5xx看起来都很奇怪。

  • 4xx客户端错误。注释:看起来很有前途。见下文。

  • 413请求实体过大:服务器拒绝处理请求,因为请求实体大于服务器愿意或能够处理的大小。如果条件是暂时的,服务器应该包含一个Retry-After头字段,以指示它是暂时的,并在什么时间后客户端可以再次尝试。注释:期望重试行为,但“实体过大”部分有些误导。

  • 417 Expectation Failed:在Expect请求标头字段(参见第14.20节)中给出的期望不能被此服务器满足。注释:因此,应该是由Expect请求标头引起的,对我的情况不适用。

  • 406无法接受:资源……根据发送到请求中的接受标头不可接受。注释:因此,它是由Accept请求标头引起的,对我的情况不适用。

  • 409冲突:由于与资源的当前状态发生冲突,无法完成请求。只有在预计用户可能能够解决冲突并重新提交请求的情况下才允许使用此代码。……冲突最可能发生在响应PUT请求时。注释:这个很接近。尽管我的情况与PUT无关,并且实际上并不是由冲突引起的。

  • 404未找到:服务器没有找到与请求URI匹配的任何内容。注释:从技术上讲,我的url路径(http://example.com/news)确实存在,只是参数引起了问题。在这种情况下,返回一个空集合而不是404可能更合适。

  • 403禁止:服务器理解请求,但拒绝履行它。授权无法帮助,也不应重复请求。注释:通常应在任何受限资源中使用吗?

  • 400错误请求:由于格式不正确,服务器无法理解请求。客户端不应在不修改的情况下重复请求。注释:在我的情况下不是真的。我的服务器理解请求,它的语法很好,只是意义不好。

  • 2xx成功。注释:如果4xx不起作用,那么2xx怎么样?见下文。

  • 200 OK。注释:好的。那么我应该在响应正文中包含什么?null或[]或{}或{"date": "2099-12-31", "content_list": null}或……哪一个更直观?另一方面,我更喜欢一种清晰区分较

    你的想法是什么?

最终这是个人意见问题。我认为我更喜欢使用带有空新闻条目的任何正文模板的200 OK,因为当然没有新闻可供检索。 - cYrixmorten
2个回答

4

使用404。

你对它的反对基于URI不包括查询字符串的普遍理解。逻辑是:“因为我有多个映射到同一处理程序的URI,我的资源实际上存在,只是由查询字符串参数化。”

这是不正确的。正如URI规范在第3.3节中所说(重点在我这里),

"路径组件包含数据,通常以分层形式组织,连同非分层查询组件中的数据(第3.4节),用于在URI方案和命名权限(如果有)的范围内标识资源。"

资源由URI标识,绝对URI的任何部分更改都会标识出不同的资源。每天向您认识的每个人发送此消息,直到他们告诉您停止为止。因此,404 是一个完美的匹配:“404(未找到)状态代码表示源服务器未找到目标资源的当前表示形式或不愿公开存在的表示形式。”

1
我认为你的帖子的主要思想是“资源由完整的URI标识,包括查询字符串”。很有趣,但这是一个(事实上的?)标准吗?你能分享一些相关文档吗?关于“404”部分,也许这是主观的,并且取决于语义:2099-12-31的新闻是一个空集合还是不存在的集合。无论如何,谢谢。 - RayLuo
共享文件。另请参见https://dev59.com/e2TWa4cB1Zd3GeqPGcG4#10955717,在那里各种REST专家发表了自己的意见。 - fumanchu
感谢@fumanchu。首先,如果你分享的“标准文档”是Roy论文中的引用,我认为它描述了“URL中的资源”和“实现中的存储对象”之间(没有直接)关系。但后来我意识到你已经在你的回答中给出了标准URI规范,所以现在我对“资源由完整的URI(包括查询字符串)标识”这一说法感到满意。因此,这是我的最新理解:所有有问题的HTTP GET请求中的查询字符串都将(或必须)导致404错误。HTTP DELETE也适用。但如果这种情况发生在HTTP POST或PUT中,则更常见的是400错误。 - RayLuo

2
您正在检索当天的新闻,这是一个有效的日期,只是没有任何新闻。一个空主体的200响应,或者基于媒体类型的逻辑上合理的响应都是可以的。这取决于您与客户端决定的媒体类型。
如果日期格式不正确(例如您要求11月的第45天,或要求一个不存在的城市),则404会更有意义。
另外,URL的格式最好是http://example.com/news/chicago/2099-12-31,因为这是您想要检索的特定资源。这种格式也会使404等错误更清晰明了。

好的,我想要区分三种情况:一个带有一些内容的资源,一个带有空内容的资源,以及根本不存在的资源。我可以看到你的仅路径URL风格如何完美地将它们映射为:200带有内容,200带有空内容(或者可能是204),以及404未找到。但是现在如果URL必须包含查询字符串,就像我的例子一样,怎么办?我只是认为不是所有复杂的查询条件都可以安排成仅路径风格。 - RayLuo
如果您必须使用一种超级资源,该资源根据查询字符串可能会有很大不同,我建议使用200。如何传达“尚无新闻”或类似内容是HTTP之外的问题。这实际上取决于您正在转换的媒体以及客户的期望。例如,在HTML中,您可以简单地说“尚无新闻”,读者会理解。但是,这仍然是内容,因为它是一个HTML页面。即使该内容的一个版本可能是没有新闻的,我也不会将404用于存在但具有变化内容的资源。 - Cormac Mulhall
如果服务类似于搜索引擎,那么“超级资源”有时是一个自然的选择。200说得很好。例如,人们或(程序的作者)在使用谷歌时是否期望突然出现404?这不会让他们想“我刚才是不是输入了错误的主机名或其他什么东西”吗?我喜欢你说的“即使该内容的一个版本可能没有内容,我也不会将404用于存在但具有变化内容的资源”。 - RayLuo
是的,我认为搜索引擎的比喻很好。我同意下面fumanchu所说的关于404的观点,如果资源本身不存在,但最终它归结为一个关于资源的元讨论。资源不存在,还是资源“尚未有消息”,这确实存在。在您所描述的情况下,我会选择一个资源,即“尚未有消息”,就像在Google上搜索不存在的东西仍然返回一个搜索资源,只是显示零结果一样。“尚未有消息”仍然是一种资源,如果对客户更有意义的话。 - Cormac Mulhall
换句话说,“资源”是新闻搜索查询结果。即使返回未找到新闻的搜索结果,该资源始终存在。 - Cormac Mulhall

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接