我的情况是用户在非常短的时间内发送多个并行请求,包括GET和POST请求。我们拥有健康的用户代理组合,但只有iOS客户端才会导致重复。用户代理似乎是非标准的。我试图找到具有类似用户代理的浏览器,我唯一能找到的是Ghostery(隐藏浏览器/版本),但我不能复制观察到的行为。以下是过去一周左右收集的用户代理字符串列表:
Mozilla/5.0 (iPhone; CPU iPhone OS 9_3_2 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Mobile/13F69
Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_1 like Mac OS X) AppleWebKit/603.1.30 (KHTML, like Gecko) Mobile/14E304
Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_2 like Mac OS X) AppleWebKit/603.2.4 (KHTML, like Gecko) Mobile/14F89
Mozilla/5.0 (iPhone; CPU iPhone OS 10_3 like Mac OS X) AppleWebKit/603.1.30 (KHTML, like Gecko) Mobile/14E277
Mozilla/5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Mobile/13B143
如上所述,这些可以产生并行请求,甚至包括当请求导致302重定向时,每个重定向都被遵循。我们通常会注意到这种行为,因为我们会因为尝试创建具有重复用户名的用户而导致数据库完整性错误,这显然是因为其中一个并行请求成功,而另一个失败。其中一个最复杂的例子是来自我们的apache日志的这一串请求:
[19/May/2017:12:18:01 +0000] "GET /product/1/ HTTP/1.0" 200
[19/May/2017:12:18:12 +0000] "POST /product/1/ HTTP/1.0" 302
[19/May/2017:12:18:12 +0000] "GET /en/queue/buy/1862/ HTTP/1.0" 302
[19/May/2017:12:18:12 +0000] "GET /en/queue/buy/1862/ HTTP/1.0" 302
[19/May/2017:12:18:12 +0000] "GET /queue/buy/1862/ HTTP/1.0" 302
[19/May/2017:12:18:12 +0000] "GET /en/queue/buy/1862/ HTTP/1.0" 302
[19/May/2017:12:18:12 +0000] "GET /queue/buy/1862/ HTTP/1.0" 302
[19/May/2017:12:18:12 +0000] "GET /queue/buy/1862/ HTTP/1.0" 302
[19/May/2017:12:18:12 +0000] "GET /queue/buy/1862/ HTTP/1.0" 500
[19/May/2017:12:18:12 +0000] "GET /en/purchasing/buy/ HTTP/1.0" 302
[19/May/2017:12:18:12 +0000] "GET /en/purchasing/buy/ HTTP/1.0" 302
[19/May/2017:12:18:12 +0000] "GET /en/purchasing/buy/ HTTP/1.0" 302
[19/May/2017:12:18:12 +0000] "GET /purchasing/buy/ HTTP/1.0" 302
[19/May/2017:12:18:12 +0000] "GET /purchasing/buy/ HTTP/1.0" 302
[19/May/2017:12:18:12 +0000] "GET /purchasing/buy/ HTTP/1.0" 302
[19/May/2017:12:18:13 +0000] "GET /purchasing/orders/ HTTP/1.0" 200
[19/May/2017:12:18:13 +0000] "GET /purchasing/orders/ HTTP/1.0" 200
[19/May/2017:12:18:13 +0000] "GET /purchasing/orders/ HTTP/1.0" 200
此流程的开始将要求用户按下Buy
按钮,其中包括JS以禁用点击按钮,以减少双击的可能性。如果没有启用JS,表单本身就不会加载,因此我们可以确保在浏览器上启用了JS。
请注意,请求之间的差距几乎不存在,最初实际上有4个并行请求。其中一个响应HTTP 500响应,但是其中3个并行请求返回302,并且所有请求都会一直跟踪到最终的200响应。
在这种情况下,用户继续合法地完成购买,因此我认为不会有任何有趣的业务。
所以我真的不确定如何处理这个问题。我猜我只是需要接受iOS客户端会发生这种情况。但我无法复制这个问题,我担心在某些情况下可能会导致糟糕的用户体验。
更新
我更新了请求列表,以包含用于加载表单的GET的初始入口点,以及用于提交表单的POST。请注意,在此实例中仅收到一个POST,但重定向似乎已被跟踪4次。
这是初始提交中涉及的HTML / JS:
HTML:
<form method="post" action="/product/1/" id="buy_form">
...
<button type="submit" id="buy_btn">Buy Now</button>
</form>
JS:
$("#buy_form").submit(function(){
$("#buy_btn").prop('disabled', true);
});