restapi的干运行策略

restapi的干运行策略,rest,Rest,我正在寻找RESTAPI的“干运行”操作的一些最佳实践 假设我有一个端点可以将资金从帐户A转移到帐户B。我可以像这样发起转移: POST /transactions { "amount": 1000, // how much to transfer "source": "A", // account to transfer from "destination": "B" // account to transfer to } 此操作将创建一个“事务”,因此响应将

我正在寻找RESTAPI的“干运行”操作的一些最佳实践

假设我有一个端点可以将资金从帐户A转移到帐户B。我可以像这样发起转移:

POST /transactions
{
  "amount": 1000,     // how much to transfer
  "source": "A",      // account to transfer from
  "destination": "B"  // account to transfer to
}
此操作将创建一个“事务”,因此响应将是一个有效负载包含以下内容的事务对象:

{
  "id": "txn-123",
  "amount": 1000,
  "source": "A",
  "destination": "B",
  "fees": 10,          // any fees that were charged
  "balance": 2500      // balance in source account AFTER transfer
}
出于以下几个原因,我希望能够进行试运行:

  • 确定转账是否会成功(例如,如果账户a余额较低,则可能会失败)
  • 事先确定适用的费用
  • 那么,“试运行”概念的最佳实践是什么?我可以想出几个选择:

  • 将标志传递给现有传输端点,以指示干运行选项。该标志可以是查询字符串、有效负载的一部分、报头等。具体的实现有待讨论,但从概念上讲,我喜欢它,因为它提供了一个干净的接口,可以让您了解有关从单个端点执行传输的所有知识
  • 专用端点专门用于执行传输干运行。这种“感觉”更安全,因为您不会无意中执行破坏性操作,因为实时和干运行端点是完全分开的。另一方面,如果你可以访问生产系统,你真的应该知道你在做什么,所以我不是一个超级粉丝
  • 无试运行概念。只需使用一组完全不同的端点来计算费用、获取余额或任何其他有助于推断转账结果的操作。我不喜欢这样,因为您强制客户机复制传输端点中已经包含的所有逻辑
    到目前为止,这些是我对这件事的看法,但我很乐意听取其他人的想法。

    选项3显然是错误的。你会无缘无故地强迫客户做额外的工作

    在选项1和2之间进行选择取决于您的品味和API的具体情况。目前还不清楚将<代码> /干运行事务> /代码>作为一种独立的事务是否合理。p>

    如果您选择了选项2,请考虑将<代码> /干运行事务< /代码>作为一个短命的资源,或者根本不坚持它。这样,客户就可以发布查看费用,并且节省存储空间

    如果使用选项1,我认为技术上最正确的选项是在有效负载中包含属性,例如
    execute:false
    。这会将所有信息返回给客户机,并允许客户机使用
    execute:true
    对事务执行PUT操作,以完全按原样提交事务。这种方法的一个缺点是会有一堆未执行的事务(永远?),因为人们会在看到结果后决定不执行它们

    我认为安全问题根本不在讨论之列。如果您真的很担心,只需将选项1的默认值设置为
    execute:false


    另一种方法可能是使用端点
    /transactions
    /transaction results
    。如果发布到
    /transaction
    ,则执行事务并获得永久事务结果的id/结果。如果您发布到/transaction results,您将得到一个没有id的响应和一组事务的临时结果。注意,我已经考虑了20秒,所以可能有一个我没有看到的明显问题。:-)

    IMHO我认为POST不应该用于干跑步。干运行具有幂等语义,因为它不改变系统的状态,这和POST相矛盾。另一方面,尽管幂等元也不是一个好的选择,因为它意味着状态改变。如果我们真的想充分休息的话,那就只剩下一个GET了。 因此,我将创建一个单独的休息点:

    GET /transactions/dry-run
    
    在URL中嵌入
    {amount,source,and target}
    ,如下所示:

    GET /transactions/dry-run?amount=100&source=A&target=B