404状态码及其在常见的几乎restful api上的双重含义

404状态码及其在常见的几乎restful api上的双重含义,api,http,rest,Api,Http,Rest,在一个真正的restful应用程序中,我应该遵循链接来访问我的资源,而唯一“神奇的已知URL”应该是应用程序入口点。直接查询(如GET/user/john)应在至少有一个指向/user的链接后发出,或作为前一链接指定的搜索url的结果发出,如GET/user?username=john 但是,随着以下链接强制提供更多功能、进一步的开发时间和更智能的客户端,实际情况是,我编写和使用的大多数restful API都是部分restful的:它们是定义良好的URI和方法的集合,所有这些都是用户以前通过一

在一个真正的restful应用程序中,我应该遵循链接来访问我的资源,而唯一“神奇的已知URL”应该是应用程序入口点。直接查询(如
GET/user/john
)应在至少有一个指向
/user
的链接后发出,或作为前一链接指定的搜索url的结果发出,如
GET/user?username=john

但是,随着以下链接强制提供更多功能、进一步的开发时间和更智能的客户端,实际情况是,我编写和使用的大多数restful API都是部分restful的:它们是定义良好的URI和方法的集合,所有这些都是用户以前通过一些文档知道的。最后,在大多数情况下,
状态转移
部分不存在

好吧,根据之前已知URL的现实,
404
代码变成了一个问题:如何区分
404
可能具有的两种含义:

  • 这意味着“未找到资源,但您可以在将来重试”。示例:
    GET/user/mario
    而mario不是注册用户

  • api的不正确使用意味着“这里永远找不到任何资源,您正在错误地使用此api”。示例:
    GET/foobar/123

区分这两种情况很重要,因为作为服务维护人员,他们基本上是在告诉我这是一个预期错误,我不应该担心(第一种情况),还是一个意外错误,我应该担心,因为与客户的服务集成有问题(第二种情况)

我试图寻找一个更好的状态代码来代表第二个案例,我找到的最接近的状态代码是
406不可接受
(但它是对
Accept
标题的响应,无法实现)和
410消失
(这可能会让人困惑,因为那里没有资源,但好处是它告诉客户端不要再尝试该URL)。然而,这两者都不足以解决这个问题

你是如何解决这个问题的


侧节点:是一个有趣的项目,它试图成为带有
状态传输
部分的restful api。因此

无法通过以下设计区分这两个原因:

10.4.5 404未找到

服务器未找到任何与请求URI匹配的内容。
指示该情况是暂时的还是
永久性。
如果服务器已关闭,则应使用410(已关闭)状态代码
通过一些内部可配置的机制,知道旧的
资源永久不可用且没有转发地址。
当服务器不希望时,通常使用此状态代码
确切说明请求被拒绝的原因
,或者没有其他请求时的原因
答复是适用的


第一种情况(连同说明)使用
403
,第二种情况使用
404
如何?因为RFC 403将404作为替代响应代码,它们可能相关

403禁止:服务器理解请求,但拒绝满足请求。 授权没有帮助,请求不应重复。如果请求方法不是HEAD,并且服务器希望公开请求未满足的原因,则应在实体中说明拒绝的原因。如果服务器不希望将此信息提供给客户端,则状态代码404(未找到)可以改为使用

403:您了解客户想要什么,但拒绝满足它。客户不应该再试一次-在创建此资源之前是禁止的-这可以作为答案的一部分进行解释

404:你知道客户想要你不会提供的东西,可以真诚地告诉他,这种资源永远不会存在

更新:

解释“不应该”的解释方式:

不应此短语或短语“不推荐”的意思是 在特定情况下,可能存在正当理由 特定的行为是可以接受的,甚至是有用的,但是 应理解其含义,并仔细权衡案情 在实现此标签描述的任何行为之前


我认为对于您的用例来说,这是正确的。如果不解决403答案中所述的原因,就不应该重复客户端请求:“由于不存在名为mario的用户,因此禁止访问此资源”.但如果客户确信原因已消失,他可以自由重试。但这可能只是我对
403
的解释,不应重复语句。

在最后一个使用错误用法的示例中,什么时候会发生这种情况?我觉得这个示例应该返回一个
405
-如果我使用错误的HTTP方法调用端点,至少我们的API会这样做(使用
POST
请求调用方法,但该方法仅允许
GET
请求,例如).W3建议,当资源被永久移动且不再位于给定路径时,应返回
410
:-为什么
410
令人困惑?410表示URL中以前存在但不再存在的内容,因此不要再次重试URL。如果URL中以前没有任何内容,则这是无用的但是后来出现了一些问题。同意Remy的意见,410是不好的,因为它告诉客户端,对于已经不存在的东西,它是一个有效的url,而真正的原因是url格式错误,因此总是错误的
405
几乎可以解决它。这是一个
方法不允许
指令,而我需要的是
>不允许URL
指令D