Zep*_*ock 11 api rest networking ruby-on-rails
假设我们在不可靠的网络上发生客户端/服务器交互(数据包丢弃).客户端正在调用服务器的RESTful api(通过http over tcp):
我看到以下问题:客户端永远不会获得新创建的资源的ID,但服务器将创建资源.
问题:这个应用程序级别的行为或框架应该处理这个问题吗?Web框架(特别是Rails)应该如何处理这种情况?关于此主题,是否有关于REST的文章/白皮书?
当服务器不响应POST时,客户端将收到错误.然后,客户端通常会重新发出请求,因为他们认为该请求已失败.在我的头脑中,我可以想到两个解决这个问题的方法.
一个是客户端可以生成某种请求标识符,例如guid,它包含在请求中.如果服务器收到带有重复GUID的POST请求,则它可以拒绝它.
另一种方法是PUT而不是POST来创建.如果您无法让客户端生成URI,那么您可以要求服务器提供带有GET的新URI,然后对该URI执行PUT.
如果您搜索"make POST idempotent"之类的内容,您可能会找到一些关于如何执行此操作的其他建议.
如果创建重复资源不合理(例如,具有相同标题、描述等的产品),则可以在服务器上生成唯一标识符,可以根据创建的资源对其进行跟踪,以防止处理重复请求。与Darrel 在客户端上生成唯一 ID 的建议不同,这还可以防止单独的用户创建重复的资源(您可能会或可能不希望这样做)。客户端将能够通过响应代码(在下面的示例中分别为 201 和 303)来区分“创建”响应和“重复”响应。
\n\n用于生成此类标识符 \xe2\x80\x94 的伪代码(在本例中)是请求的规范表示的哈希值:
\n\nfunc product_POST\n // the canonical representation need not contain every field in\n // the request, just those which contribute to its "identity"\n tags = join sorted request.tags\n canonical = join [request.name, request.maker, tags, request.desc]\n id = hash canonical\n\n if id in products\n http303 products[id]\n else\n products[id] = create_product_from request\n http201 products[id]\n end\nend\nRun Code Online (Sandbox Code Playgroud)\n\n此 ID 可能是也可能不是所创建资源的 URI 的一部分。就我个人而言,如果 URI 要向用户公开,我倾向于单独跟踪它们 \xe2\x80\x94,但需要额外的查找表 \xe2\x80\x94,因为哈希值往往很难看,而且人类很难记住。
\n\n在许多情况下,在一段时间后让这些独特的哈希值“过期”也是有意义的。例如,如果您要开发一个转账 API,则用户在几分钟内向同一个人转账相同金额的资金可能表明客户端从未收到“成功”响应。另一方面,如果用户每月向同一个人转账一次相同金额的钱,他们可能正在支付租金。;-)
\n