Search code examples
phpapicurlproxmox

Stop foreach loop when curl return 200


I try to communicate with my Proxmox cluster which contain 3 servers, from API. Goal is to connect to at least 1 of these servers in case of failure then execute other code (not visible here).

With the below code, I connect to these servers 1 by 1 using "foreach" and I want this loop stop when one server return "200" from Curl (so I can continue with this online server). For the test, I stopped the first server and let online the others 2 but the "foreach" loop keep connect the third server.

Any idea ? Thank you and sorry for my english.

<?php

$datas = array(
    array(
        "apiurl" => "192.168.1.34:8006",
        "node" => "pve1",
        "user" => "root",
        "userpass" => "pass",
    ),
    array(
        "apiurl" => "192.168.1.35:8006",
        "node" => "pve2",
        "user" => "root",
        "userpass" => "pass",
    ),
    array(
        "apiurl" => "192.168.1.36:8006",
        "node" => "pve3",
        "user" => "root",
        "userpass" => "pass",
    )
);

do {
    foreach ($datas as $data) {
        $ch = curl_init();

        curl_setopt($ch, CURLOPT_URL, 'https://'.$data['apiurl'].'/api2/json/access/ticket');
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, 'username='.$data['user'].'@pam&password='.$data['userpass']);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
        curl_setopt($ch, CURLOPT_TIMEOUT, 2);

        $headers = array();
        $headers[] = 'Content-Type: application/x-www-form-urlencoded';

        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

        $result = curl_exec($ch);

        if (curl_errno($ch)) {
            echo 'Server ' .$data['node']. ' is not reachable (error : ' .curl_error($ch). ')<br>';
        }
        else {
            $myArray = json_decode($result, true);
            $cookie = $myArray['data']['ticket'];
            $info = curl_getinfo($ch);
            echo "Server " .$data['node']. " is reachable (code is : " .$info['http_code']. ")<br>";
        }
    curl_close($ch);
    }
} while ($info['http_code'] !== 200);
?>

Solution

  • You can break out of an outer loop by giving an argument to break. break 2 means to break out of the second containing loop.

    while (true) {
        foreach ($datas as $data) {
            $ch = curl_init();
    
            curl_setopt($ch, CURLOPT_URL, 'https://'.$data['apiurl'].'/api2/json/access/ticket');
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
            curl_setopt($ch, CURLOPT_POST, 1);
            curl_setopt($ch, CURLOPT_POSTFIELDS, 'username='.$data['user'].'@pam&password='.$data['userpass']);
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
            curl_setopt($ch, CURLOPT_TIMEOUT, 2);
    
            $headers = array();
            $headers[] = 'Content-Type: application/x-www-form-urlencoded';
    
            curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    
            $result = curl_exec($ch);
    
            if (curl_errno($ch)) {
                echo 'Server ' .$data['node']. ' is not reachable (error : ' .curl_error($ch). ')<br>';
            }
            else {
                $myArray = json_decode($result, true);
                $cookie = $myArray['data']['ticket'];
                $info = curl_getinfo($ch);
                echo "Server " .$data['node']. " is reachable (code is : " .$info['http_code']. ")<br>";
                if ($info['http_code'] == 200) {
                    break 2;
                }
            }
            curl_close($ch);
        }
    }