5

我的 RESTful 服务包含一个表示项目 ACL 的资源。要更新此 ACL,客户端会PUT使用新 ACL 作为其实体发出请求。成功后,PUT响应实体将包含新 ACL 的经过清理的规范版本。

在大多数情况下,HTTP 响应状态码是相当明显的。 200成功时,403如果不允许用户编辑 ACL,400如果新的 ACL 格式不正确,404如果他们尝试在不存在的项目上设置 ACL,412如果If-Match标头不匹配,等等。

然而,在一种情况下,正确的 HTTP 状态代码并不明显。如果经过身份验证的用户使用PUT将自己从 ACL 中删除怎么办?我们需要表明请求已成功,但他们不再有权访问该资源。

我考虑200过在实体中使用新的 ACL返回PUT,但这没有任何迹象表明他们不再拥有GET该资源的能力。我考虑过直接返回403,但这并不表示PUT成功。我考虑过返回303指向Location相同的资源(后续GET将给出 a 403),但这似乎是303对资源没有移动的滥用。

那么“成功,因此您不再有权访问”的正确 REST HTTP 状态代码是什么?

4

4 回答 4

3

200 是适当的响应,因为它表示成功(正如任何 2xx 代码所暗示的那样)。您可以在响应中区分用户缺乏权限(或者,如果您不希望,204 可以)。状态码没有约定未来的请求将返回相同的代码:对 PUT 的 200 响应并不意味着后续的 GET 不能返回 403。通常,服务器不应该试图告诉客户端如果他们发出特定的代码会发生什么要求。HTTP 客户端几乎总是应该在他们看到并准备好处理几乎任何响应代码之前就跳跃。

您应该阅读httpbis 中 PUT 方法的更新描述;它不仅讨论了 200/204 的使用,而且在仔细阅读时指出,在对 PUT 的立即响应中返回转换后的表示是不合适的;相反,使用 ETag 或 Last-Modified 标头来指示客户端发送的实体是否已转换。如果是这样,客户端应该发出一个后续的 GET,而不是期望发送新的表示来响应 PUT,如果没有其他原因,只是更新沿途的任何缓存(因为对 PUT 的响应是不可缓存的) . 第 6.3.1 节同意:对 PUT 的响应应该代表操作的状态,而不是资源本身。另请注意,对于新的 ACL,您必须返回 201,而不是 200。

于 2013-08-11T01:25:57.250 回答
2

您混淆了两个语义概念,并试图将它们组合成一个响应代码。

第一个:您在尝试创建的位置成功创建了 ACL。正确的语义响应(在 RESTful 或非 RESTful 场景中)是201 Created。来自 RFC:“请求已完成并导致创建新资源。”

第二个:执行 PUT 的用户不再有权访问该资源。这是一个暂时的想法——如果 ACL 更新了,或者在下一个请求之前发生了一些变化怎么办?用户无权访问任何类型的资源(这包括 ACL 资源)的想法仅与该请求的范围有关。在执行下一个请求之前,可能会发生一些变化。在用户无权访问某些内容的单个请求中,您应该返回403 Forbidden

你的 PUT 方法应该返回一个 201。如果客户端担心它是否有访问权限,它应该发出一个后续请求来确定它的状态。

于 2013-08-11T15:40:31.553 回答
1

您可能想查看 HTTP 响应代码“204 No Content”(http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html),表明“服务器已完成请求 [to be从 ACL 中删除],但不需要返回实体主体,并且可能希望返回更新的元信息”(此处为成功删除的结果)。尽管不允许您返回带有 204 的消息正文,但您可以返回指示用户对资源的访问权限的更改的实体标头。我从 Amazon S3 得到了这个想法 - 他们在成功的 DELETE 请求(http://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectDELETE.html)上返回 204,这似乎与您的情况相似,因为通过删除你自己来自 ACL,你

于 2013-08-10T21:21:49.393 回答
0

非常有趣的问题 :-) 这就是我喜欢 REST 的原因,有时它可能会让你发疯。阅读w3 http 状态代码定义我会选择其中之一(这当然只是我的拙见):

  • 202 Accepted - 因为这意味着“是的,我收到了您的请求,我会处理它,但稍后再回来看看会发生什么” - 当用户稍后回来时,她会得到 403(这应该是预期的行为)
  • 205 重置内容 - “是的,我知道你想删除自己,请提出新的请求,当你回来时,你会得到 403”

另一方面(只是在我脑海中弹出),为什么要引入单独的逻辑并区分这种情况而不使用 200 ?是否将在某些具有 UI 的客户端应用程序中使用其余部分?其余的用户应该向最终用户显示一个弹出窗口“您确定要从 ACL 中删除自己吗?” 好吧,如果您的其余部分返回 200 并且只显示一个弹出窗口“您确定要从 ACL 中删除具有名称的用户吗?”,则可以处理这种情况,无需区分这两种情况。如果这个剩余部分将再次用于某些服务到服务的通信(即仅从另一个程序调用),为什么还要区分这里的情况,程序不会关心哪个用户将从 ACL 中删除。

希望有帮助。

于 2013-08-10T20:35:11.090 回答