缺少父资源的{REST}响应代码

时间:2018-01-25 18:00:03

标签: rest http httpresponse http-response-codes

我的问题是,当父资源或更高资源不存在/已被删除时,我应该返回400 Bad Request,404 Not Found或410 Gone的HTTP响应代码吗?

寻找有关如何处理RESTful资源树中缺少链接的一些指导,因为我已经阅读了相当多但不是很多个人经验。

假设我们有以下资源结构:

/users/{userId}/accounts/{accoundId}/logs/{logId}

一个用户可以拥有多个帐户,而这些帐户又可以拥有多个订单,而这些订单又可以包含许多日志。日志仅针对单个帐户存在,而帐户仅针对单个用户存在。没有帐户就不能存在日志,没有用户就无法存在帐户。

当我尝试解决以下问题时,我的问题出现了:

/users/123/accounts/321/logs - POST
/users/123/accounts/321/logs/987 - GET
/users/123/accounts/321/logs/987 - PUT
/users/123/accounts/321/logs/987 - DELETE
/users/123/accounts/321/logs/987 - PATCH
/users/123/accounts/321/logs/987 - HEAD

但是这种资源不存在或不存在:

/users/123/accounts/321

或此资源不存在或不存在:

/users/123

我认为这是一个 400错误请求,根据RFC7231

  

6.5.1。 400错误请求

     

400(错误请求)状态代码表示服务器不能   或者由于感知到的东西而不会处理请求   是客户端错误(例如,格式错误的请求语法,无效   请求消息框架或欺骗性请求路由)。

定义为true,除非在缓存未过期的情况下,意味着应用程序尚未重新遍历层次结构,另一个应用程序已删除父资源。通过提供相关的oplock,客户端将证明,根据其最后的知识,它正在做出语义上正确的请求。

本能地 会借助 404 Not Found 410 Gone ,即使这不是缓存的事情,因为失败的原因实际上是一个缺失/不可用的资源。但是根据规范RFC7231

  

6.5.4。找不到404

     

404(未找到)状态代码表示原始服务器   没有找到目标资源的当前代表或是   不愿意透露那个存在。 404状态代码   不表明这种缺乏代表性是暂时的还是暂时的   常驻;如果是,则410(Gone)状态代码优先于404   原始服务器可能通过一些可配置的方式知道   这种情况可能是永久性的。

  

6.5.9。 410 Gone

     

410(Gone)状态代码表示访问目标
  资源
在原始服务器上不再可用,而且这个   条件可能是永久性的。

这似乎可以说明这种本能。

有没有人有过处理这种或类似场景和好方法的​​经验?我觉得我应该选择感觉正确的东西以及我希望看到的消费服务,而不是文字。

3 个答案:

答案 0 :(得分:5)

要记住的一点是:HTTP响应(包括包含状态代码的元数据)特定于请求的资源,而不是某些隐式的层次结构。

这就是说

GET /users/{userId}/accounts/{accoundId}/logs/{logId}

请求:目标资源的当前选定表示。见RFC 7231;特别是,请求并不询问任何这些的表示:

/users/{userId}/accounts/{accoundId}/logs/
/users/{userId}/accounts/{accoundId}/
/users/{userId}
...

它比那简单得多 - 我能得到我要求的东西吗?并且原始服务器提供响应,该响应可以是当前表示,或者它可以是解释没有这样的表示可用的消息。

由于/users/{userId}/accounts/{accoundId}/logs/{logId}不存在而无法使用/users/{userId}/accounts/{accoundId}的表示,因此实施细节

404通常是您希望用作状态代码以宣布目标资源的当前表示不可用的内容。对于为什么会出现这种情况的任何解释通常都会进入消息体。例如,您可以使用problem details来描述它。

服务器没有义务发送资源的过期表示,只是因为它碰巧有一个(再次,缓存是一个实现细节)。

410 几乎同样的事情;它实际上是一个顾问,客户可以将其书签标记为已弃用。

如果您无法找到更符合有效负载中消息语义的状态代码,那么

400是一种非常合理的方式。但是,如果404确实符合您的需求,我就不会使用。

答案 1 :(得分:1)

:排除 400错误请求,因为您提到的所有请求都有效。

:添加一些香料:我在类似的情况下看到了 409 Conflict 。在您的情况下,这似乎是不合适的,因为您清楚地表明资源缺失。

:如果您的资源不存在, 404 Not Found 是最合适的响应。它是否存在无关紧要。 404表示“抱歉,资源不可用”。我会添加一条错误消息,准确地说明缺少资源,以便您的API消费者能够更好地处理这种情况。

可能 410 Gone 是404的特定情况。如果资源不可用并且它之前存在,则应该引发它它(实际上)将再也不存在。因此,无论您多久以及何时尝试获取资源,您都将永远不会再获得它,但在过去,您可能已经能够获得它。同样的事情:如果您决定使用410,请考虑添加精确的错误消息。

个人说明:

  • 我从未见过 410 Gone 的实际有用情况,因此我避免使用它,并建议我的团队不要使用它,除非他们能够提出一个真正的理由。它似乎有点学术性。在大多数情况下,您的API使用者将以相同的方式处理404和410。他们通常不介意/关心。我只能看到罕见的边缘情况,才能对差异化产生有价值的认识。
  • DELETE通常不会删除资源。它们被停用(不可用),但它们在技术上仍然可用。如果资源有可能再次可用,例如通过名为“返回所有最近删除的资源”的新功能,410就会产生误导。
  • A 410还指出该资源确实存在于过去。从数据证券的角度来看,您可以认为信息应该保留在内部,不应该暴露。在这些情况下,410会成为您的API的一般禁忌。

答案 2 :(得分:-2)

410 Gone

如果/ users / 123 / accounts / 321 / logs / 987不再存在,则410 Gone是最合适的响应。由于/ users / 123被删除而删除的事实与/ users / 123 / accounts / 321 / logs / 987的请求无关。

400 Bad Request对于/ users / 123 / accounts / 321 / lergs / 987的请求更合适。