缺少父资源的 REST HTTP 响应代码

REST HTTP response code for missing parent resource

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

寻找一些关于如何处理 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 Bad Request

The 400 (Bad Request) status code indicates that the server cannot or will not process the request due to something that is perceived to be a client error (e.g., malformed request syntax, invalid request message framing, or deceptive request routing).

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

本能地 会借给 404 Not Found 410 Gone 即使这不是缓存问题,因为失败的原因实际上是 missing/unavailable 资源。但是根据规范 RFC7231:

6.5.4. 404 Not Found

The 404 (Not Found) status code indicates that the origin server did not find a current representation for the target resource or is not willing to disclose that one exists. A 404 status code does not indicate whether this lack of representation is temporary or
permanent; the 410 (Gone) status code is preferred over 404 if the
origin server knows, presumably through some configurable means, that the condition is likely to be permanent.

6.5.9. 410 Gone

The 410 (Gone) status code indicates that access to the target
resource
is no longer available at the origin server and that this
condition is likely to be permanent.

这些似乎证明了这种本能。

有没有人有处理这种或类似情况的经验和好的方法?我觉得我应该选择感觉正确的东西以及如果使用此服务我希望看到的东西,而不是文本中的字母。

410 走了

如果/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 之类的请求是更合适的响应。

NO: 排除 400 Bad Request 因为你提到的所有请求都是有效的。

NO:添加一些香料:我看到在类似情况下会返回 409 Conflict。尽管您明确指出缺少资源,但它在您的情况下似乎不合适。

YES:如果您的资源不存在,404 Not Found 是最合适的响应。它是否曾经存在并不重要。 404 表示 "sorry, resource unavailable"。我会添加一条错误消息来准确说明缺少 哪个 资源,以便您的 API 消费者可以更好地处理这种情况。

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

个人笔记:

  • 我从未见过 410 Gone 的实际有用情况,因此我避免使用它并建议我的团队不要使用它,除非他们能想出一个真正好的理由。显得有点学术。在大多数情况下,您的 API 消费者将以相同方式处理 404 和 410。他们通常不会 mind/care。我只能看到罕见的边缘案例才能对差异化做出有价值的理解。
  • DELETE 通常不会删除资源。它们被灭活(变得不可用),但它们在技术上仍然可用。如果资源有可能再次可用,例如通过名为 "return all recently deleted resources" 的新功能,410 就已经具有误导性了。
  • A 410 还指出该资源过去确实存在。从数据安全的角度来看,您可能会争辩说信息应该保留在内部,不应公开。在这些情况下,410 成为您 API 的一般禁忌。

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

也就是说

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

requests:当前为目标资源选择的表示。参见RFC 7231;特别是,该请求不会询问以下任何内容的表示:

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

比那简单多了——我能得到我想要的吗?并且源服务器提供一个响应,可能是当前的表示,也可能是一条消息,说明没有这样的表示可用。

由于 /users/{userId}/accounts/{accoundId} 不存在,/users/{userId}/accounts/{accoundId}/logs/{logId} 的表示不可用这一事实是 实现细节

404 is normally what you would want to use as a status code to announce that no current representation of the target resource is available. Any explanation for why this is the case would normally go into the message body. For instance, you might describe it using problem details.

服务器没有义务发送资源的过期表示只是因为它恰好有一个资源存在(同样,缓存是一个实现细节)。

410几乎 一样;这实际上是一个建议,客户可以将其书签标记为已弃用。

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

400 是一种非常合理的投注方式。但是对于 404 确实满足您需求的这种情况,我不会使用 if。