【问题标题】:HTTP Status Code for Resource not yet available资源的 HTTP 状态码尚不可用
【发布时间】:2012-06-19 14:25:05
【问题描述】:

我有一个 REST 端点接受 POST 请求以将代码标记为已兑换。该代码只能在特定日期之间兑换。

如果有人尝试提前兑换代码,我应该如何应对?

我怀疑 HTTP 403,禁止,是正确的选择,但 w3c 声明“the request SHOULD NOT be repeated”,而在这种情况下,我预计请求会在以后重复。

【问题讨论】:

  • 相同的 URI 是否响应 GET?总是或仅在特定日期之间?
  • 那种。代码表示可以在它上线之前被 GETted。赎回是可以针对代码创建的单独表示。正是这个 POST 请求创建了兑换。显然,创建之前的 GET 将返回 404,因为该兑换不存在(请注意,此 GET 将使用兑换 ID 而不是代码)。
  • POST 是否在该 URL 创建资源?其他?一个都没有?
  • POST 用于兑换/并创建兑换资源,然后可在兑换/{ID} 上获取。成功 POST 后,完整的 URL(包括 ID)将在位置标头中返回。 POST 之前没有兑换资源,所以 GET 什么都没有。
  • 层次结构有一个活动(具有开始日期),针对活动生成的代码,然后(在活动开始后)针对每个代码进行 1-n 次兑换。活动和代码在开始日期之前可用,但不允许兑换代码。

标签: http rest


【解决方案1】:

409 Conflict

由于与当前的冲突,请求无法完成 资源的状态。仅在以下情况下才允许使用此代码 预计用户可能能够解决冲突,并且 重新提交请求。响应正文应该包含足够的 供用户识别冲突来源的信息。 理想情况下,响应实体将包含足够的信息 用户或用户代理来解决问题;但是,这可能不是 可能但不是必需的。

403 Forbidden 在尝试兑换已兑换的优惠券时更有意义,尽管410 Gone 在这种情况下也很优雅。

404 Not Found 并不理想,因为该资源确实存在,但是如果您不想使用 403 指定原因或出于安全原因想要隐藏资源的存在,则可以使用它.

如果您使用的是HATEOAS,那么您还可以通过仅在优惠券资源中包含redeem 超媒体控件(通过GET 检索)来阻止您的客户(可以这么说),当可以兑换优惠券;虽然这不会阻止过度绑定的客户尝试赎回它。

【讨论】:

  • 嗨汤姆,我第一次通过这个问题让我倾向于 403。但经过更多思考(和一些回击),我现在倾向于 409。你引用它的方式,“由于与资源的当前状态冲突”可以被理解为,在以后的时间,请求可能是非冲突的,因此是有效的。
  • @DavidJames 这也正是让我信服的原因。优惠券处于不可兑换状态,因此任何兑换尝试都会与其当前状态发生冲突。
  • 关于“如果他们试图兑换已兑换的优惠券,403 Forbidden 更有意义”,409 Conflict 不也是这里的合适选择吗?
  • @DanMidwood 从资源状态的角度来看,是的,我仍然会坚持使用 409。但是 409 “仅在预期用户可能能够解决冲突并重新提交的情况下才允许使用请求。”对于已兑换的优惠券,您可以争辩说冲突永远不会解决,因此不应使用 409。这就是为什么我针对这种情况建议使用 403 和 410。
【解决方案2】:

编辑:感谢一些好的批评(见下文),我想警告这个答案。它基于 Richardson & Ruby 的文章,可以说与 httpbis writing on 403 Forbidden 不匹配。 (就个人而言,现在我正在学习 409,正如 Tom 在单独的答案中所解释的那样。)

403 禁止是最好的选择。我将逐行引用RESTful Web Services by Richardson & Ruby。如您所见,403 非常适合:

客户端的请求格式正确,但服务器不想执行。

检查!

这不仅仅是凭据不足的情况:这将是 401(“未经授权”)。这更像是一种只能在特定时间或从特定 IP 地址访问的资源。

检查!

403 的响应意味着客户端请求了一个确实存在的资源。与 401(“未授权”)一样,如果服务器甚至不想提供此信息,它可以撒谎并发送 404(“未找到”)。

您在上面写道:“代码表示在它上线之前可以被获取。”所以,你并没有试图隐藏任何东西。所以,坚持使用 403。检查!

如果客户端的请求格式正确,为什么这个状态码是4xx系列(客户端错误)而不是5xx系列(服务器端错误)?因为服务是根据请求的某些方面而不是其形式做出决定的;例如,提出请求的时间。

检查!客户的请求已更正,但不适用于特定时间。

我们四对四。 403 代码是赢家。也没有其他代码匹配。

所有这一切都表明,一个普通的、非特定的 400 不会错,但不会那么具体或有用。

另一个答案建议使用 409 冲突代码。虽然值得考虑,但它并不适合。这就是为什么。再次根据 Richardson & Ruby 的说法:

得到这个 [409] 响应意味着您试图将服务器的资源置于不可能或不一致的状态。当您尝试删除非空存储桶时,Amazon S3 会提供此响应代码。

在“活动”之前声明提升不会“将服务器资源置于不一致的状态”。它会破坏一些商业规则——并导致作弊——但不会导致我看到的逻辑矛盾。

因此,无论您是否在提出问题时就意识到这一点,403 都是一个不错的选择。 :)

【讨论】:

  • Richardson & Ruby 显然没有 httpbis 的好处,它现在说:“服务器理解请求,但拒绝授权。提供不同的用户身份验证凭据可能会成功,但任何请求中提供的凭据不足。请求不应使用相同的凭据重复。见tools.ietf.org/html/…
  • @fumanchu 你说得很好! “不要重复请求”对它有一定的确定性。 (似乎 R&R 可能已经超出规范了一点?)
【解决方案3】:

由于 Rest URL 应该代表资源,我会回复 404 - Not Found
该资源仅在特定日期之间可用,因此在任何其他日期都找不到。

【讨论】:

  • 这很接近但不是最佳选择。根据“RESTful Web Services”,“404 可能是掩盖 403 或 401 的谎言。可能是资源存在,但服务器不希望客户端知道它。”请注意,上面的 Dan 说他没有隐藏资源。他只是想将其上的某个操作(兑换代码)限制在某个时间窗口内。所以我们不需要用 404 作为掩饰。
【解决方案4】:

当它说“不应该重复”请求时,它指的是您应该发送给查看者的消息。

与实际请求是否重复无关。 (如果他/她愿意,用户将一遍又一遍地收到相同的 403 消息。)

也就是说,404 不适用于此,因为资源可用 - 只是代码不可兑换/禁止兑换。它实际上是有害的,因为它告诉用户您可能在 URL 链接或服务器配置中犯了错误。

当然,这假设您在适当的日期返回 200。

【讨论】:

  • 反对者,你能解释一下吗?这对我来说似乎是一个合理的答案
  • 我不是反对者,但我的理解是请求按原样(即 UA 发送的参数和标头)不应重复;也就是说,无论发送多少次完全相同的请求,除了 403 之外,它永远不会得到任何东西。“该请求被禁止;请尝试另一个”——诸如此类的事情。
  • 这个“答案”并不是真正的答案,它四处游荡而不清晰。前两句真的应该是问题上的cmets。此外,它并没有真正提供问题的答案。所以我认为反对票是应得的,我正在添加另一个。
  • @Len:是的。然而,W3C 403 PageRichardson & Ruby 写的关于 403 的内容之间似乎存在一些紧张关系:“这更像是一种只能在特定时间或从特定 IP 地址访问的资源。”考虑到这一点,客户端可以稍后发出完全相同的请求并获得成功 (2xx) 的结果。
  • 你说得对,这更多地是作为 cmets 而不是直接答案。但是我还没有评论的声誉,所以我不得不把它们放在一个答案中。如果它提供相关信息但不是错误答案,我不明白你为什么会投反对票?
猜你喜欢
  • 2022-11-03
  • 2017-03-23
  • 2012-01-21
  • 2016-05-01
  • 2017-12-21
  • 1970-01-01
  • 1970-01-01
  • 2015-05-26
  • 2018-04-13
相关资源
最近更新 更多