【问题标题】:Providing parameters to a RESTful POST request that requires confirmation向需要确认的 RESTful POST 请求提供参数
【发布时间】:2016-06-14 21:15:18
【问题描述】:

我正在开发一个 REST 服务,我的一个服务器端操作以一种可能需要一段时间的方式操作数据库,但是一旦操作开始,数据库就无法恢复(这是来自我们在服务器上使用的系统。我也许可以在以后的版本中更改它,但现在我们被这个限制所困扰)。 结果是在允许操作运行之前,我需要一个带有警告的“确定/取消”对话框。

起初我想将创建对话框的逻辑放在客户端,但这似乎违反了 HATEOAS(例如,如果我确实更改了服务器端的框架,则不需要对话框,但如果我的 API 保持不变,我不想更改客户端)。 我的下一个解决方案是返回带有警告的响应,以及链接到不同 POST 操作的 ok,但我不确定何时发送参数。我是否在第一个 POST 中发送参数?如果是这样,他们如何到达第二个 POST(当然,不保持应用程序状态)?仅将参数发送到第二个 POST 不是一种选择,因为只有 HATEOAS 会确定是否需要第二个。

我在这里发现了一个类似的问题: REST, HTTP DELETE and parameters 但这有两个问题:

  1. 它并没有解决我们的问题(因为他只是在第二次尝试时添加了一个参数,但我需要从第一次开始携带我的参数)。
  2. DELETE 必须符合“统一接口”。 他确实提出了一个有效的观点,即并非所有客户端都一定需要确认,但是将整个对话框放在 UI 中让我回到了我们的问题,即如果我改进我的服务器端应用程序会发生什么。

我很高兴听到您对此事的看法。

PS:这是我在 stackoverflow.com 上的第一篇文章(经过多年使用它来寻找我之前提出的问题的答案),所以如果问题的格式不太正确,请原谅我(你是当然,欢迎纠正我)。

【问题讨论】:

  • 您可以生成一个令牌来“确认”或授权删除。例如,POST /confirmations 返回带有确认实体的 201。然后通过 HTTP 标头将所述实体传递给DELETE /users/1
  • 您可以先发出请求以获取令牌,然后当您在第二次请求时发送该令牌时,操作就会发生。

标签: rest


【解决方案1】:

您的服务器端操作之一需要确认才能执行。在我看来,这意味着两个不同的调用,例如,这可能意味着首先检查您是否需要确认,然后执行实际操作。

例如,您可以请求客户端首先执行 GET 以查看是否需要确认并检索要显示的消息,然后执行实际的 POST 操作。如果您没有先收到 GET 请求,则 POST 可能会返回 4xx(可能是 412?)错误。

但是,请记住,无论您做什么,都需要客户的配合。即使服务器确实收到了 GET 请求,客户端也可能会收到响应,不显示确认并进行发布,这不是您可以 100% 解决服务器端的问题。

【讨论】:

    【解决方案2】:

    我不会修改DELETE 的语义,就像链接文章中的解决方案之一(返回4xx 以强制执行新请求)。大多数人会惊讶于DELETE 不起作用,应尽可能避免出现意外。

    我的第一个想法是,您可以像 HTML 中的确认对话框一样解决它。那就是在链接中加入一些代码,或者一些标志来表明它需要确认才能删除:

    <a rel="something" onDelete="confirm" href="..."/>
    <a rel="something" onDelete="showConfirmation()" href="..."/>
    

    起初这看起来不错,但这真的是链接的属性吗?好吧,阅读您对问题的描述,您似乎正在定义POST 操作本身的一些能力 是否存在。这个能力是可恢复性还是可回滚性?因此,如果客户端需要检测某个操作的某些功能,它可以像这样使用OPTIONS 请求:

    OPTIONS /something/abc HTTP/1.1
    ...
    
    200 OK
    Allow: GET,HEAD,POST,OPTIONS,TRACE
    ...
    <body describing confirmation dialogs, messages, etc>
    

    所以基本上你可以通过OPTIONS 的自定义表示来宣布该功能。规范明确允许这样做 (https://www.rfc-editor.org/rfc/rfc7231#section-4.3.7):

    生成对 OPTIONS 的成功响应的服务器应该发送任何 标头字段可能指示由实现的可选功能 服务器并适用于目标资源(例如,允许), 包括本规范未定义的潜在扩展。

    【讨论】:

      【解决方案3】:

      是否需要一次性服务器端生成的令牌来执行关键操作?所以客户端总是需要首先触发另一个非关键请求来获取令牌。只能使用该令牌进行关键调用。因此,在这种情况下,获取令牌是启动的行为,将令牌发送到关键端点是确认。

      操作所需的所有详细信息都应与第一个请求一起发送,因此令牌只会确认该特定参数集。在第二个请求中只需要令牌,操作所需的任何其他参数必须已经发送并在令牌中/由令牌编码或标识。

      这样,客户端不会在没有明确请求的情况下意外调用关键请求或使用另一个令牌来确认不相关的操作,这在某种意义上是一种确认,因为单个“错误”不会导致意外结果。

      当然,客户端可能仍然决定在不提示用户的情况下执行两轮,但我们无能为力。

      【讨论】:

      • 我刚刚注意到 jchook 在上面的评论中说了同样的想法......
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-01-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多