PHP-如果curl需要超过15秒,请执行操作

时间:2017-07-13 15:32:06

标签: php curl

我正在向API发送测试卷曲请求,以测试接收数据并在进程持续超过15秒时取消请求。问题是30秒后数据返回,我必须检查等待它是否需要超过15秒。这是我做的:

for($x=0; $x<$quantity; $x++){
$xmlRequest = "<?xml version='1.0' encoding='utf-8'?>
<REQUEST TYPE='PINPRINTING' MODE='DIRECT'>
<AMOUNT>" . $amount . "</AMOUNT>
<PRODUCTID>" . $comp_id . "</PRODUCTID>
<USERNAME>Username</USERNAME>
<PASSWORD>Password</PASSWORD>
</REQUEST>";

 $url = "URL-HERE";
 $headers = array(
     "Content-type: text/xml;charset=\"utf-8\"",
     "Accept: text/xml",
     "Cache-Control: no-cache",
     "Pragma: no-cache",
     "SOAPAction: \"run\""
 );

 try {
      $ch = curl_init();
      curl_setopt($ch, CURLOPT_URL, $url);
      curl_setopt($ch, CURLOPT_POST, 1);
      curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
      curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
      curl_setopt($ch, CURLOPT_POSTFIELDS, $xmlRequest);
      curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
      curl_setopt($ch, CURLOPT_VERBOSE, 0);
      curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
      $data = curl_exec($ch);

      $now = time();
      $later =  time();
      for($i=1; $i<16; $i++){

          if(!is_array($data)){
             sleep(1);
             $later += $i;
             if( ($later - $now) >= 15 ){
                echo $now.'<br>'.$later.'<br>';
                echo '<p>It passed 15 seconds</p>';
                $xmlRequest1 = "<?xml version='1.0' encoding='utf-8'?>
                <REQUEST TYPE='CANCEL'>
                <AMOUNT>" . $amount . "</AMOUNT>
                <PRODUCTID>" . $comp_id . "</PRODUCTID>
                <USERNAME>Username</USERNAME>
                <PASSWORD>Password</PASSWORD>
                </REQUEST>";

                $headers = array(
                            "Content-type: text/xml;charset=\"utf-8\"",
                            "Accept: text/xml",
                            "Cache-Control: no-cache",
                            "Pragma: no-cache",
                            "SOAPAction: \"run\""
                        );

                try {
                     $ch1 = curl_init();
                     curl_setopt($ch1, CURLOPT_URL, $url);
                     curl_setopt($ch1, CURLOPT_POST, 1);
                     curl_setopt($ch1, CURLOPT_SSL_VERIFYHOST, 0);
                     curl_setopt($ch1, CURLOPT_SSL_VERIFYPEER, 0);
                     curl_setopt($ch1, CURLOPT_POSTFIELDS, $xmlRequest1);
                     curl_setopt($ch1, CURLOPT_RETURNTRANSFER, 1);
                     curl_setopt($ch1, CURLOPT_VERBOSE, 0);
                     curl_setopt($ch1, CURLOPT_HTTPHEADER, $headers);
                     $data = curl_exec($ch1);
                     print_r($data);
                     curl_close($ch1);
                    }
                    catch (Exception  $e) {
                          echo 'error occurred<br>';
                         echo 'Message: ' . $e->getMessage();
                       }
                        die('Error');
                    }
                }

                else{
                    if ($data === false) {
                        $error = curl_error($ch);
                        echo $error;
                        die('error occurred');
                    }

                    else {
                        $data = json_decode(json_encode(simplexml_load_string($data)), true);

                        if($data['RESULTTEXT'] == 'transaction successful'){
                            print_r($data);
                        }

                        else{
                            echo "Error: ".$data['RESULTTEXT']."<p>";
                        }

                    }
                }

            }

            curl_close($ch);

        }

        catch (Exception  $e) {
            echo '<p>Message: ' . $e->getMessage();
            die("Error");
        }
}

我创建了一个内部循环,每秒检查一次,如果$ data不是一个发送取消请求的数组,但问题是它会等待30秒(整个时间过程来获取数据,即使它无效)而不是15秒。

我想要做的是每隔15秒检查一次是否收到数据。如果没有收到,它应该发送取消请求,而不必等待整个30秒,如果有效则不发送请求15次,所以如果有数据应该只执行一次并退出内部循环继续外循环( for(x = 0)...)

1 个答案:

答案 0 :(得分:0)

看着你的代码,你显然都错了。你尝试发送页面的开头 - 页面加载前的起始卷曲,并在页面上发送不同的内容,这取决于使用的滚动曲线+15秒或不 - 你将运行各种浏览器特定的(和特定于Web服务器的配置)缓存该方法的问题。一个更好的方法是使用一些带有一些javascript的页面启动/停止按钮来控制Ajax(XMLHttpRequest)启动/停止curl请求。

这是一个例子, a.html - 包含GUI控件和javascript,它计算已经过了多少秒,并允许您在认为它已经过长时间时中止(例如,在15秒后中止)

<input id="startRequest" type="button" value="start request" /><br/>
<input id="abortRequest" type="button" value="abort request" /><br/>
seconds running: <span id="runtimeCounter">not started yet</span><br/>
<span id="response">the xhr response will be added here by javascript</span>
<script>
window.xhr;
function count(){
    var xhr=window.xhr;
    var ele=document.querySelector("#runtimeCounter");
    if(!xhr.aborted && xhr.readyState<4){
        ele.textContent=Number(ele.textContent)+1;
    }else{
        ele.textContent+=" completed!";
        clearTimeout(window.count.clearid);
    }
}
document.querySelector("#startRequest").addEventListener("click",function(){
    document.querySelector("#runtimeCounter").textContent=0;
    var xhr=window.xhr=new XMLHttpRequest();
    xhr.open("POST","xhr.php");
    xhr.addEventListener("progress",function(ev){
        var xhr=ev.target;
        document.querySelector("#response").textContent=xhr.responseText;
    });
    xhr.send();
    window.count.clearid=setTimeout(count,1000);
});
document.querySelector("#abortRequest").addEventListener("click",function(){
    var xhr=window.xhr;
    xhr.abort();
    xhr.aborted=true;
    document.querySelector("#runtimeCounter").textContent+=" - aborted";
});

</script>

和xhr.php,实际上是卷曲的东西:

for($x = 0; $x < $quantity; ++$x) {
    $xmlRequest = "<?xml version='1.0' encoding='utf-8'?>
<REQUEST TYPE='PINPRINTING' MODE='DIRECT'>
<AMOUNT>" . $amount . "</AMOUNT>
<PRODUCTID>" . $comp_id . "</PRODUCTID>
<USERNAME>Username</USERNAME>
<PASSWORD>Password</PASSWORD>
</REQUEST>";

    $url = "URL-HERE";
    $headers = array (
            "Content-type: text/xml;charset=\"utf-8\"",
            "Accept: text/xml",
            "Cache-Control: no-cache",
            "Pragma: no-cache",
            "SOAPAction: \"run\"" 
    );

    try {
        $ch = curl_init ();
        curl_setopt ( $ch, CURLOPT_URL, $url );
        curl_setopt ( $ch, CURLOPT_POST, 1 );
        curl_setopt ( $ch, CURLOPT_SSL_VERIFYHOST, 0 );
        curl_setopt ( $ch, CURLOPT_SSL_VERIFYPEER, 0 );
        curl_setopt ( $ch, CURLOPT_POSTFIELDS, $xmlRequest );
        curl_setopt ( $ch, CURLOPT_RETURNTRANSFER, 0 );
        curl_setopt ( $ch, CURLOPT_VERBOSE, 0 );
        curl_setopt ( $ch, CURLOPT_HTTPHEADER, $headers );
        $data = curl_exec ( $ch );
        curl_close ( $ch );
    } catch ( Exception $e ) {
        echo '<p>Message: ' . $e->getMessage ();
        die ( "Error" );
    }
}

请注意我如何将CURLOPT_RETURNTRANSFER设置为0,因为这允许javascript在进展时监控下载 - 而不是像最后一样发送所有内容,如RETURNTRANSFER必须这样做(它还节省了服务器ram btw,因为下载的内容是只是存储,直到它被发送到客户端,分批,并丢弃,而不是将所有内容存储在RAM中直到100%下载)

  • 请注意,此方法是使用PHP的ignore_user_abort行为(ab?),如果在xhr.php中执行ignore_user_abort(true);,则中止按钮将不起作用