REST 404 与 400。使用哪一个?

REST 404 vs 400. Which one to use?

如果我有如下所示的 REST 资源:

GET http://www.example.com/customers/{customerId}/orders

如果提供的 customerId 不存在,我的服务器应该 return 404(未找到)还是 400(错误请求)?

我认为它应该是 404 状态,因为请求有效,但是没有找到 customerID

有几种不同的方法可以解决这个问题。

如果您在检查 {customerId} 时发现它完全是假的,那么 400 - Bad Request 就有意义了。

但是,如果 {customerId} 的格式和类型有效,但它不存在,那么我建议使用 204 - 无内容。在我看来,这种情况不属于 404,因为该操作已被发现。

假设用户提供了一个有效的路径,即使customerId 123456不存在,调用也执行成功并且没有返回任何数据。因此 204 无内容。

200 范围内的状态也被视为 "success" 状态,因此您可以验证您的调用是否成功调用了格式正确的 {customerId}。然而,确定该 ID 是否有效可能是另一项服务的责任。

在这种情况下,我会说你应该 return 404 Not Found

为了说明问题,我对本实例中的规范的解释如下:

400 Bad Request 用于应用程序成功接收到请求,并且应用程序确定请求有问题的情况:端点不存在,或者格式或请求的性质 parameters/variables 在某种程度上是 incorrect/malformed,导致请求无效。

这将代表@Trevor Conn 的示例,其中请求中的 customerID 格式无效(太长、太短、无效字符等),查找或操作可以简单地由于错误未尝试。

200 系列响应(@Trevor Conn 也提到过)表明成功处理了针对有效实体或主题的请求。

204 No Content 应在找到主题或执行操作且请求的真实有效输出或结果为“无”的情况下使用。

据我了解,这有几件事:

  1. 它消除了关于响应真实内容的歧义。其中 200 表示成功,但空响应可能表示某种形式的传输或响应失败。您明确地告诉客户:“我们成功地发现 and/or 做了一件事,而真正的回应是什么都没有。”
  2. 此外,虽然我自己不使用此代码,但我相信当前的浏览器支持会阻止替换客户端的内容。 IE:如果您要单击 URL 并点击 returned 204 No Content 的端点,它将向浏览器指示请求成功,但实际上不会导航到任何地方(视口和当前 URI 都将保持不变)。

在您的情况下,404 Not Found 将是对有效端点请求的正确响应,格式正确 customerID,不会解析为客户。

往兔子洞里走一点...

您还可以跟踪哪些有效的 customerID 是 deleted/archived,如果它们曾经存在,则用 410 Gone 响应,如果客户已被删除,则用 451 Unavailable For Legal Reasons 响应由于法律要求。

另外请注意,如果您使用 OOP 语言,您可能处于将 endpoints/actions 视为“方法”的生态系统中。

如果您真的要深入 HTTP 响应代码的陷阱,请注意在这种情况下使用 400 Bad Request 处理缺少的“方法”。这与 405 Method Not Allowed 不同,因为 Method Not Allowed 中的“方法”指的是 HTTP 方法 (GET/POST/PUT/DELETE). 405 应且仅在客户端尝试对不支持该方法的端点使用这些方法之一的情况下使用。

这方面的一个例子是使用:

DELETE http://www.example.com/customers/{customerId}/orders

正确的用法是:

DELETE http://www.example.com/customers/{customerId}/orders/{orderID}

再往下看:“不允许”严格指的是该方法是否已实现,如果用户没有权限执行以其他方式实现的 HTTP 方法,则正确的响应将是 403 Forbidden,或 401 Unauthorized 如果由于客户端尚未通过身份验证而无法确定客户端的权限。

更多兔子洞...

501 Not Implemented 是 HTTP 方法失败的服务器指示器(因为服务器本身,无论是 Nginx、Apache 还是任何其他服务器)在基础级别上不支持 HTTP 请求方法。

IE:

EXPELLIARMUS http://www.example.com/customers/{customerId}

205 Reset Content204 类似,它指示请求成功,以及一个真正的空响应,除了它指示客户端就地重置其文档视图(其中 204 根本不会触发任何操作)。