首页 > 解决方案 > curl_multi 没有运行第二个请求

问题描述

我正在尝试使用 curl_multi 将数据发送到两个不同的 URL,并从其中一个 URL 的响应中获取 URL 并重定向用户。

到目前为止,除了第二个请求没有被处理外,一切正常。

这是我的代码:

// create both cURL resources
$ch1 = curl_init();
$ch2 = curl_init();

// set URL and other appropriate options
//--------------------------CH1
curl_setopt_array($ch1, array(
  CURLOPT_URL => "https://my.crm.com/api/signup",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_ENCODING => "",
  CURLOPT_MAXREDIRS => 10,
  CURLOPT_TIMEOUT => 30,
  CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  CURLOPT_CUSTOMREQUEST => "POST",
  CURLOPT_POSTFIELDS => '{"userip":"'.$_REQUEST['ip'].'","firstname":"'.$_REQUEST['firstname'].'", "lastname":"'.$_REQUEST['lastName'].'", "email":"'.$_REQUEST['email'].'", "password":"'.$_REQUEST['password'].'", "phone":"'.$_REQUEST['phonenumber'].'", "prefix":"'.$_REQUEST['phonecode'].'" }', 
)); 
//-------------------------CH2
curl_setopt_array($ch2, array(
  CURLOPT_URL => "https://my2.crm2.com/api/signup",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_ENCODING => "",
  CURLOPT_MAXREDIRS => 10,
  CURLOPT_TIMEOUT => 30,
  CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  CURLOPT_CUSTOMREQUEST => "POST",
  CURLOPT_POSTFIELDS => '{"userip":"'.$_REQUEST['ip'].'","firstname":"'.$_REQUEST['firstname'].'", "lastname":"'.$_REQUEST['lastname'].'", "email":"'.$_REQUEST['email'].'", "password":"'.$_REQUEST['password'].'", "phone":"'.$_REQUEST['phonenumber'].'", "prefix":"'.$_REQUEST['phonecode'].'" }', 
)); 

//create the multiple cURL handle
$mh = curl_multi_init();

//add the two handles
curl_multi_add_handle($mh,$ch1);
curl_multi_add_handle($mh,$ch2);

// While we're still active, execute curl
$active = null;
do {
    $mrc = curl_multi_exec($mh, $active);
} while ($mh == CURLM_CALL_MULTI_PERFORM);

while ($active && $mrc == CURLM_OK) {
    // Wait for activity on any curl-connection
    if (curl_multi_select($mh) == -1) {
        continue;
    }

    // Continue to exec until curl is ready to
    // give us more data
    do {
        $mrc = curl_multi_exec($mh, $active);
    } while ($mrc == CURLM_CALL_MULTI_PERFORM);
}

//close the handles
curl_multi_remove_handle($mh, $ch1);
curl_multi_remove_handle($mh, $ch2);
curl_multi_close($mh);

//responses

$response1 = curl_multi_getcontent($ch1);
$response2 = curl_multi_getcontent($ch2);

//read response and redirect
$json_array = json_decode($response1, true);
$loginurl = $json_array['data'];
header("Location: $loginurl");

我尝试了不同的解决方案,但我仍然无法让第二个请求 ($ch2) 工作。

标签: phpcurlresponse

解决方案


你的代码有几个问题,但我怀疑你没有得到内容#2,因为你在获取结果之前关闭了 multi_handle ......事实上,我很惊讶你得到第一个内容,甚至。

但首先我想抱怨这个:

curl_setopt_array($ch1, array(
    CURLOPT_URL => "url",
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_ENCODING => "",
    CURLOPT_MAXREDIRS => 10,
    CURLOPT_TIMEOUT => 30,
    CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
    CURLOPT_CUSTOMREQUEST => "POST",
    CURLOPT_POSTFIELDS => '{"userip":"' . $_REQUEST['ip'] . '","firstname":"' . $_REQUEST['firstname'] . '", "lastname":"' . $_REQUEST['lastName'] . '", "email":"' . $_REQUEST['email'] . '", "password":"' . $_REQUEST['password'] . '", "phone":"' . $_REQUEST['phonenumber'] . '", "prefix":"' . $_REQUEST['phonecode'] . '" }',
));

1:使用 CURLOPT_POST,而不是 CURLOPT_CUSTOMREQUEST(一方面,这是正确的做法,libcurl 实际上明白你想要一个 POST 请求,而不是一些非标准的请求)

$_REQUEST['password']2:如果包含,您认为会发生"什么?它会破坏你的json,使其无法解析......

3:通过操纵 $_REQUEST['password'] (或那里的任何其他变量),您的代码容易受到 JSON 注入的攻击,黑客可以例如欺骗他们的 IP,提供假的userip(如果您不知道 JSON 注入是什么,它有点像SQL Injection,但它们可以注入 JSON 数据(如欺骗的用户 IP)而不是 SQL 命令,看起来像 {"data":"real_data","data":"evil_hacker_injected_version_of_data_that_will_replace_it_because_it_is_the_last_definition_of_data"} :)

使用 json_encode() 安全地创建您的 json,如下所示:

curl_setopt_array($ch1, array(
    CURLOPT_URL => "url",
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_ENCODING => "",
    CURLOPT_MAXREDIRS => 10,
    CURLOPT_TIMEOUT => 30,
    CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
    CURLOPT_POST => 1,
    CURLOPT_POSTFIELDS => json_encode(array(
        'userip' => (string) $_REQUEST['ip'],
        'firstname' => (string) $_REQUEST['firstname'],
        'lastname' => (string) $_REQUEST['lastName'],
        'email' => (string) $_REQUEST['email'],
        'password' => (string) $_REQUEST['password'],
        'phone' => (string) $_REQUEST['phonenumber'],
        'prefix' => (string) $_REQUEST['phonecode'],
    ))
));

... 和这里

do {
    $mrc = curl_multi_exec($mh, $active);
} while ($mh == CURLM_CALL_MULTI_PERFORM);

您正在检查错误的值, $mh 是 NEVER CURLM_CALL_MULTI_PERFORM ,您想将其与 $mrc 进行比较,而不是 $mh (libcurl 开发人员还删除了 CURLM_CALL_MULTI_PERFORM ,因为很多人用错了它,这发生在几年前,现代代码不再需要它。)

除此之外,我根本不喜欢你实现循环的方式..试试这个:

while (1) {
    do {
        $mrc = curl_multi_exec($mh, $active);
    } while ($mrc == CURLM_CALL_MULTI_PERFORM);
    if (!$active) {
        break;
    }
    curl_multi_select($mh);
}

但话虽如此,我相信你真正的问题是你在调用 curl_multi_getcontent() 之前运行 curl_multi_remove_handle() 和 curl_multi_close()。


推荐阅读