繁体   English   中英

当两个发布请求都到达服务器时,在php中处理重试发布请求

[英]Handling retry post requests in php, when both post requests reach the server

我的php应用程序的用户有时会不小心意外地两次提交消息或其他操作。 这似乎是由于响应时间过长(例如由于不良的网络连接)导致(移动)客户端自动重试请求而导致的问题。 我的服务器虽然处理两个请求并将它们作为单独的动作进行处理。

如何处理此类重试发布请求,而又不禁用发送故意重复发布请求的可能性? 因此,如何区分这些重试和故意将同一请求的用户发送重发?

有一点上下文可以帮助您理解问题:我正在运行一个基于html的老式学校浏览器游戏。 用户可能想通过页面刷新巧妙地重新发送完全相同的操作(例如“攻击”),并且我不想削减此选项,因为它确实很方便。 但是我想通过客户端自动发送两次后发请求而不先询问用户来防止意外的双重操作。 我不确定它是否是特定于移动浏览器的问题。

您正在专注于问题的错误结局。 如果用户发送了两次帖子,则可能是因为他们没有看到回复。 是的,您仍然需要在服务器端进行规划和处理问题,但是在客户端上解决该问题不仅会减少返回服务器的次数,还可以改善用户体验。

前端的实时更新意味着使用JavaScript。 另外,在使用触摸设备时,默认情况下,延迟时间约为三分之一秒,除非您明确禁用某些触摸功能。

我认为这应该做您想要的事情,并且至少应该给您这个主意-它最初是一个较大的帖子的一部分, 防止实际两次提交的角度出发停止html的多个提交

再次查看它,希望您对自己的要求太高,所以这里是它的替代版本。 您可能想要重新实现对Submit按钮的禁用,但是您似乎实际上希望连续地对其进行启用,因此为了清楚起见,在此删除了该代码。

您可能需要调整计数-不确定会发生多少次自动提交-就目前而言,这将占一个,但是在下一次“实际”提交之前,它将不接受任何内容。

那时,PHP代码可以按照“您真的提交了两次吗?”这一行请求用户干预。 或者它可以简单地忽略提交。 根据@symcbean的建议,JavaScript可以在完全重新提交之前要求确认,JavaScript也是这样-皮带和括号始终是个好主意! 如果在仍提交时单击,则应选择故意提交两次或取消。

据我所知,如果您注释掉keyPress事件submit_this(); 要求按F5键,它将不接受F5提交以进行刷新。 -当keyPress功能起作用时,按F5即可提交,而不会出现通常的确认警告,您将得到刷新。

我已经进行了测试,但是只能等待您的确认,以查看它是否也可以自动重新提交。 如果单击浏览器刷新按钮,则PHP不接受提交。 也不接受由Ctrl+R刷新产生的提交。 希望这反映了重新提交的情况。 我回退了警报,使单击速度比提交页面时快,因为无法确定确认/取消是否有效。 您可以尝试一下!

<?php   
session_start();
if (!isset($_POST['hidden_input'])) $hidden_input = 1;
if (!isset($_SESSION['submit_count_input'])) $_SESSION['submit_count_input'] = -1;
if (isset($_POST['hidden_input'])) $hidden_input = intval($_POST['hidden_input']);

// detect difference between JavaScript submitted value and possible automatic ones
if (($hidden_input - $_SESSION['submit_count_input']) == 1){
    // do your processing here 
    //$submit_count_input should always be 1 behind
    echo "Thank you. Form processed";
    }else{
    // correct the balance between $hidden_input and $submit_count_input
    $_SESSION['submit_count_input'] = ($hidden_input - 1); // will be incremented so will be -1 effectively
    echo "Form not processed.";
}    
// remove this echo section - just for testing
echo " Control Token: " . $hidden_input . " ";
echo " Submit Count: " . $_SESSION['submit_count_input']; // to show it submits but does not process form

$_SESSION['submit_count_input']++; 
?>
<!DOCTYPE html>
  <html>
    <head>
    <script language="javascript">
    document.onkeydown=function(e) {
        var event = window.event || e;
        if (event.keyCode == 116) {
        event.keyCode = 0;
           submit_this();
           return false;
        }
    }

function submit_this(){
    if(document.getElementById('submit_count_input').value - document.getElementById('hidden_input').value == -1) {
        // Warning when submit clicked before previous submission finished confirm/cancel option as per link below could be used
    alert("Easy Tiger - please slow down a bit!");
    }else{
    document.getElementById('hidden_input').value = 1+parseInt(document.getElementById('hidden_input').value);
    document.form.submit();
    }
}
    </script>
    </head>
    <body>

      <form name="form" id="form" action="<?php echo htmlspecialchars($_SERVER['PHP_SELF']) ?>" method="post">   
      <input type="hidden" name="hidden_input" id="hidden_input" value="<?php echo $hidden_input ?>" />
      <input type="hidden" name="submit_count_input" id="submit_count_input" value="<?php echo intval($_SESSION['submit_count_input']) ?>" />

      <input type="button" name="sbutton" id="sbutton" value="Submit" onclick="submit_this();" />
      </form>

      <a href="<?php echo htmlspecialchars($_SERVER['REQUEST_URI']); ?>">Click to start a new submission</a>

    </body>
   </html>

确认/取消JavaScript对话框JavaScript确认取消按钮不会停止JavaScript

关于将值保留在提交的表单中而没有会话的第二个问题,那么即使您使用value="<?php echo htmlspecialchars($_POST['form_element_name_value'] ?>"在每个表单文本框元素的值中。请确保每个文本框都有一个name="something"供php以$_POST -很抱歉。

为了满足用户使用F5提交页面的愿望,您可以捕获功能并将其转换为实际的提交,但这可能是一个讨厌的想法,尽管它确实起作用了……而且它将保留PHP端提供了已提交的数据,对于失败的连接,仍然可以将其与自动重新提交区分开。

    document.onkeydown=function(e) {
        var event = window.event || e;
        if (event.keyCode == 116) {
        event.keyCode = 0;
        submit_this();
        return false;            }
    }

要捕获浏览器上的实际刷新按钮,您可以查看以下方法: 如何知道在Firefox中是单击刷新按钮还是浏览器后退按钮,但是颠覆浏览器行为以强制给定用户体验,这是人们普遍反对的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM